diff --git a/front/src/pages/settings/data-model/__stories__/SettingsNewObject.stories.tsx b/front/src/pages/settings/data-model/__stories__/SettingsNewObject.stories.tsx index dbe54c960..24b436380 100644 --- a/front/src/pages/settings/data-model/__stories__/SettingsNewObject.stories.tsx +++ b/front/src/pages/settings/data-model/__stories__/SettingsNewObject.stories.tsx @@ -1,4 +1,5 @@ import { Meta, StoryObj } from '@storybook/react'; +import { userEvent, within } from '@storybook/testing-library'; import { PageDecorator, @@ -25,8 +26,20 @@ export default meta; export type Story = StoryObj; -export const Default: Story = { +export const WithStandardSelected: Story = { play: async ({}) => { await sleep(100); }, }; + +export const WithCustomSelected: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await sleep(1000); + + const customButtonElement = canvas.getByText('Custom'); + + await userEvent.click(customButtonElement); + }, +}; diff --git a/front/src/pages/settings/data-model/__stories__/SettingsObjectDetail.stories.tsx b/front/src/pages/settings/data-model/__stories__/SettingsObjectDetail.stories.tsx index a8766dd26..bcf4449df 100644 --- a/front/src/pages/settings/data-model/__stories__/SettingsObjectDetail.stories.tsx +++ b/front/src/pages/settings/data-model/__stories__/SettingsObjectDetail.stories.tsx @@ -26,8 +26,14 @@ export default meta; export type Story = StoryObj; -export const Default: Story = { +export const StandardObject: Story = { play: async ({}) => { await sleep(100); }, }; + +export const CustomObject: Story = { + args: { + routeParams: { ':objectSlug': 'workspaces' }, + }, +}; diff --git a/front/src/pages/settings/data-model/__stories__/SettingsObjectEdit.stories.tsx b/front/src/pages/settings/data-model/__stories__/SettingsObjectEdit.stories.tsx index 138b3f281..0ce4b8485 100644 --- a/front/src/pages/settings/data-model/__stories__/SettingsObjectEdit.stories.tsx +++ b/front/src/pages/settings/data-model/__stories__/SettingsObjectEdit.stories.tsx @@ -26,8 +26,14 @@ export default meta; export type Story = StoryObj; -export const Default: Story = { +export const StandardObject: Story = { play: async ({}) => { await sleep(100); }, }; + +export const CustomObject: Story = { + args: { + routeParams: { ':objectSlug': 'workspaces' }, + }, +}; diff --git a/front/src/pages/settings/data-model/__stories__/SettingsObjectFieldEdit.stories.tsx b/front/src/pages/settings/data-model/__stories__/SettingsObjectFieldEdit.stories.tsx new file mode 100644 index 000000000..d760d8960 --- /dev/null +++ b/front/src/pages/settings/data-model/__stories__/SettingsObjectFieldEdit.stories.tsx @@ -0,0 +1,37 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import { + PageDecorator, + PageDecoratorArgs, +} from '~/testing/decorators/PageDecorator'; +import { graphqlMocks } from '~/testing/graphqlMocks'; + +import { SettingsObjectFieldEdit } from '../SettingsObjectFieldEdit'; + +const meta: Meta = { + title: 'Pages/Settings/DataModel/SettingsObjectFieldEdit', + component: SettingsObjectFieldEdit, + decorators: [PageDecorator], + args: { + routePath: '/settings/objects/:objectSlug/:fieldSlug', + routeParams: { ':objectSlug': 'companies', ':fieldSlug': 'name' }, + }, + parameters: { + msw: graphqlMocks, + }, +}; + +export default meta; + +export type Story = StoryObj; + +export const StandardField: Story = {}; + +export const CustomField: Story = { + args: { + routeParams: { + ':objectSlug': 'companies', + ':fieldSlug': 'employees', + }, + }, +}; diff --git a/front/src/testing/decorators/RootDecorator.tsx b/front/src/testing/decorators/RootDecorator.tsx index 16872b82f..dfcd961e7 100644 --- a/front/src/testing/decorators/RootDecorator.tsx +++ b/front/src/testing/decorators/RootDecorator.tsx @@ -2,14 +2,18 @@ import { ApolloProvider } from '@apollo/client'; import { Decorator } from '@storybook/react'; import { RecoilRoot } from 'recoil'; +import { ApolloMetadataClientProvider } from '@/metadata/components/ApolloMetadataClientProvider'; + import { InitializeHotkeyStorybookHookEffect } from '../InitializeHotkeyStorybookHook'; import { mockedClient } from '../mockedClient'; export const RootDecorator: Decorator = (Story) => ( - - + + + + ); diff --git a/front/src/testing/graphqlMocks.ts b/front/src/testing/graphqlMocks.ts index 19e6a17c5..365cc9a10 100644 --- a/front/src/testing/graphqlMocks.ts +++ b/front/src/testing/graphqlMocks.ts @@ -7,6 +7,7 @@ import { CREATE_EVENT } from '@/analytics/graphql/queries/createEvent'; import { GET_CLIENT_CONFIG } from '@/client-config/graphql/queries/getClientConfig'; import { INSERT_ONE_COMPANY } from '@/companies/graphql/mutations/insertOneCompany'; import { GET_COMPANIES } from '@/companies/graphql/queries/getCompanies'; +import { FIND_MANY_METADATA_OBJECTS } from '@/metadata/graphql/queries'; import { INSERT_ONE_PERSON } from '@/people/graphql/mutations/insertOnePerson'; import { UPDATE_ONE_PERSON } from '@/people/graphql/mutations/updateOnePerson'; import { GET_PEOPLE } from '@/people/graphql/queries/getPeople'; @@ -33,6 +34,7 @@ import { mockedApiKeys } from '~/testing/mock-data/api-keys'; import { mockedActivities, mockedTasks } from './mock-data/activities'; import { mockedCompaniesData } from './mock-data/companies'; +import { mockedMetadataObjects } from './mock-data/metadata'; import { mockedPeopleData } from './mock-data/people'; import { mockedPipelineProgressData } from './mock-data/pipeline-progress'; import { mockedPipelinesData } from './mock-data/pipelines'; @@ -43,6 +45,10 @@ import { updateOneFromData, } from './mock-data'; +const metadataGraphql = graphql.link( + `${process.env.REACT_APP_SERVER_BASE_URL}/metadata`, +); + export const graphqlMocks = [ graphql.query(getOperationName(GET_COMPANIES) ?? '', (req, res, ctx) => { const returnedMockedData = filterAndSortData< @@ -282,4 +288,10 @@ export const graphqlMocks = [ ); }, ), + metadataGraphql.query( + getOperationName(FIND_MANY_METADATA_OBJECTS) ?? '', + (req, res, ctx) => { + return res(ctx.data({ objects: mockedMetadataObjects })); + }, + ), ]; diff --git a/front/src/testing/mock-data/metadata.ts b/front/src/testing/mock-data/metadata.ts new file mode 100644 index 000000000..0065c268f --- /dev/null +++ b/front/src/testing/mock-data/metadata.ts @@ -0,0 +1,179 @@ +export const mockedMetadataObjects = { + edges: [ + { + node: { + id: 'a3195559-cc20-4749-9565-572a2f506581', + dataSourceId: '', + nameSingular: 'company', + namePlural: 'companies', + labelSingular: 'Company', + labelPlural: 'Companies', + description: null, + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + createdAt: '', + updatedAt: '', + fields: { + edges: [ + { + node: { + id: '397eabc0-c5a1-4550-8e68-839c878a8d0e', + type: 'text', + name: 'name', + label: 'Name', + description: 'The company name.', + placeholder: null, + icon: 'IconBuildingSkyscraper', + isCustom: false, + isActive: true, + isNullable: false, + createdAt: '', + updatedAt: '', + }, + }, + { + node: { + id: '7ad234c7-f3b9-4efc-813c-43dc97070b07', + type: 'url', + name: 'url', + label: 'URL', + description: + 'The company website URL. We use this url to fetch the company icon.', + placeholder: null, + icon: 'IconLink', + isCustom: false, + isActive: true, + isNullable: true, + createdAt: '', + updatedAt: '', + }, + }, + { + node: { + id: 'a578ffb2-13db-483c-ace7-5c30a13dff2d', + type: 'relation', + name: 'accountOwner', + label: 'Account Owner', + description: + 'Your team member responsible for managing the company account.', + placeholder: null, + icon: 'IconUserCircle', + isCustom: false, + isActive: true, + isNullable: true, + createdAt: '', + updatedAt: '', + }, + }, + { + node: { + id: 'b7fd622d-7d8b-4f5a-b148-a7e9fd2c4660', + type: 'number', + name: 'employees', + label: 'Employees', + description: 'Number of employees in the company.', + placeholder: null, + icon: 'IconUsers', + isCustom: true, + isActive: true, + isNullable: true, + createdAt: '', + updatedAt: '', + }, + }, + { + node: { + id: '60ab27ed-a959-471e-b583-887387f7accd', + type: 'url', + name: 'linkedin', + label: 'Linkedin', + description: null, + placeholder: null, + icon: 'IconBrandLinkedin', + isCustom: false, + isActive: true, + isNullable: true, + createdAt: '', + updatedAt: '', + }, + }, + { + node: { + id: '6daadb98-83ca-4c85-bca5-7792a7d958ad', + type: 'boolean', + name: 'prioritySupport', + label: 'Priority Support', + description: 'Whether the company has priority support.', + placeholder: null, + icon: 'IconHeadphones', + isCustom: true, + isActive: false, + isNullable: true, + createdAt: '', + updatedAt: '', + }, + }, + ], + pageInfo: { + hasNextPage: false, + hasPreviousPage: false, + startCursor: null, + endCursor: null, + }, + totalCount: 6, + }, + }, + }, + { + node: { + id: 'c973efa3-436e-47ea-8dbc-983ed869c04d', + dataSourceId: '', + nameSingular: 'workspace', + namePlural: 'workspaces', + labelSingular: 'Workspace', + labelPlural: 'Workspaces', + description: null, + icon: 'IconApps', + isCustom: true, + isActive: true, + createdAt: '', + updatedAt: '', + fields: { + edges: [ + { + node: { + id: 'f955402c-9e8f-4b91-a82c-95f6de392b99', + type: 'text', + name: 'slug', + label: 'Slug', + description: null, + placeholder: null, + icon: 'IconSlash', + isCustom: true, + isActive: true, + isNullable: true, + createdAt: '', + updatedAt: '', + }, + }, + ], + pageInfo: { + hasNextPage: false, + hasPreviousPage: false, + startCursor: null, + endCursor: null, + }, + totalCount: 1, + }, + }, + }, + ], + pageInfo: { + hasNextPage: false, + hasPreviousPage: false, + startCursor: null, + endCursor: null, + }, + totalCount: 2, +};