Increase storybook pages coverage (#4885)

On FE:
- refreshing metadata mocks
- updating jest tests
- fixing storybook pages coverage
- fixing storybook modules coverage
This commit is contained in:
Charles Bochet
2024-04-17 16:24:04 +02:00
committed by GitHub
parent 6804a90f2f
commit 75fd430149
46 changed files with 13679 additions and 7354 deletions

View File

@ -7,41 +7,27 @@ import {
FieldSelectMetadata,
FieldTextMetadata,
} from '@/object-record/record-field/types/FieldMetadata';
import { type } from 'os';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import {
mockedCompaniesMetadata,
mockedCustomMetadata,
mockedPeopleMetadata,
} from '~/testing/mock-data/metadata';
import { mockedCompanyObjectMetadataItem, mockedPersonObjectMetadataItem } from '~/testing/mock-data/metadata';
;
export const fieldMetadataId = 'fieldMetadataId';
export const mockedPersonObjectMetadataItem = {
...mockedPeopleMetadata.node,
fields: mockedPeopleMetadata.node.fields.edges.map(({ node }) => node),
};
export const mockedCompanyObjectMetadataItem = {
...mockedCompaniesMetadata.node,
fields: mockedCompaniesMetadata.node.fields.edges.map(({ node }) => node),
};
export const mockedCustomObjectMetadataItem = {
...mockedCustomMetadata.node,
fields: mockedCustomMetadata.node.fields.edges.map(({ node }) => node),
};
export const textfieldDefinition: FieldDefinition<FieldTextMetadata> = {
fieldMetadataId,
label: 'User Name',
iconName: 'User',
defaultValue: '',
type: FieldMetadataType.Text,
metadata: { placeHolder: 'John Doe', fieldName: 'userName' },
};
const relationFieldMetadataItem = mockedPersonObjectMetadataItem.fields.find(
const relationFieldMetadataItem = mockedPersonObjectMetadataItem.fields?.find(
({ name }) => name === 'company',
);
export const relationFieldDefinition = formatFieldMetadataItemAsFieldDefinition(
{
field: relationFieldMetadataItem!,
@ -54,6 +40,7 @@ export const selectFieldDefinition: FieldDefinition<FieldSelectMetadata> = {
label: 'Account Owner',
iconName: 'iconName',
type: FieldMetadataType.Select,
defaultValue: null,
metadata: {
fieldName: 'accountOwner',
options: [{ label: 'Elon Musk', color: 'blue', value: 'userId' }],
@ -65,6 +52,7 @@ export const fullNameFieldDefinition: FieldDefinition<FieldFullNameMetadata> = {
label: 'Display Name',
iconName: 'profile',
type: FieldMetadataType.FullName,
defaultValue: { firstName: '', lastName: '' },
metadata: {
fieldName: 'displayName',
placeHolder: 'Mr Miagi',
@ -76,13 +64,14 @@ export const linkFieldDefinition: FieldDefinition<FieldLinkMetadata> = {
label: 'LinkedIn URL',
iconName: 'url',
type: FieldMetadataType.Link,
defaultValue: { label: '', url: ''},
metadata: {
fieldName: 'linkedInURL',
placeHolder: 'https://linkedin.com/user',
},
};
const phoneFieldMetadataItem = mockedPersonObjectMetadataItem.fields.find(
const phoneFieldMetadataItem = mockedPersonObjectMetadataItem.fields?.find(
({ name }) => name === 'phone',
);
export const phoneFieldDefinition = formatFieldMetadataItemAsFieldDefinition({
@ -95,12 +84,13 @@ export const ratingfieldDefinition: FieldDefinition<FieldRatingMetadata> = {
label: 'Rating',
iconName: 'iconName',
type: FieldMetadataType.Rating,
defaultValue: null,
metadata: {
fieldName: 'rating',
},
};
const booleanFieldMetadataItem = mockedCompanyObjectMetadataItem.fields.find(
const booleanFieldMetadataItem = mockedCompanyObjectMetadataItem.fields?.find(
({ name }) => name === 'idealCustomerProfile',
);
export const booleanFieldDefinition = formatFieldMetadataItemAsFieldDefinition({

View File

@ -24,6 +24,29 @@ const DateFieldValueSetterEffect = ({ value }: { value: Date }) => {
return <></>;
};
type DateFieldValueGaterProps = Pick<
DateTimeFieldInputProps,
'onEscape' | 'onEnter' | 'onClickOutside'
>;
const DateFieldValueGater = ({
onEscape,
onEnter,
onClickOutside,
}: DateFieldValueGaterProps) => {
const { fieldValue } = useDateTimeField();
return (
fieldValue && (
<DateTimeFieldInput
onEscape={onEscape}
onEnter={onEnter}
onClickOutside={onClickOutside}
/>
)
);
};
type DateFieldInputWithContextProps = DateTimeFieldInputProps & {
value: Date;
entityId?: string;
@ -47,6 +70,7 @@ const DateFieldInputWithContext = ({
<FieldContextProvider
fieldDefinition={{
fieldMetadataId: 'date',
defaultValue: null,
label: 'Date',
type: FieldMetadataType.DateTime,
iconName: 'IconCalendarEvent',
@ -58,7 +82,7 @@ const DateFieldInputWithContext = ({
entityId={entityId}
>
<DateFieldValueSetterEffect value={value} />
<DateTimeFieldInput
<DateFieldValueGater
onEscape={onEscape}
onEnter={onEnter}
onClickOutside={onClickOutside}
@ -102,9 +126,9 @@ type Story = StoryObj<typeof DateFieldInputWithContext>;
export const Default: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const div = await canvas.findByText('Feb 1, 2022');
const div = await canvas.findByText('February - 2022');
await expect(div.innerText).toContain('Feb 1, 2022');
await expect(div.innerText).toContain('February - 2022');
},
};
@ -125,7 +149,7 @@ export const Escape: Story = {
play: async () => {
await expect(escapeJestFn).toHaveBeenCalledTimes(0);
await userEvent.keyboard('{esc}');
await userEvent.keyboard('{escape}');
await expect(escapeJestFn).toHaveBeenCalledTimes(1);
},

View File

@ -62,6 +62,7 @@ export const RecordDetailRelationSection = () => {
fieldValue && isToOneObject
? [fieldValue as ObjectRecord]
: (fieldValue as ObjectRecord[]) ?? [];
const relationRecordIds = relationRecords.map(({ id }) => id);
const dropdownId = `record-field-card-relation-picker-${fieldDefinition.label}`;

View File

@ -2,7 +2,6 @@ import { Meta, StoryObj } from '@storybook/react';
import { ComponentDecorator } from 'twenty-ui';
import { formatFieldMetadataItemAsFieldDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsFieldDefinition';
import { mockedCompanyObjectMetadataItem } from '@/object-record/record-field/__mocks__/fieldDefinitions';
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator';
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
@ -10,6 +9,7 @@ import { RecordStoreDecorator } from '~/testing/decorators/RecordStoreDecorator'
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
import { graphqlMocks } from '~/testing/graphqlMocks';
import { mockedCompaniesData } from '~/testing/mock-data/companies';
import { mockedCompanyObjectMetadataItem } from '~/testing/mock-data/metadata';
import { mockedPeopleData } from '~/testing/mock-data/people';
import { RecordDetailRelationSection } from '../RecordDetailRelationSection';
@ -59,7 +59,7 @@ export const WithRecords: Story = {
records: [
{
...mockedCompaniesData[0],
people: { edges: mockedPeopleData.map((person) => ({ node: person })) },
people: mockedPeopleData,
},
...mockedPeopleData,
],

View File

@ -1,7 +1,8 @@
import { ChangeEvent } from 'react';
import { act, renderHook } from '@testing-library/react';
import { RecoilRoot } from 'recoil';
import { RecoilRoot, useRecoilValue } from 'recoil';
import { useRelationPickerScopedStates } from '@/object-record/relation-picker/hooks/internal/useRelationPickerScopedStates';
import { useEntitySelectSearch } from '@/object-record/relation-picker/hooks/useEntitySelectSearch';
import { RelationPickerScopeInternalContext } from '@/object-record/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext';
@ -14,16 +15,32 @@ const Wrapper = ({ children }: { children: React.ReactNode }) => (
describe('useEntitySelectSearch', () => {
it('should update searchFilter after change event', async () => {
const { result } = renderHook(() => useEntitySelectSearch(), {
wrapper: Wrapper,
});
const { result } = renderHook(
() => {
const entitySelectSearchHook = useEntitySelectSearch({
relationPickerScopeId: 'relation-picker',
});
const relationPickerScopedStatesHook = useRelationPickerScopedStates({
relationPickerScopedId: 'relation-picker',
});
const internallyStoredFilter = useRecoilValue(
relationPickerScopedStatesHook.relationPickerSearchFilterState,
);
return { entitySelectSearchHook, internallyStoredFilter };
},
{
wrapper: Wrapper,
},
);
const filter = 'value';
act(() => {
result.current.handleSearchFilterChange({
result.current.entitySelectSearchHook.handleSearchFilterChange({
currentTarget: { value: filter },
} as ChangeEvent<HTMLInputElement>);
});
expect(result.current.searchFilter).toBe(filter);
expect(result.current.internallyStoredFilter).toBe(filter);
});
});