diff --git a/front/src/modules/metadata/hooks/useFindManyObjectMetadataItems.ts b/front/src/modules/metadata/hooks/useFindManyObjectMetadataItems.ts index a6dd39bea..8eeec5220 100644 --- a/front/src/modules/metadata/hooks/useFindManyObjectMetadataItems.ts +++ b/front/src/modules/metadata/hooks/useFindManyObjectMetadataItems.ts @@ -14,7 +14,9 @@ import { formatPagedObjectMetadataItemsToObjectMetadataItems } from '../utils/fo import { useApolloMetadataClient } from './useApolloMetadataClient'; // TODO: test fetchMore -export const useFindManyObjectMetadataItems = () => { +export const useFindManyObjectMetadataItems = ({ + skip, +}: { skip?: boolean } = {}) => { const apolloMetadataClient = useApolloMetadataClient(); const { enqueueSnackBar } = useSnackBar(); @@ -28,7 +30,7 @@ export const useFindManyObjectMetadataItems = () => { FIND_MANY_METADATA_OBJECTS, { client: apolloMetadataClient ?? undefined, - skip: !apolloMetadataClient, + skip: skip || !apolloMetadataClient, onError: (error) => { logError('useFindManyObjectMetadataItems error : ' + error); enqueueSnackBar( diff --git a/front/src/modules/metadata/hooks/useFindManyObjects.ts b/front/src/modules/metadata/hooks/useFindManyObjects.ts index 97118186d..baf415983 100644 --- a/front/src/modules/metadata/hooks/useFindManyObjects.ts +++ b/front/src/modules/metadata/hooks/useFindManyObjects.ts @@ -19,14 +19,17 @@ export const useFindManyObjects = < filter, orderBy, onCompleted, + skip, }: Pick & { filter?: any; orderBy?: any; onCompleted?: (data: any) => void; + skip?: boolean; }) => { const { foundObjectMetadataItem, objectNotFoundInMetadata, findManyQuery } = useFindOneObjectMetadataItem({ objectNamePlural, + skip, }); const { enqueueSnackBar } = useSnackBar(); @@ -34,7 +37,7 @@ export const useFindManyObjects = < const { data, loading, error } = useQuery>( findManyQuery, { - skip: !foundObjectMetadataItem, + skip: skip || !foundObjectMetadataItem, variables: { filter: filter ?? {}, orderBy: orderBy ?? {}, diff --git a/front/src/modules/metadata/hooks/useFindOneObjectMetadataItem.ts b/front/src/modules/metadata/hooks/useFindOneObjectMetadataItem.ts index c43980995..200b2fcca 100644 --- a/front/src/modules/metadata/hooks/useFindOneObjectMetadataItem.ts +++ b/front/src/modules/metadata/hooks/useFindOneObjectMetadataItem.ts @@ -21,8 +21,11 @@ import { useFindManyObjectMetadataItems } from './useFindManyObjectMetadataItems export const useFindOneObjectMetadataItem = ({ objectNamePlural, objectNameSingular, -}: ObjectMetadataItemIdentifier) => { - const { objectMetadataItems, loading } = useFindManyObjectMetadataItems(); + skip, +}: ObjectMetadataItemIdentifier & { skip?: boolean }) => { + const { objectMetadataItems, loading } = useFindManyObjectMetadataItems({ + skip, + }); const foundObjectMetadataItem = objectMetadataItems.find( (object) => diff --git a/front/src/modules/ui/object/record-table/hooks/useUpsertRecordTableItem.ts b/front/src/modules/ui/object/record-table/hooks/useUpsertRecordTableItem.ts index aa3f7a9d4..4b9fbb1d7 100644 --- a/front/src/modules/ui/object/record-table/hooks/useUpsertRecordTableItem.ts +++ b/front/src/modules/ui/object/record-table/hooks/useUpsertRecordTableItem.ts @@ -1,6 +1,7 @@ import { useRecoilCallback } from 'recoil'; import { entityFieldsFamilyState } from '@/ui/object/field/states/entityFieldsFamilyState'; +import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; export const useUpsertRecordTableItem = () => useRecoilCallback( @@ -10,7 +11,7 @@ export const useUpsertRecordTableItem = () => .getLoadable(entityFieldsFamilyState(entity.id)) .valueOrThrow(); - if (JSON.stringify(currentEntity) !== JSON.stringify(entity)) { + if (!isDeeplyEqual(currentEntity, entity)) { set(entityFieldsFamilyState(entity.id), entity); } }, diff --git a/front/src/modules/views/components/ViewBarEffect.tsx b/front/src/modules/views/components/ViewBarEffect.tsx index 5d499dcbb..dc4e74382 100644 --- a/front/src/modules/views/components/ViewBarEffect.tsx +++ b/front/src/modules/views/components/ViewBarEffect.tsx @@ -70,6 +70,7 @@ export const ViewBarEffect = () => { }); useFindManyObjects({ + skip: !currentViewId, objectNamePlural: 'viewFieldsV2', filter: { viewId: { eq: currentViewId } }, onCompleted: useRecoilCallback( @@ -114,6 +115,7 @@ export const ViewBarEffect = () => { }); useFindManyObjects({ + skip: !currentViewId, objectNamePlural: 'viewFiltersV2', filter: { viewId: { eq: currentViewId } }, onCompleted: useRecoilCallback( @@ -170,6 +172,7 @@ export const ViewBarEffect = () => { }); useFindManyObjects({ + skip: !currentViewId, objectNamePlural: 'viewSortsV2', filter: { viewId: { eq: currentViewId } }, onCompleted: useRecoilCallback( diff --git a/front/src/pages/companies/__stories__/Companies.add.stories.tsx b/front/src/pages/companies/__stories__/Companies.add.stories.tsx index a1dc69250..e0d8bd0f7 100644 --- a/front/src/pages/companies/__stories__/Companies.add.stories.tsx +++ b/front/src/pages/companies/__stories__/Companies.add.stories.tsx @@ -8,6 +8,7 @@ import { PageDecoratorArgs, } from '~/testing/decorators/PageDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; +import { mockedCompaniesData } from '~/testing/mock-data/companies'; import { sleep } from '~/testing/sleep'; import { Companies } from '../Companies'; @@ -27,26 +28,35 @@ const meta: Meta = { export default meta; export const AddNewCompany: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); - await sleep(2000); + await step('Wait for rows to appear', async () => { + await canvas.findByText( + mockedCompaniesData[0].name, + {}, + { timeout: 3000 }, + ); + }); const rowsBeforeAdd = canvas.getAllByRole('row'); - const addButton = canvas.getByRole('button', { name: 'Add' }); + await step('Click on add button', async () => { + const addButton = canvas.getByRole('button', { name: 'Add' }); - userEvent.click(addButton); + await userEvent.click(addButton); + }); await sleep(1000); - const rowsAfterAdd = canvas.getAllByRole('row'); + await step('Check an empty row has been added', async () => { + const rowsAfterAdd = canvas.getAllByRole('row'); - const firstRow = rowsAfterAdd[1]; - const cells = within(firstRow).getAllByRole('cell'); + const firstRow = rowsAfterAdd[1]; + const cells = within(firstRow).getAllByRole('cell'); - expect(cells[1].textContent).toBe(''); - - expect(rowsAfterAdd).toHaveLength(rowsBeforeAdd.length + 1); + expect(cells[1].textContent).toBe(''); + expect(rowsAfterAdd).toHaveLength(rowsBeforeAdd.length + 1); + }); }, }; diff --git a/front/src/pages/companies/__stories__/Companies.filterBy.stories.tsx b/front/src/pages/companies/__stories__/Companies.filterBy.stories.tsx index 7702682c3..b151a356f 100644 --- a/front/src/pages/companies/__stories__/Companies.filterBy.stories.tsx +++ b/front/src/pages/companies/__stories__/Companies.filterBy.stories.tsx @@ -1,7 +1,6 @@ import { expect } from '@storybook/jest'; import { Meta } from '@storybook/react'; import { userEvent, within } from '@storybook/testing-library'; -import assert from 'assert'; import { AppPath } from '@/types/AppPath'; import { @@ -9,6 +8,7 @@ import { PageDecoratorArgs, } from '~/testing/decorators/PageDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; +import { mockedCompaniesData } from '~/testing/mock-data/companies'; import { sleep } from '~/testing/sleep'; import { Companies } from '../Companies'; @@ -28,81 +28,92 @@ const meta: Meta = { export default meta; export const FilterByName: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); - const filterButton = await canvas.findByText('Filter'); - await userEvent.click(filterButton); - - const nameFilterButton = await canvas.findByTestId('select-filter-0'); - - assert(nameFilterButton); - - await userEvent.click(nameFilterButton); - - const nameInput = canvas.getByPlaceholderText('Name'); - await userEvent.type(nameInput, 'Air', { - delay: 200, + await step('Wait for rows to appear', async () => { + await canvas.findByText( + mockedCompaniesData[0].name, + {}, + { timeout: 3000 }, + ); }); - await sleep(200); - - expect(await canvas.findByText('Airbnb')).toBeInTheDocument(); - expect(await canvas.findByText('Aircall')).toBeInTheDocument(); - expect(await canvas.queryAllByText('Qonto')).toStrictEqual([]); - - const nameFilter = canvas.getAllByText('Name').find((item) => { - return item.parentElement?.textContent?.includes('Name: Air'); + await step('Click on filter button', async () => { + const filterButton = canvas.getByText('Filter'); + await userEvent.click(filterButton); }); - expect(nameFilter).toBeInTheDocument(); - }, -}; -export const FilterByAccountOwner: Story = { - play: async ({ canvasElement }) => { - const canvas = within(canvasElement); + await step('Select name filter', async () => { + const nameFilterButton = canvas.getByTestId('select-filter-0'); + await userEvent.click(nameFilterButton); - const filterButton = await canvas.findByText('Filter'); - await userEvent.click(filterButton); + const nameInput = canvas.getByPlaceholderText('Name'); + await userEvent.type(nameInput, 'Air', { delay: 200 }); - const accountOwnerFilterButton = await canvas.findByTestId( - 'select-filter-5', - ); - - assert(accountOwnerFilterButton); - - await userEvent.click(accountOwnerFilterButton); - - const accountOwnerNameInput = await canvas.findByPlaceholderText( - 'Account owner', - ); - await userEvent.type(accountOwnerNameInput, 'Char', { - delay: 200, + const nameFilter = canvas.getAllByText( + (_, element) => !!element?.textContent?.includes('Name: Air'), + ); + expect(nameFilter).not.toHaveLength(0); }); await sleep(1000); - const charlesChip = (await canvas.findAllByTestId('menu-item')).find( - (item) => { - return item.textContent?.includes('Charles Test'); - }, - ); - - assert(charlesChip); - - await userEvent.click(charlesChip); - - // TODO: fix msw where clauses - // expect(await canvas.findByText('Airbnb')).toBeInTheDocument(); - // await expect(canvas.queryAllByText('Qonto')).toStrictEqual([]); - - const accountOwnerFilter = canvas - .getAllByText('Account owner') - .find((item) => { - return item.parentElement?.textContent?.includes( - 'Account owner: Charles Test', - ); - }); - expect(accountOwnerFilter).toBeInTheDocument(); + await step('Check filtered rows', async () => { + expect(canvas.getByText('Airbnb')).toBeVisible(); + expect(canvas.getByText('Aircall')).toBeVisible(); + expect(canvas.queryByText('Qonto')).toBeNull(); + }); + }, +}; + +export const FilterByAccountOwner: Story = { + play: async ({ canvasElement, step }) => { + const canvas = within(canvasElement); + + await step('Wait for rows to appear', async () => { + await canvas.findByText( + mockedCompaniesData[0].name, + {}, + { timeout: 3000 }, + ); + }); + + await step('Click on filter button', async () => { + const filterButton = canvas.getByText('Filter'); + await userEvent.click(filterButton); + }); + + await step('Select account owner filter', async () => { + const accountOwnerFilterButton = canvas.getByTestId('select-filter-5'); + await userEvent.click(accountOwnerFilterButton); + + const accountOwnerNameInput = + canvas.getByPlaceholderText('Account owner'); + await userEvent.type(accountOwnerNameInput, 'Char', { delay: 200 }); + + const charlesChip = await canvas.findByRole( + 'listitem', + { + name: (_, element) => + !!element?.textContent?.includes('Charles Test'), + }, + { timeout: 1000 }, + ); + await userEvent.click(charlesChip); + + const accountOwnerFilter = canvas.getAllByText( + (_, element) => + !!element?.textContent?.includes('Account owner: Charles Test'), + ); + expect(accountOwnerFilter).not.toHaveLength(0); + }); + + await sleep(1000); + + await step('Check filtered rows', async () => { + expect(canvas.getByText('Airbnb')).toBeVisible(); + expect(canvas.queryByText('Qonto')).toBeNull(); + }); }, }; diff --git a/front/src/pages/companies/__stories__/Companies.sortBy.stories.tsx b/front/src/pages/companies/__stories__/Companies.sortBy.stories.tsx index f100a8ddd..c42d9d304 100644 --- a/front/src/pages/companies/__stories__/Companies.sortBy.stories.tsx +++ b/front/src/pages/companies/__stories__/Companies.sortBy.stories.tsx @@ -8,6 +8,8 @@ import { PageDecoratorArgs, } from '~/testing/decorators/PageDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; +import { mockedCompaniesData } from '~/testing/mock-data/companies'; +import { sleep } from '~/testing/sleep'; import { Companies } from '../Companies'; @@ -25,24 +27,50 @@ const meta: Meta = { export default meta; +const sortedCompanyNames = mockedCompaniesData + .map(({ name }) => name) + .toSorted(); + export const SortByName: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); - const sortButton = await canvas.findByText('Sort'); - await userEvent.click(sortButton); + await step('Wait for rows to appear', async () => { + await canvas.findByText( + mockedCompaniesData[0].name, + {}, + { timeout: 3000 }, + ); + }); - const nameSortButton = await canvas.findByTestId('select-sort-0'); + await step('Click on sort button', async () => { + const sortButton = canvas.getByRole('button', { name: 'Sort' }); + await userEvent.click(sortButton); + }); - await userEvent.click(nameSortButton); + await step('Select sort by name', async () => { + const nameSortButton = canvas.getByTestId('select-sort-0'); + await userEvent.click(nameSortButton); - expect(await canvas.getByTestId('remove-icon-name')).toBeInTheDocument(); + await canvas.findByTestId('remove-icon-name', {}, { timeout: 3000 }); + }); - expect(await canvas.findByText('Airbnb')).toBeInTheDocument(); + await sleep(1000); - const resetButton = canvas.getByText('Reset'); - await userEvent.click(resetButton); + await step('Check rows are sorted by name', async () => { + const nameCells = canvas.getAllByText( + (_, element) => + sortedCompanyNames.some((name) => + element?.textContent?.includes(name), + ), + { selector: '[data-testid="editable-cell-display-mode"]' }, + ); - await expect(canvas.queryAllByTestId('remove-icon-name')).toStrictEqual([]); + expect(nameCells).toHaveLength(sortedCompanyNames.length); + + sortedCompanyNames.forEach((name, index) => + expect(nameCells[index]).toHaveTextContent(name), + ); + }); }, }; diff --git a/front/src/pages/companies/__stories__/Company.stories.tsx b/front/src/pages/companies/__stories__/Company.stories.tsx index d4287fc91..b0b28cc97 100644 --- a/front/src/pages/companies/__stories__/Company.stories.tsx +++ b/front/src/pages/companies/__stories__/Company.stories.tsx @@ -10,6 +10,7 @@ import { GET_ACTIVITY } from '@/activities/graphql/queries/getActivity'; import { UPDATE_ONE_COMPANY } from '@/companies/graphql/mutations/updateOneCompany'; import { GET_COMPANY } from '@/companies/graphql/queries/getCompany'; import { AppPath } from '@/types/AppPath'; +import { ObjectFilterDropdownScope } from '@/ui/object/object-filter-dropdown/scopes/ObjectFilterDropdownScope'; import { PageDecorator, PageDecoratorArgs, @@ -176,6 +177,13 @@ export const NoteTab: Story = { }; export const TaskTab: Story = { + decorators: [ + (Story) => ( + + + + ), + ], play: async ({ canvasElement }) => { const canvas = within(canvasElement); const taskTab = await canvas.findByTestId('tab-tasks'); diff --git a/front/src/pages/opportunities/__stories__/Opportunities.stories.tsx b/front/src/pages/opportunities/__stories__/Opportunities.stories.tsx index 8de68be70..3e078ac67 100644 --- a/front/src/pages/opportunities/__stories__/Opportunities.stories.tsx +++ b/front/src/pages/opportunities/__stories__/Opportunities.stories.tsx @@ -1,5 +1,5 @@ import { Meta, StoryObj } from '@storybook/react'; -import { within } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { AppPath } from '@/types/AppPath'; import { @@ -24,12 +24,7 @@ export default meta; export type Story = StoryObj; -export const Default: Story = { - play: async ({ canvasElement }) => { - const canvas = within(canvasElement); - await canvas.findByText('All opportunities'); - }, -}; +export const Default: Story = {}; export const AddCompanyFromHeader: Story = { play: async ({ canvasElement, step }) => { @@ -38,53 +33,35 @@ export const AddCompanyFromHeader: Story = { await step('Click on the add company button', async () => { const button = await canvas.findByTestId('add-company-progress-button'); - await button.click(); + await userEvent.click(button); - await canvas.findByText('Algolia'); + await canvas.findByRole( + 'listitem', + { name: (_, element) => !!element?.textContent?.includes('Algolia') }, + { timeout: 1000 }, + ); }); await step('Change pipeline stage', async () => { - const dropdownMenu = within( - await canvas.findByTestId('company-progress-dropdown-menu'), + const pipelineStageDropdownHeader = await canvas.findByRole( + 'listitem', + { name: (_, element) => !!element?.textContent?.includes('New') }, + { timeout: 1000 }, ); - const pipelineStageDropdownHeader = await canvas.findByTestId( - 'selected-pipeline-stage', - ); - - const pipelineStageDropdownUnfoldButton = await within( + const pipelineStageDropdownUnfoldButton = within( pipelineStageDropdownHeader, - ).findByTestId('dropdown-menu-header-end-icon'); + ).getByRole('button'); - await pipelineStageDropdownUnfoldButton.click(); + await userEvent.click(pipelineStageDropdownUnfoldButton); - const menuItem1 = await canvas.findByTestId('select-pipeline-stage-1'); - - await menuItem1.click(); - - await dropdownMenu.findByText('Screening'); - }); - - await step('Change pipeline stage', async () => { - const dropdownMenu = within( - await canvas.findByTestId('company-progress-dropdown-menu'), + const menuItem1 = await canvas.findByRole( + 'listitem', + { name: (_, element) => !!element?.textContent?.includes('Screening') }, + { timeout: 1000 }, ); - const pipelineStageDropdownHeader = await canvas.findByTestId( - 'selected-pipeline-stage', - ); - - const pipelineStageDropdownUnfoldButton = await within( - pipelineStageDropdownHeader, - ).findByTestId('dropdown-menu-header-end-icon'); - - await pipelineStageDropdownUnfoldButton.click(); - - const menuItem1 = await canvas.findByTestId('select-pipeline-stage-1'); - - await menuItem1.click(); - - await dropdownMenu.findByText('Screening'); + await userEvent.click(menuItem1); }); // TODO: mock add company mutation and add step for company creation diff --git a/front/src/pages/people/__stories__/People.add.stories.tsx b/front/src/pages/people/__stories__/People.add.stories.tsx index 7c6434e7e..c45e80d68 100644 --- a/front/src/pages/people/__stories__/People.add.stories.tsx +++ b/front/src/pages/people/__stories__/People.add.stories.tsx @@ -8,6 +8,7 @@ import { PageDecoratorArgs, } from '~/testing/decorators/PageDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; +import { mockedPeopleData } from '~/testing/mock-data/people'; import { sleep } from '~/testing/sleep'; import { People } from '../People'; @@ -27,26 +28,35 @@ const meta: Meta = { export default meta; export const AddNewPerson: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); - await sleep(2000); + await step('Wait for rows to appear', async () => { + await canvas.findByText( + mockedPeopleData[0].displayName, + {}, + { timeout: 3000 }, + ); + }); const rowsBeforeAdd = canvas.getAllByRole('row'); - const addButton = canvas.getByRole('button', { name: 'Add' }); + await step('Click on add button', async () => { + const addButton = canvas.getByRole('button', { name: 'Add' }); - userEvent.click(addButton); + await userEvent.click(addButton); + }); await sleep(1000); - const rowsAfterAdd = canvas.getAllByRole('row'); + await step('Check an empty row has been added', async () => { + const rowsAfterAdd = canvas.getAllByRole('row'); - const firstRow = rowsAfterAdd[1]; - const cells = within(firstRow).getAllByRole('cell'); + const firstRow = rowsAfterAdd[1]; + const cells = within(firstRow).getAllByRole('cell'); - expect(cells[1].textContent).toBe(''); - - expect(rowsAfterAdd).toHaveLength(rowsBeforeAdd.length + 1); + expect(cells[1].textContent).toBe(''); + expect(rowsAfterAdd).toHaveLength(rowsBeforeAdd.length + 1); + }); }, }; diff --git a/front/src/pages/people/__stories__/People.filterBy.stories.tsx b/front/src/pages/people/__stories__/People.filterBy.stories.tsx index 78d5fa12b..f0c680fa2 100644 --- a/front/src/pages/people/__stories__/People.filterBy.stories.tsx +++ b/front/src/pages/people/__stories__/People.filterBy.stories.tsx @@ -1,7 +1,6 @@ import { expect } from '@storybook/jest'; import { Meta } from '@storybook/react'; import { userEvent, within } from '@storybook/testing-library'; -import assert from 'assert'; import { AppPath } from '@/types/AppPath'; import { @@ -9,6 +8,7 @@ import { PageDecoratorArgs, } from '~/testing/decorators/PageDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; +import { mockedPeopleData } from '~/testing/mock-data/people'; import { sleep } from '~/testing/sleep'; import { People } from '../People'; @@ -28,75 +28,86 @@ const meta: Meta = { export default meta; export const Email: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); - const filterButton = await canvas.findByText('Filter'); - await userEvent.click(filterButton); - - const emailFilterButton = await canvas.findByTestId('select-filter-2'); - - assert(emailFilterButton); - - await userEvent.click(emailFilterButton); - - const emailInput = canvas.getByPlaceholderText('Email'); - - await userEvent.type(emailInput, 'al', { - delay: 200, + await step('Wait for rows to appear', async () => { + await canvas.findByText( + mockedPeopleData[0].displayName, + {}, + { timeout: 3000 }, + ); }); - await sleep(100); - - expect(await canvas.findByText('Alexandre Prot')).toBeInTheDocument(); - await expect(canvas.queryAllByText('John Doe')).toStrictEqual([]); - - const emailFilter = canvas.getAllByText('Email').find((item) => { - return item.parentElement?.textContent?.includes('Email: al'); + await step('Click on filter button', async () => { + const filterButton = canvas.getByText('Filter'); + await userEvent.click(filterButton); + }); + + await step('Select email filter', async () => { + const emailFilterButton = canvas.getByTestId('select-filter-2'); + await userEvent.click(emailFilterButton); + + const emailInput = canvas.getByPlaceholderText('Email'); + await userEvent.type(emailInput, 'al', { delay: 200 }); + + const emailFilter = canvas.getAllByText( + (_, element) => !!element?.textContent?.includes('Email: al'), + ); + expect(emailFilter).not.toHaveLength(0); + }); + + await sleep(1000); + + await step('Check filtered rows', async () => { + expect(canvas.getByText('Alexandre Prot')).toBeVisible(); + expect(canvas.queryByText('John Doe')).toBeNull(); }); - expect(emailFilter).toBeInTheDocument(); }, }; export const CompanyName: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); - const filterButton = await canvas.findByText('Filter'); - await userEvent.click(filterButton); - - const companyFilterButton = await canvas.findByTestId('select-filter-3'); - - assert(companyFilterButton); - - await userEvent.click(companyFilterButton); - - const companyNameInput = canvas.getByPlaceholderText('Company'); - await userEvent.type(companyNameInput, 'Qon', { - delay: 200, + await step('Wait for rows to appear', async () => { + await canvas.findByText( + mockedPeopleData[0].displayName, + {}, + { timeout: 3000 }, + ); }); - await sleep(500); - - const qontoChip = (await canvas.findAllByTestId('menu-item')).find( - (item) => { - return item.textContent?.includes('Qonto'); - }, - ); - - expect(qontoChip).toBeInTheDocument(); - - assert(qontoChip); - - await userEvent.click(qontoChip); - - // TODO: fix msw where clauses - // expect(await canvas.findByText('Alexandre Prot')).toBeInTheDocument(); - // await expect(canvas.queryAllByText('John Doe')).toStrictEqual([]); - - const companyFilter = canvas.getAllByText('Company').find((item) => { - return item.parentElement?.textContent?.includes('Company: Qonto'); + await step('Click on filter button', async () => { + const filterButton = canvas.getByText('Filter'); + await userEvent.click(filterButton); + }); + + await step('Select company filter', async () => { + const companyFilterButton = canvas.getByTestId('select-filter-3'); + await userEvent.click(companyFilterButton); + + const companyNameInput = canvas.getByPlaceholderText('Company'); + await userEvent.type(companyNameInput, 'Qon', { delay: 200 }); + + const qontoChip = await canvas.findByRole( + 'listitem', + { name: (_, element) => !!element?.textContent?.includes('Qonto') }, + { timeout: 1000 }, + ); + await userEvent.click(qontoChip); + + const companyFilter = canvas.getAllByText( + (_, element) => !!element?.textContent?.includes('Company: Qonto'), + ); + expect(companyFilter).not.toHaveLength(0); + }); + + await sleep(1000); + + await step('Check filtered rows', async () => { + expect(canvas.getByText('Alexandre Prot')).toBeVisible(); + expect(canvas.queryByText('John Doe')).toBeNull(); }); - expect(companyFilter).toBeInTheDocument(); }, }; diff --git a/front/src/pages/people/__stories__/People.inputs.stories.tsx b/front/src/pages/people/__stories__/People.inputs.stories.tsx index ff6be56fa..3b34d2c4b 100644 --- a/front/src/pages/people/__stories__/People.inputs.stories.tsx +++ b/front/src/pages/people/__stories__/People.inputs.stories.tsx @@ -1,21 +1,14 @@ -import { getOperationName } from '@apollo/client/utilities'; -import { isString } from '@sniptt/guards'; import { expect } from '@storybook/jest'; import { Meta } from '@storybook/react'; import { userEvent, within } from '@storybook/testing-library'; -import { graphql } from 'msw'; +import assert from 'assert'; -import { UPDATE_ONE_PERSON } from '@/people/graphql/mutations/updateOnePerson'; -import { SEARCH_COMPANY_QUERY } from '@/search/graphql/queries/searchCompanyQuery'; import { AppPath } from '@/types/AppPath'; -import { Company } from '~/generated/graphql'; import { PageDecorator, PageDecoratorArgs, } from '~/testing/decorators/PageDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; -import { fetchOneFromData } from '~/testing/mock-data'; -import { mockedCompaniesData } from '~/testing/mock-data/companies'; import { mockedPeopleData } from '~/testing/mock-data/people'; import { sleep } from '~/testing/sleep'; @@ -41,29 +34,23 @@ export const InteractWithManyRows: Story = { const firstRowEmailCell = await canvas.findByText( mockedPeopleData[0].email, + {}, + { timeout: 3000 }, ); + assert(firstRowEmailCell.parentElement); - const secondRowEmailCell = await canvas.findByText( - mockedPeopleData[1].email, - ); + const secondRowEmailCell = canvas.getByText(mockedPeopleData[1].email); + assert(secondRowEmailCell.parentElement); expect( canvas.queryByTestId('editable-cell-edit-mode-container'), ).toBeNull(); - if (!firstRowEmailCell.parentElement) { - throw new Error('No parent node'); - } - await userEvent.click(firstRowEmailCell.parentElement); expect( - canvas.queryByTestId('editable-cell-edit-mode-container'), - ).toBeInTheDocument(); - - if (!secondRowEmailCell.parentElement) { - throw new Error('No parent node'); - } + canvas.getByTestId('editable-cell-edit-mode-container'), + ).toBeVisible(); await userEvent.click(secondRowEmailCell.parentElement); @@ -75,220 +62,138 @@ export const InteractWithManyRows: Story = { await userEvent.click(secondRowEmailCell.parentElement); - await sleep(25); - expect( - canvas.queryByTestId('editable-cell-edit-mode-container'), - ).toBeInTheDocument(); + canvas.getByTestId('editable-cell-edit-mode-container'), + ).toBeVisible(); }, }; export const CheckCheckboxes: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); - await canvas.findByText(mockedPeopleData[0].email); + await step('Wait for rows to appear', async () => { + await canvas.findByText( + mockedPeopleData[0].displayName, + {}, + { timeout: 3000 }, + ); + }); - const inputCheckboxContainers = await canvas.findAllByTestId( - 'input-checkbox', - ); + const [, firstRowCheckbox, secondRowCheckbox] = + canvas.getAllByRole('checkbox'); - const inputCheckboxes = await canvas.findAllByTestId('input-checkbox'); + await step('Select first row', async () => { + assert(firstRowCheckbox.parentElement); - const secondCheckboxContainer = inputCheckboxContainers[1]; - const secondCheckbox = inputCheckboxes[1] as HTMLInputElement; + await userEvent.click(firstRowCheckbox.parentElement); + await sleep(25); - expect(secondCheckboxContainer).toBeDefined(); + expect(firstRowCheckbox).toBeChecked(); + }); - await userEvent.click(secondCheckboxContainer); + await step('Select second row', async () => { + await userEvent.click(secondRowCheckbox); + await sleep(25); - expect(secondCheckbox.checked).toBe(true); + expect(secondRowCheckbox).toBeChecked(); + }); - await userEvent.click(secondCheckbox); + await step('Unselect second row', async () => { + assert(secondRowCheckbox.parentElement); - expect(secondCheckbox.checked).toBe(false); + await userEvent.click(secondRowCheckbox.parentElement); + await sleep(25); + + expect(secondRowCheckbox).not.toBeChecked(); + }); }, }; -const editRelationMocks = ( - initiallySelectedCompanyName: string, - searchCompanyNames: Array, - updateSelectedCompany: Pick, -) => [ - ...graphqlMocks.filter((graphqlMock) => { - if ( - isString(graphqlMock.info.operationName) && - [ - getOperationName(UPDATE_ONE_PERSON), - getOperationName(SEARCH_COMPANY_QUERY), - ].includes(graphqlMock.info.operationName) - ) { - return false; - } - return true; - }), - ...[ - graphql.mutation( - getOperationName(UPDATE_ONE_PERSON) ?? '', - (req, res, ctx) => { - return res( - ctx.data({ - updateOnePerson: { - ...fetchOneFromData(mockedPeopleData, req.variables.where.id), - ...{ - company: { - id: req.variables.where.id, - name: updateSelectedCompany.name, - domainName: updateSelectedCompany.domainName, - __typename: 'Company', - }, - }, - }, - }), - ); - }, - ), - graphql.query( - getOperationName(SEARCH_COMPANY_QUERY) ?? '', - (req, res, ctx) => { - if (!req.variables.where?.AND) { - // Selected company case - const searchResults = mockedCompaniesData.filter((company) => - [initiallySelectedCompanyName].includes(company.name), - ); - return res( - ctx.data({ - searchResults: searchResults, - }), - ); - } - - if ( - req.variables.where?.AND?.some( - (where: { id?: { in: Array } }) => where.id?.in, - ) - ) { - // Selected company case - const searchResults = mockedCompaniesData.filter((company) => - [initiallySelectedCompanyName].includes(company.name), - ); - return res( - ctx.data({ - searchResults: searchResults, - }), - ); - } else { - // Search case - - const searchResults = mockedCompaniesData.filter((company) => - searchCompanyNames.includes(company.name), - ); - return res( - ctx.data({ - searchResults: searchResults, - }), - ); - } - }, - ), - ], -]; - export const EditRelation: Story = { play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); - await step('Click on second row company cell', async () => { - const secondRowCompanyCell = await canvas.findByText( + await step('Click on third row company cell', async () => { + const thirdRowCompanyCell = await canvas.findByText( mockedPeopleData[2].company.name, + {}, + { timeout: 3000 }, ); - await userEvent.click( - secondRowCompanyCell.parentNode?.parentNode?.parentNode - ?.parentElement as HTMLElement, - ); + await userEvent.click(thirdRowCompanyCell); }); await step('Type "Air" in relation picker', async () => { - const relationInput = await canvas.findByPlaceholderText('Search'); + const relationSearchInput = canvas.getByPlaceholderText('Search'); - await userEvent.type(relationInput, 'Air', { - delay: 200, - }); + await userEvent.type(relationSearchInput, 'Air', { delay: 200 }); }); await step('Select "Airbnb"', async () => { - const airbnbChip = await canvas.findByText('Airbnb', { - selector: 'div', + const airbnbChip = await canvas.findByRole('listitem', { + name: (_, element) => !!element?.textContent?.includes('Airbnb'), }); await userEvent.click(airbnbChip); }); - await step('Check if Airbnb is in second row company cell', async () => { - await canvas.findByText('Airbnb'); + await step('Check if Airbnb is in the table', async () => { + expect( + await canvas.findByText('Airbnb', {}, { timeout: 3000 }), + ).toBeVisible(); }); }, - parameters: { - msw: editRelationMocks('Qonto', ['Airbnb', 'Aircall'], { - name: 'Airbnb', - domainName: 'airbnb.com', - }), - }, }; export const SelectRelationWithKeys: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); - let firstRowCompanyCell = await canvas.findByText( - mockedPeopleData[0].company.name, - ); - await sleep(25); + await step('Click on first row company cell', async () => { + const firstRowCompanyCell = await canvas.findByText( + mockedPeopleData[0].company.name, + {}, + { timeout: 3000 }, + ); - await userEvent.click( - firstRowCompanyCell.parentNode?.parentNode?.parentNode - ?.parentElement as HTMLElement, - ); - firstRowCompanyCell = await canvas.findByText( - mockedPeopleData[0].company.name, - ); - await sleep(25); - await userEvent.click(firstRowCompanyCell); - - const relationInput = await canvas.findByPlaceholderText('Search'); - - await userEvent.type(relationInput, 'Air', { - delay: 200, + await userEvent.click(firstRowCompanyCell); }); - await userEvent.type(relationInput, '{arrowdown}'); + const relationSearchInput = canvas.getByPlaceholderText('Search'); - await sleep(50); + await step('Type "Air" in relation picker', async () => { + await userEvent.type(relationSearchInput, 'Air', { delay: 200 }); + }); - await userEvent.type(relationInput, '{arrowup}'); + await step('Select "Aircall"', async () => { + await userEvent.keyboard('{arrowdown}'); - await sleep(50); + await sleep(50); - await userEvent.type(relationInput, '{arrowdown}'); + await userEvent.keyboard('{arrowup}'); - await sleep(50); + await sleep(50); - await userEvent.type(relationInput, '{arrowdown}'); + await userEvent.keyboard('{arrowdown}'); - await sleep(50); + await sleep(50); - await userEvent.type(relationInput, '{enter}'); + await userEvent.keyboard('{arrowdown}'); - await sleep(200); + await sleep(50); - const allAirbns = await canvas.findAllByText('Aircall'); - expect(allAirbns.length).toBe(1); - }, - parameters: { - msw: editRelationMocks('Qonto', ['Airbnb', 'Aircall'], { - name: 'Aircall', - domainName: 'aircall.io', - }), + await userEvent.keyboard('{arrowdown}'); + + await sleep(50); + + await userEvent.keyboard('{enter}'); + }); + + await step('Check if Aircall is in the table', async () => { + expect( + await canvas.findByText('Aircall', {}, { timeout: 3000 }), + ).toBeVisible(); + }); }, }; diff --git a/front/src/pages/people/__stories__/People.sortBy.stories.tsx b/front/src/pages/people/__stories__/People.sortBy.stories.tsx index 03a1b3c4e..be3600e58 100644 --- a/front/src/pages/people/__stories__/People.sortBy.stories.tsx +++ b/front/src/pages/people/__stories__/People.sortBy.stories.tsx @@ -8,6 +8,7 @@ import { PageDecoratorArgs, } from '~/testing/decorators/PageDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; +import { mockedPeopleData } from '~/testing/mock-data/people'; import { sleep } from '~/testing/sleep'; import { People } from '../People'; @@ -26,41 +27,98 @@ const meta: Meta = { export default meta; +const peopleEmails = mockedPeopleData.map(({ email }) => email); +const sortedPeopleEmails = peopleEmails.toSorted(); + export const Email: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); - const sortButton = await canvas.findByText('Sort'); - await userEvent.click(sortButton); + await step('Wait for rows to appear', async () => { + await canvas.findByText( + mockedPeopleData[0].displayName, + {}, + { timeout: 3000 }, + ); + }); - const emailSortButton = await canvas.findByTestId('select-sort-2'); - await userEvent.click(emailSortButton); + await step('Click on sort button', async () => { + const sortButton = canvas.getByRole('button', { name: 'Sort' }); + await userEvent.click(sortButton); + }); - expect(await canvas.getByTestId('remove-icon-email')).toBeInTheDocument(); + await step('Select sort by email', async () => { + const emailSortButton = canvas.getByTestId('select-sort-2'); + await userEvent.click(emailSortButton); - expect(await canvas.findByText('Alexandre Prot')).toBeInTheDocument(); + await canvas.findByTestId('remove-icon-email', {}, { timeout: 3000 }); + }); + + await sleep(1000); + + await step('Check rows are sorted by email', async () => { + const emailCells = canvas.getAllByText( + (_, element) => + sortedPeopleEmails.some((email) => + element?.textContent?.includes(email), + ), + { selector: '[data-testid="editable-cell-display-mode"]' }, + ); + + expect(emailCells).toHaveLength(sortedPeopleEmails.length); + + sortedPeopleEmails.forEach((email, index) => + expect(emailCells[index]).toHaveTextContent(email), + ); + }); }, }; export const Reset: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); - const sortButton = await canvas.findByText('Sort'); - await userEvent.click(sortButton); + await step('Wait for rows to appear', async () => { + await canvas.findByText( + mockedPeopleData[0].displayName, + {}, + { timeout: 3000 }, + ); + }); - const emailSortButton = await canvas.findByTestId('select-sort-2'); - await userEvent.click(emailSortButton); + await step('Click on sort button', async () => { + const sortButton = canvas.getByRole('button', { name: 'Sort' }); + await userEvent.click(sortButton); + }); - expect(await canvas.getByTestId('remove-icon-email')).toBeInTheDocument(); + await step('Select sort by email', async () => { + const emailSortButton = canvas.getByTestId('select-sort-2'); + await userEvent.click(emailSortButton); - const resetButton = canvas.getByText('Reset'); - await userEvent.click(resetButton); + expect( + await canvas.findByTestId('remove-icon-email'), + ).toBeInTheDocument(); + }); - await sleep(1000); + await step('Click on reset button', async () => { + const resetButton = canvas.getByRole('button', { name: 'Reset' }); + await userEvent.click(resetButton); - await expect(canvas.queryAllByTestId('remove-icon-email')).toStrictEqual( - [], - ); + expect(canvas.queryByTestId('remove-icon-email')).toBeNull(); + }); + + await step('Check rows are in initial order', async () => { + const emailCells = canvas.getAllByText( + (_, element) => + peopleEmails.some((email) => element?.textContent?.includes(email)), + { selector: '[data-testid="editable-cell-display-mode"]' }, + ); + + expect(emailCells).toHaveLength(peopleEmails.length); + + peopleEmails.forEach((email, index) => + expect(emailCells[index]).toHaveTextContent(email), + ); + }); }, }; diff --git a/front/src/testing/graphqlMocks.ts b/front/src/testing/graphqlMocks.ts index 6cd4f7d91..1976c7f90 100644 --- a/front/src/testing/graphqlMocks.ts +++ b/front/src/testing/graphqlMocks.ts @@ -33,12 +33,17 @@ import { import { mockedApiKeys } from '~/testing/mock-data/api-keys'; import { mockedActivities, mockedTasks } from './mock-data/activities'; -import { mockedCompaniesData } from './mock-data/companies'; +import { + mockedCompaniesData, + mockedEmptyCompanyData, +} from './mock-data/companies'; import { mockedObjectMetadataItems } from './mock-data/metadata'; -import { mockedPeopleData } from './mock-data/people'; +import { mockedEmptyPersonData, mockedPeopleData } from './mock-data/people'; import { mockedPipelineProgressData } from './mock-data/pipeline-progress'; import { mockedPipelinesData } from './mock-data/pipelines'; import { mockedUsersData } from './mock-data/users'; +import { mockedViewFieldsData } from './mock-data/view-fields'; +import { mockedViewsData } from './mock-data/views'; import { fetchOneFromData, filterAndSortData, @@ -73,7 +78,7 @@ export const graphqlMocks = [ >( mockedCompaniesData, req.variables.where, - Array.isArray(req.variables.orderBy) + !req.variables.orderBy || Array.isArray(req.variables.orderBy) ? req.variables.orderBy : [req.variables.orderBy], req.variables.limit, @@ -93,7 +98,7 @@ export const graphqlMocks = [ >( mockedPeopleData, req.variables.where, - Array.isArray(req.variables.orderBy) + !req.variables.orderBy || Array.isArray(req.variables.orderBy) ? req.variables.orderBy : [req.variables.orderBy], req.variables.limit, @@ -128,7 +133,7 @@ export const graphqlMocks = [ >( mockedActivities, req.variables.where, - Array.isArray(req.variables.orderBy) + !req.variables.orderBy || Array.isArray(req.variables.orderBy) ? req.variables.orderBy : [req.variables.orderBy], req.variables.limit, @@ -173,13 +178,31 @@ export const graphqlMocks = [ graphql.mutation( getOperationName(UPDATE_ONE_PERSON) ?? '', (req, res, ctx) => { + const updatedCompanyId = req.variables.data?.company?.connect?.id; + const updatedCompany = mockedCompaniesData.find( + ({ id }) => id === updatedCompanyId, + ); + const updatedCompanyData = updatedCompany + ? { + companyId: updatedCompany.id, + company: { + id: updatedCompany.id, + name: updatedCompany.name, + domainName: updatedCompany.domainName, + __typename: 'Company', + }, + } + : {}; return res( ctx.data({ - updateOnePerson: updateOneFromData( - mockedPeopleData, - req.variables.where.id, - req.variables, - ), + updateOnePerson: { + ...updateOneFromData( + mockedPeopleData, + req.variables.where.id, + req.variables, + ), + ...updatedCompanyData, + }, }), ); }, @@ -267,8 +290,8 @@ export const graphqlMocks = [ return res( ctx.data({ createOneCompany: { - id: '9d162de1-cfbf-4156-a790-e39854dcd4ef', - __typename: 'Company', + ...mockedEmptyCompanyData, + ...req.variables.data, }, }), ); @@ -280,8 +303,8 @@ export const graphqlMocks = [ return res( ctx.data({ createOnePerson: { - id: '9d162de1-cfbf-4156-a790-e39854dcd4ef', - __typename: 'Person', + ...mockedEmptyPersonData, + ...req.variables.data, }, }), ); @@ -293,4 +316,39 @@ export const graphqlMocks = [ return res(ctx.data({ objects: mockedObjectMetadataItems })); }, ), + graphql.query('FindManyviewsV2', (req, res, ctx) => { + const objectId = req.variables.filter.objectId.eq; + const viewType = req.variables.filter.type.eq; + + return res( + ctx.data({ + viewsV2: { + edges: mockedViewsData + .filter( + (view) => view.objectId === objectId && view.type === viewType, + ) + .map((view) => ({ + node: view, + cursor: null, + })), + }, + }), + ); + }), + graphql.query('FindManyviewFieldsV2', (req, res, ctx) => { + const viewId = req.variables.filter.viewId.eq; + + return res( + ctx.data({ + viewFieldsV2: { + edges: mockedViewFieldsData + .filter((viewField) => viewField.viewId === viewId) + .map((viewField) => ({ + node: viewField, + cursor: null, + })), + }, + }), + ); + }), ]; diff --git a/front/src/testing/mock-data/companies.ts b/front/src/testing/mock-data/companies.ts index 81c934d6e..7e167ae2a 100644 --- a/front/src/testing/mock-data/companies.ts +++ b/front/src/testing/mock-data/companies.ts @@ -1,5 +1,7 @@ import { Company, Favorite, User } from '~/generated/graphql'; +import { mockedUsersData } from './users'; + type MockedCompany = Pick< Company, | 'id' @@ -14,6 +16,7 @@ type MockedCompany = Pick< | 'annualRecurringRevenue' | 'idealCustomerProfile' | '_activityCount' + | 'accountOwnerId' > & { accountOwner: Pick< User, @@ -25,7 +28,8 @@ type MockedCompany = Pick< | 'firstName' | 'lastName' > | null; -} & { Favorite: Pick | null }; + Favorite: Pick | null; +}; export const mockedCompaniesData: Array = [ { @@ -41,13 +45,14 @@ export const mockedCompaniesData: Array = [ idealCustomerProfile: true, _activityCount: 1, Favorite: null, + accountOwnerId: mockedUsersData[0].id, accountOwner: { email: 'charles@test.com', displayName: 'Charles Test', firstName: 'Charles', lastName: 'Test', avatarUrl: null, - id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b', + id: mockedUsersData[0].id, __typename: 'User', }, __typename: 'Company', @@ -149,3 +154,19 @@ export const mockedCompaniesData: Array = [ __typename: 'Company', }, ]; + +export const mockedEmptyCompanyData = { + id: '9231e6ee-4cc2-4c7b-8c55-dff16f4d968a', + name: '', + domainName: '', + address: '', + accountOwner: null, + annualRecurringRevenue: null, + createdAt: null, + employees: null, + idealCustomerProfile: null, + linkedinUrl: null, + xUrl: null, + _activityCount: null, + __typename: 'Company', +}; diff --git a/front/src/testing/mock-data/index.ts b/front/src/testing/mock-data/index.ts index 1ab5052e5..0ec54e945 100644 --- a/front/src/testing/mock-data/index.ts +++ b/front/src/testing/mock-data/index.ts @@ -103,7 +103,7 @@ export const filterAndSortData = ( filteredData = filterData(data, where); } - if (orderBy && Array.isArray(orderBy) && orderBy.length > 0 && orderBy[0]) { + if (Array.isArray(orderBy) && orderBy.length > 0 && orderBy[0]) { const firstOrderBy = orderBy[0]; const key = Object.keys(firstOrderBy)[0]; diff --git a/front/src/testing/mock-data/metadata.ts b/front/src/testing/mock-data/metadata.ts index 0c18b1a14..7bff83720 100644 --- a/front/src/testing/mock-data/metadata.ts +++ b/front/src/testing/mock-data/metadata.ts @@ -1,5 +1,187 @@ export const mockedObjectMetadataItems = { edges: [ + { + node: { + id: 'b25eb5e6-9fdc-4df2-a039-40ccea4c8032', + dataSourceId: '', + nameSingular: 'viewV2', + namePlural: 'viewsV2', + labelSingular: 'View', + labelPlural: 'Views', + description: '(System) Views', + icon: 'IconLayoutCollage', + isCustom: false, + isActive: true, + createdAt: '', + updatedAt: '', + fields: { + edges: [ + { + node: { + id: '5db475e7-8208-402d-97a1-62c9ce344dd4', + type: 'text', + name: 'objectId', + label: 'Object Id', + description: 'View target object', + icon: null, + placeholder: null, + isCustom: false, + isActive: true, + isNullable: false, + createdAt: '', + updatedAt: '', + }, + }, + { + node: { + id: 'ddc89a56-9add-4110-aa53-4ecdbba36767', + type: 'text', + name: 'type', + label: 'Type', + description: 'View type', + icon: null, + placeholder: null, + isCustom: false, + isActive: true, + isNullable: false, + createdAt: '', + updatedAt: '', + }, + }, + { + node: { + id: '35fa806b-5d9d-446d-bd0e-1a6874b871ee', + type: 'text', + name: 'name', + label: 'Name', + description: 'View name', + icon: null, + placeholder: null, + isCustom: false, + isActive: true, + isNullable: false, + createdAt: '', + updatedAt: '', + }, + }, + ], + pageInfo: { + hasNextPage: false, + hasPreviousPage: false, + startCursor: null, + endCursor: null, + }, + totalCount: 3, + }, + }, + }, + { + node: { + id: 'c419540f-ff6e-47bf-9d87-3aa366afd8e4', + dataSourceId: '', + nameSingular: 'viewFieldV2', + namePlural: 'viewFieldsV2', + labelSingular: 'View Field', + labelPlural: 'View Fields', + description: '(System) View Fields', + icon: 'IconColumns3', + isCustom: false, + isActive: true, + createdAt: '', + updatedAt: '', + fields: { + edges: [ + { + node: { + id: '1d718fcf-5a17-4694-91a4-4d3968a51aa4', + type: 'text', + name: 'viewId', + label: 'View Id', + description: 'View Field related view', + icon: null, + placeholder: null, + isCustom: false, + isActive: true, + isNullable: false, + createdAt: '', + updatedAt: '', + }, + }, + { + node: { + id: '8ead2e86-7b60-4a47-9b4f-ad008e744d52', + type: 'number', + name: 'position', + label: 'Position', + description: 'View Field position', + icon: null, + placeholder: null, + isCustom: false, + isActive: true, + isNullable: false, + createdAt: '', + updatedAt: '', + }, + }, + { + node: { + id: '4d77c2dd-2b04-4989-b11e-cb0e386d1b4d', + type: 'text', + name: 'fieldId', + label: 'Field Id', + description: 'View Field target field', + icon: null, + placeholder: null, + isCustom: false, + isActive: true, + isNullable: false, + createdAt: '', + updatedAt: '', + }, + }, + { + node: { + id: '0f5ab566-9fc4-44b7-85c5-1e05db9f6b49', + type: 'boolean', + name: 'isVisible', + label: 'Visible', + description: 'View Field visibility', + icon: null, + placeholder: null, + isCustom: false, + isActive: true, + isNullable: false, + createdAt: '', + updatedAt: '', + }, + }, + { + node: { + id: '21268ece-7002-4b04-a442-f25278f8ca13', + type: 'number', + name: 'size', + label: 'Size', + description: 'View Field size', + icon: null, + placeholder: null, + isCustom: false, + isActive: true, + isNullable: false, + createdAt: '', + updatedAt: '', + }, + }, + ], + pageInfo: { + hasNextPage: false, + hasPreviousPage: false, + startCursor: null, + endCursor: null, + }, + totalCount: 5, + }, + }, + }, { node: { id: 'a3195559-cc20-4749-9565-572a2f506581', @@ -175,5 +357,5 @@ export const mockedObjectMetadataItems = { startCursor: null, endCursor: null, }, - totalCount: 2, + totalCount: 4, }; diff --git a/front/src/testing/mock-data/people.ts b/front/src/testing/mock-data/people.ts index a1980f687..98e13d100 100644 --- a/front/src/testing/mock-data/people.ts +++ b/front/src/testing/mock-data/people.ts @@ -21,6 +21,7 @@ type MockedPerson = RequiredAndNotNull< | 'avatarUrl' | '_activityCount' | 'createdAt' + | 'companyId' > & { company: Pick; } @@ -39,6 +40,7 @@ export const mockedPeopleData: MockedPerson[] = [ avatarUrl: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAADygAwAEAAAAAQAAADwAAAAA/+0AOFBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAAOEJJTQQlAAAAAAAQ1B2M2Y8AsgTpgAmY7PhCfv/AABEIADwAPAMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2wBDAAoHCBUSFRgSEhUYGBgYGBgYGBgYGBgYGBgYGBgZGRgaGBgcIS4lHB4rIRgYJjgmKy8xNTU1GiQ7QDszPy40NTH/2wBDAQwMDBAPEBwSEh40ISQkMTQ0NjQxNDQ2NDQ0NDQ0MTQ0NDQ0NDQ0NDQ0NDE0NDQ0NDQ0PzQ0NDQ0NDQ0NDQ0NDT/3QAEAAT/2gAMAwEAAhEDEQA/AOtApcUtLWpkJiub1TxlawHaC0pGM+WAQM9ixIGfal8bas8ESwwjMs5KLjqq4+ZgO55A/wCBe1cDceGLxVyYCysOqfNjnoQOQfzqJTs7GkYNq53uleLba5KoCyO2fldcDI7b/uk/jW8VrxSSJowQ6OPqhwPxxXofw81Mz27IxyYmCjPUKRlee/f8qIyuKUbHT4oxT6SrIP/Q6+ilorUyOJ147tTjzjbFArEk4A3M/wD9au20u4Rl+R1bHXawJFZ89vGbgM4GWj2898HI/rTbXSIo5lkj5fpuyWO3upPccVx1H7zO6nH3EizroBjbIB/KuL+H0eJ7soMIBGPx3Ocfkf1rUbRPPzM0jYYtv3MTjkjCDOF7flS+C7Hyo5XznzZSRxjhAEH16E1VH4ia/wAJ0dFFLXUcZ//R7HFIRWXq/iS1teJZRu6hEG9+/JC9Bx1OK43VPiM7ZW2iCejyHc34Ivyj8zWpmdtqkiq8QfoxYe3bGfryKbNb8HEzIwyUYKCQCOnbP0IPasPwtKb+3JlcvICUck8hgSVYAcLkFSMelSya3LbL5U8Bl28K67efTcD0P0rjm7zZ3UtIocsZEQhDEu5IXrnaTks+Scnqa3LWBY1EaDCqMDkn9TXCSapNBIb+ZR0ZRGSQArY+Vf8Aa4GD9a6XRvE9tdYCuFc/8s3IVvw7MPcVtRStcwrybZuilpopa2Oc/9Ly0J/kUBaVTS1sZl7SNWmtH8yB9pPBBGVYZzhl7j9R611T/ERmHzWqFvXzDt+uNuevb9a4eiolCMtyozlHYu6zrE12QZSAF+6ijCjPfHc+5/Ss3bUlFUkkrITbbuze8P8Aiqe0IDMZIsjcjEsQOh8ticqcduhx26163FKGUMpyGAII6EEZBrwQmvX/AAFIXso93O0ug/3Vdgo/KmI//9k=', jobTitle: 'CEO', + companyId: '5c21e19e-e049-4393-8c09-3e3f8fb09ecb', company: { id: '5c21e19e-e049-4393-8c09-3e3f8fb09ecb', name: 'Qonto', @@ -48,7 +50,6 @@ export const mockedPeopleData: MockedPerson[] = [ phone: '06 12 34 56 78', _activityCount: 1, createdAt: '2023-04-20T13:20:09.158312+00:00', - city: 'Paris', }, { @@ -62,6 +63,7 @@ export const mockedPeopleData: MockedPerson[] = [ avatarUrl: '', jobTitle: 'CTO', email: 'john@linkedin.com', + companyId: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6e', company: { id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6e', name: 'LinkedIn', @@ -71,7 +73,6 @@ export const mockedPeopleData: MockedPerson[] = [ phone: '06 12 34 56 78', _activityCount: 1, createdAt: '2023-04-20T13:20:09.158312+00:00', - city: 'Paris', }, { @@ -85,6 +86,7 @@ export const mockedPeopleData: MockedPerson[] = [ avatarUrl: '', jobTitle: 'Investor', email: 'jane@sequoiacap.com', + companyId: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6g', company: { id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6g', name: 'Sequoia', @@ -94,7 +96,6 @@ export const mockedPeopleData: MockedPerson[] = [ phone: '06 12 34 56 78', _activityCount: 1, createdAt: '2023-04-20T13:20:09.158312+00:00', - city: 'Paris', }, { @@ -108,6 +109,7 @@ export const mockedPeopleData: MockedPerson[] = [ xUrl: 'https://twitter.com/janicedane', avatarUrl: '', jobTitle: 'CEO', + companyId: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6i', company: { id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6i', name: 'Facebook', @@ -117,7 +119,24 @@ export const mockedPeopleData: MockedPerson[] = [ phone: '06 12 34 56 78', _activityCount: 2, createdAt: '2023-04-20T13:20:09.158312+00:00', - city: 'Paris', }, ]; + +export const mockedEmptyPersonData = { + id: 'ce7f0a37-88d7-4cd8-8b41-6721c57195b5', + firstName: '', + lastName: '', + phone: null, + email: null, + city: null, + displayName: null, + avatarUrl: null, + createdAt: null, + jobTitle: null, + linkedinUrl: null, + xUrl: null, + _activityCount: null, + company: null, + __typename: 'Person', +}; diff --git a/front/src/testing/mock-data/view-fields.ts b/front/src/testing/mock-data/view-fields.ts new file mode 100644 index 000000000..4bb4f8977 --- /dev/null +++ b/front/src/testing/mock-data/view-fields.ts @@ -0,0 +1,185 @@ +import { mockedViewsData } from './views'; + +export const mockedViewFieldsData = [ + // Companies + { + id: '79035310-e955-4986-a4a4-73f9d9949c6a', + fieldId: 'name', + viewId: mockedViewsData[0].id, + position: 0, + isVisible: true, + size: 180, + }, + { + id: '2a96bbc8-d86d-439a-8e50-4b07ebd27750', + fieldId: 'domainName', + viewId: mockedViewsData[0].id, + position: 1, + isVisible: true, + size: 100, + }, + { + id: '0c1b4c7b-6a3d-4fb0-bf2b-5d7c8fb844ed', + fieldId: 'accountOwner', + viewId: mockedViewsData[0].id, + position: 2, + isVisible: true, + size: 150, + }, + { + id: 'cc7f9560-32b5-4b82-8fd9-b05fe77c8cf7', + fieldId: 'createdAt', + viewId: mockedViewsData[0].id, + position: 3, + isVisible: true, + size: 150, + }, + { + id: '3de4d078-3396-4480-be2d-6f3b1a228b0d', + fieldId: 'employees', + viewId: mockedViewsData[0].id, + position: 4, + isVisible: true, + size: 150, + }, + { + id: '4650c8fb-0f1e-4342-88dc-adedae1445f9', + fieldId: 'linkedin', + viewId: mockedViewsData[0].id, + position: 5, + isVisible: true, + size: 170, + }, + { + id: '727430bf-6ff8-4c85-9828-cbe72ac0fc27', + fieldId: 'address', + viewId: mockedViewsData[0].id, + position: 6, + isVisible: true, + size: 170, + }, + + // People + { + id: '28894146-4fde-4a16-a9ca-1a31b5b788b4', + fieldId: 'displayName', + viewId: mockedViewsData[1].id, + position: 0, + isVisible: true, + size: 210, + }, + { + id: 'e1e24864-8601-4cd8-8a63-09c1285f2e39', + fieldId: 'email', + viewId: mockedViewsData[1].id, + position: 1, + isVisible: true, + size: 150, + }, + { + id: '5a1df716-7211-445a-9f16-9783a00998a7', + fieldId: 'company', + viewId: mockedViewsData[1].id, + position: 2, + isVisible: true, + size: 150, + }, + { + id: 'a6e1197a-7e84-4d92-ace2-367c0bc46c49', + fieldId: 'phone', + viewId: mockedViewsData[1].id, + position: 3, + isVisible: true, + size: 150, + }, + { + id: 'c9343097-d14b-4559-a5fa-626c1527d39f', + fieldId: 'createdAt', + viewId: mockedViewsData[1].id, + position: 4, + isVisible: true, + size: 150, + }, + { + id: 'a873e5f0-fed6-47e9-a712-6854eab3ec77', + fieldId: 'city', + viewId: mockedViewsData[1].id, + position: 5, + isVisible: true, + size: 150, + }, + { + id: '66f134b8-5329-422f-b88e-83e6bb707eb5', + fieldId: 'jobTitle', + viewId: mockedViewsData[1].id, + position: 6, + isVisible: true, + size: 150, + }, + { + id: '648faa24-cabb-482a-8578-ba3f09906017', + fieldId: 'linkedin', + viewId: mockedViewsData[1].id, + position: 7, + isVisible: true, + size: 150, + }, + { + id: '3a9e7f0d-a4ce-4ad5-aac7-3a24eb1a412d', + fieldId: 'x', + viewId: mockedViewsData[1].id, + position: 8, + isVisible: true, + size: 150, + }, + + // Opportunities + { + id: '35a42e2d-83dd-4b57-ada6-f90616da706d', + fieldId: 'amount', + viewId: mockedViewsData[2].id, + position: 0, + isVisible: true, + size: 180, + }, + { + id: 'e5a731bb-82b9-4abe-ad22-1ddea94722f9', + fieldId: 'probability', + viewId: mockedViewsData[2].id, + position: 1, + isVisible: true, + size: 150, + }, + { + id: '3159acd8-463f-458d-bf9a-af8ac6f57dc0', + fieldId: 'closeDate', + viewId: mockedViewsData[2].id, + position: 2, + isVisible: true, + size: 100, + }, + { + id: 'afc0819d-b694-4e3c-a2e6-25261aa3ed2c', + fieldId: 'company', + viewId: mockedViewsData[2].id, + position: 3, + isVisible: true, + size: 150, + }, + { + id: 'ec0507bb-aedc-4695-ba96-d81bdeb9db83', + fieldId: 'createdAt', + viewId: mockedViewsData[2].id, + position: 4, + isVisible: true, + size: 150, + }, + { + id: '3f1585f6-44f6-45c5-b840-bc05af5d0008', + fieldId: 'pointOfContact', + viewId: mockedViewsData[2].id, + position: 5, + isVisible: true, + size: 150, + }, +]; diff --git a/front/src/testing/mock-data/views.ts b/front/src/testing/mock-data/views.ts new file mode 100644 index 000000000..35d45df92 --- /dev/null +++ b/front/src/testing/mock-data/views.ts @@ -0,0 +1,20 @@ +export const mockedViewsData = [ + { + id: '37a8a866-eb17-4e76-9382-03143a2f6a80', + name: 'All companies', + objectId: 'company', + type: 'table', + }, + { + id: '6095799e-b48f-4e00-b071-10818083593a', + name: 'All people', + objectId: 'person', + type: 'table', + }, + { + id: 'e26f66b7-f890-4a5c-b4d2-ec09987b5308', + name: 'All opportunities', + objectId: 'company', + type: 'kanban', + }, +];