Adding storybook tests on meta-types/display/components (#1862)

* working on a story for MoneyFieldDisplay

* Write test on MoneyDisplayField
This commit is contained in:
bosiraphael
2023-10-04 13:26:06 +02:00
committed by GitHub
parent aab2f3ab3c
commit 46dffeadef
6 changed files with 196 additions and 35 deletions

View File

@ -3,7 +3,7 @@ import { createContext } from 'react';
import { FieldDefinition } from '../types/FieldDefinition';
import { FieldMetadata } from '../types/FieldMetadata';
type GenericFieldContextType = {
export type GenericFieldContextType = {
fieldDefinition: FieldDefinition<FieldMetadata>;
// TODO: add better typing for mutation hook
useUpdateEntityMutation: () => [(params: any) => void, any];

View File

@ -0,0 +1,35 @@
import {
FieldContext,
GenericFieldContextType,
} from '@/ui/field/contexts/FieldContext';
type FieldDisplayContextProviderProps = {
children: React.ReactNode;
fieldDefinition: GenericFieldContextType['fieldDefinition'];
entityId?: string;
};
export const FieldDisplayContextProvider = ({
children,
fieldDefinition,
entityId,
}: FieldDisplayContextProviderProps) => {
return (
<FieldContext.Provider
value={{
entityId: entityId ?? '1',
recoilScopeId: '1',
hotkeyScope: 'hotkey-scope',
fieldDefinition,
useUpdateEntityMutation: () => [
() => {
return;
},
{},
],
}}
>
{children}
</FieldContext.Provider>
);
};

View File

@ -0,0 +1,112 @@
import { useEffect } from 'react';
import { Meta, StoryObj } from '@storybook/react';
import { v4 } from 'uuid';
import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
import { CatalogStory } from '~/testing/types';
import { useMoneyField } from '../../../hooks/useMoneyField';
import { MoneyFieldDisplay } from '../MoneyFieldDisplay';
import { FieldDisplayContextProvider } from './FieldDisplayContextProvider';
const MoneyFieldValueSetterEffect = ({ value }: { value: number }) => {
const { setFieldValue } = useMoneyField();
useEffect(() => {
setFieldValue(value);
}, [setFieldValue, value]);
return <></>;
};
type MoneyFieldDisplayWithContextProps = {
value: number;
entityId?: string;
};
const MoneyFieldDisplayWithContext = ({
value,
entityId,
}: MoneyFieldDisplayWithContextProps) => {
return (
<FieldDisplayContextProvider
fieldDefinition={{
key: 'money',
name: 'Money',
type: 'moneyAmount',
metadata: {
fieldName: 'Amount',
placeHolder: 'Amount',
isPositive: true,
},
}}
entityId={entityId}
>
<MoneyFieldValueSetterEffect value={value} />
<MoneyFieldDisplay />
</FieldDisplayContextProvider>
);
};
const meta: Meta = {
title: 'UI/Field/MoneyFieldDisplay',
component: MoneyFieldDisplayWithContext,
};
export default meta;
type Story = StoryObj<typeof MoneyFieldDisplayWithContext>;
export const Default: Story = {
args: {
value: 100,
},
};
export const Elipsis: Story = {
args: {
value: 1e100,
},
argTypes: {
value: { control: false },
},
parameters: {
container: {
width: 100,
},
},
decorators: [ComponentDecorator],
};
export const Catalog: CatalogStory<Story, typeof MoneyFieldDisplayWithContext> =
{
argTypes: {
value: { control: false },
},
parameters: {
catalog: {
dimensions: [
{
name: 'currency',
values: ['$'] satisfies string[],
props: (_value: string) => ({}),
},
{
name: 'value',
values: [
100, 1000, -1000, 1e10, 1.357802, -1.283, 0,
] satisfies number[],
props: (value: number) => ({ value, entityId: v4() }),
},
],
options: {
elementContainer: {
width: 100,
},
},
},
},
decorators: [CatalogDecorator],
};

View File

@ -1,6 +1,6 @@
import styled from '@emotion/styled';
const StyledLayout = styled.div`
const StyledLayout = styled.div<{ width?: number }>`
background: ${({ theme }) => theme.background.primary};
border: 1px solid ${({ theme }) => theme.border.color.light};
border-radius: 5px;
@ -12,13 +12,17 @@ const StyledLayout = styled.div`
max-width: calc(100% - 40px);
min-width: 300px;
padding: 20px;
width: fit-content;
width: ${({ width }) => (width ? width + 'px' : 'fit-content')};
`;
type OwnProps = {
type ComponentStorybookLayoutProps = {
width?: number;
children: JSX.Element;
};
export const ComponentStorybookLayout = ({ children }: OwnProps) => (
<StyledLayout>{children}</StyledLayout>
export const ComponentStorybookLayout = ({
width,
children,
}: ComponentStorybookLayoutProps) => (
<StyledLayout width={width}>{children}</StyledLayout>
);

View File

@ -108,41 +108,47 @@ export const CatalogDecorator: Decorator = (Story, context) => {
<StyledColumnContainer key={value4}>
<StyledColumnTitle>
{dimension4.labels?.(value4) ??
(typeof value4 === 'string' ? value4 : '')}
(['string', 'number'].includes(typeof value4) ? value4 : '')}
</StyledColumnTitle>
{dimension3.values.map((value3: any) => (
<StyledRowsContainer key={value3}>
<StyledRowsTitle>
{dimension3.labels?.(value3) ??
(typeof value3 === 'string' ? value3 : '')}
(['string', 'number'].includes(typeof value3) ? value3 : '')}
</StyledRowsTitle>
{dimension2.values.map((value2: any) => (
<StyledRowContainer key={value2}>
<StyledRowTitle>
{dimension2.labels?.(value2) ??
(typeof value2 === 'string' ? value2 : '')}
(['string', 'number'].includes(typeof value2)
? value2
: '')}
</StyledRowTitle>
{dimension1.values.map((value1: any) => (
<StyledCellContainer key={value1} id={value1}>
<StyledElementTitle>
{dimension1.labels?.(value1) ??
(typeof value1 === 'string' ? value1 : '')}
</StyledElementTitle>
<StyledElementContainer
width={options?.elementContainer?.width}
>
<Story
args={{
...context.args,
...dimension1.props(value1),
...dimension2.props(value2),
...dimension3.props(value3),
...dimension4.props(value4),
}}
/>
</StyledElementContainer>
</StyledCellContainer>
))}
{dimension1.values.map((value1: any) => {
return (
<StyledCellContainer key={value1} id={value1}>
<StyledElementTitle>
{dimension1.labels?.(value1) ??
(['string', 'number'].includes(typeof value1)
? value1
: '')}
</StyledElementTitle>
<StyledElementContainer
width={options?.elementContainer?.width}
>
<Story
args={{
...context.args,
...dimension1.props(value1),
...dimension2.props(value2),
...dimension3.props(value3),
...dimension4.props(value4),
}}
/>
</StyledElementContainer>
</StyledCellContainer>
);
})}
</StyledRowContainer>
))}
</StyledRowsContainer>

View File

@ -2,8 +2,12 @@ import { Decorator } from '@storybook/react';
import { ComponentStorybookLayout } from '../ComponentStorybookLayout';
export const ComponentDecorator: Decorator = (Story) => (
<ComponentStorybookLayout>
<Story />
</ComponentStorybookLayout>
);
export const ComponentDecorator: Decorator = (Story, context) => {
const { container } = context.parameters;
return (
<ComponentStorybookLayout width={container?.width}>
<Story />
</ComponentStorybookLayout>
);
};