From 93a9eb0e3c492fe3d754f401225134fc42e2a99f Mon Sep 17 00:00:00 2001 From: gitstart-twenty <140154534+gitstart-twenty@users.noreply.github.com> Date: Thu, 11 Jan 2024 10:37:09 +0100 Subject: [PATCH] Add tests for `modules/object-record/hooks` (#3361) * Add tests for `modules/object-record/hooks` Co-authored-by: v1b3m * Remove temporary changes Co-authored-by: v1b3m --------- Co-authored-by: gitstart-twenty Co-authored-by: v1b3m Co-authored-by: Charles Bochet --- packages/twenty-front/jest.config.ts | 1 - .../hooks/__mocks__/useCreateManyRecords.ts | 116 +++++++++++++ .../hooks/__mocks__/useCreateOneRecord.ts | 113 ++++++++++++ .../hooks/__mocks__/useDeleteManyRecords.ts | 24 +++ .../hooks/__mocks__/useDeleteOneRecord.ts | 17 ++ .../useExecuteQuickActionOnOneRecord.ts | 74 ++++++++ .../hooks/__mocks__/useFindManyRecords.ts | 164 ++++++++++++++++++ .../hooks/__mocks__/useFindOneRecord.ts | 79 +++++++++ .../hooks/__mocks__/useUpdateOneRecord.ts | 126 ++++++++++++++ .../__tests__/useCreateManyRecords.test.tsx | 63 +++++++ .../__tests__/useCreateOneRecord.test.tsx | 54 ++++++ .../__tests__/useDeleteManyRecords.test.tsx | 57 ++++++ .../__tests__/useDeleteOneRecord.test.tsx | 54 ++++++ .../useExecuteQuickActionOnOneRecord.test.tsx | 62 +++++++ .../__tests__/useFindManyRecords.test.tsx | 96 ++++++++++ .../hooks/__tests__/useFindOneRecord.test.tsx | 60 +++++++ ...ordsForMultipleMetadataItemsQuery.test.tsx | 30 ++++ .../useModifyRecordFromCache.test.tsx | 52 ++++++ .../__tests__/useObjectRecordBoard.test.tsx | 31 ++++ .../__tests__/useObjectRecordTable.test.tsx | 37 ++++ .../__tests__/useUpdateOneRecord.test.tsx | 62 +++++++ .../object-record/hooks/useDeleteOneRecord.ts | 2 +- 22 files changed, 1372 insertions(+), 2 deletions(-) create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateManyRecords.ts create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateOneRecord.ts create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__mocks__/useDeleteManyRecords.ts create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__mocks__/useDeleteOneRecord.ts create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__mocks__/useExecuteQuickActionOnOneRecord.ts create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__mocks__/useFindManyRecords.ts create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__mocks__/useFindOneRecord.ts create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__mocks__/useUpdateOneRecord.ts create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__tests__/useCreateManyRecords.test.tsx create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__tests__/useCreateOneRecord.test.tsx create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__tests__/useDeleteManyRecords.test.tsx create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__tests__/useDeleteOneRecord.test.tsx create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__tests__/useExecuteQuickActionOnOneRecord.test.tsx create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindManyRecords.test.tsx create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindOneRecord.test.tsx create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__tests__/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.test.tsx create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__tests__/useModifyRecordFromCache.test.tsx create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__tests__/useObjectRecordBoard.test.tsx create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__tests__/useObjectRecordTable.test.tsx create mode 100644 packages/twenty-front/src/modules/object-record/hooks/__tests__/useUpdateOneRecord.test.tsx diff --git a/packages/twenty-front/jest.config.ts b/packages/twenty-front/jest.config.ts index e3a50b3121..3f9960330a 100644 --- a/packages/twenty-front/jest.config.ts +++ b/packages/twenty-front/jest.config.ts @@ -37,6 +37,5 @@ export default { '__stories__/*', 'display/icon/index.ts', ], - testPathIgnorePatterns: ['src/modules/activities/blocks/spec.ts'], // coverageDirectory: '/coverage/', }; diff --git a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateManyRecords.ts b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateManyRecords.ts new file mode 100644 index 0000000000..e928f9947e --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateManyRecords.ts @@ -0,0 +1,116 @@ +import { gql } from '@apollo/client'; + +export const query = gql` + mutation CreatePeople($data: [PersonCreateInput!]!) { + createPeople(data: $data) { + id + opportunities { + edges { + node { + id + } + } + } + xLink { + label + url + } + id + pointOfContactForOpportunities { + edges { + node { + id + } + } + } + createdAt + company { + id + } + city + email + activityTargets { + edges { + node { + id + } + } + } + jobTitle + favorites { + edges { + node { + id + } + } + } + attachments { + edges { + node { + id + } + } + } + name { + firstName + lastName + } + phone + linkedinLink { + label + url + } + updatedAt + avatarUrl + companyId + } + } +`; + +export const variables = { + data: [ + { id: 'a7286b9a-c039-4a89-9567-2dfa7953cda9' }, + { id: '37faabcd-cb39-4a0a-8618-7e3fda9afca0' }, + ], +}; + +export const responseData = { + opportunities: { + edges: [], + }, + xLink: { + label: '', + url: '', + }, + pointOfContactForOpportunities: { + edges: [], + }, + createdAt: '', + company: { + id: '', + }, + city: '', + email: '', + activityTargets: { + edges: [], + }, + jobTitle: '', + favorites: { + edges: [], + }, + attachments: { + edges: [], + }, + name: { + firstName: '', + lastName: '', + }, + phone: '', + linkedinLink: { + label: '', + url: '', + }, + updatedAt: '', + avatarUrl: '', + companyId: '', +}; diff --git a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateOneRecord.ts b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateOneRecord.ts new file mode 100644 index 0000000000..426b120a78 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useCreateOneRecord.ts @@ -0,0 +1,113 @@ +import { gql } from '@apollo/client'; + +export const query = gql` + mutation CreateOnePerson($input: PersonCreateInput!) { + createPerson(data: $input) { + id + opportunities { + edges { + node { + id + } + } + } + xLink { + label + url + } + id + pointOfContactForOpportunities { + edges { + node { + id + } + } + } + createdAt + company { + id + } + city + email + activityTargets { + edges { + node { + id + } + } + } + jobTitle + favorites { + edges { + node { + id + } + } + } + attachments { + edges { + node { + id + } + } + } + name { + firstName + lastName + } + phone + linkedinLink { + label + url + } + updatedAt + avatarUrl + companyId + } + } +`; + +export const variables = { + input: { id: 'a7286b9a-c039-4a89-9567-2dfa7953cda9' }, +}; + +export const responseData = { + opportunities: { + edges: [], + }, + xLink: { + label: '', + url: '', + }, + pointOfContactForOpportunities: { + edges: [], + }, + createdAt: '', + company: { + id: '', + }, + city: '', + email: '', + activityTargets: { + edges: [], + }, + jobTitle: '', + favorites: { + edges: [], + }, + attachments: { + edges: [], + }, + name: { + firstName: '', + lastName: '', + }, + phone: '', + linkedinLink: { + label: '', + url: '', + }, + updatedAt: '', + avatarUrl: '', + companyId: '', +}; diff --git a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useDeleteManyRecords.ts b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useDeleteManyRecords.ts new file mode 100644 index 0000000000..dbe68fda0a --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useDeleteManyRecords.ts @@ -0,0 +1,24 @@ +import { gql } from '@apollo/client'; + +export const query = gql` + mutation DeleteManyPeople($filter: PersonFilterInput!) { + deletePeople(filter: $filter) { + id + } + } +`; + +export const variables = { + filter: { + id: { + in: [ + 'a7286b9a-c039-4a89-9567-2dfa7953cda9', + '37faabcd-cb39-4a0a-8618-7e3fda9afca0', + ], + }, + }, +}; + +export const responseData = { + id: '', +}; diff --git a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useDeleteOneRecord.ts b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useDeleteOneRecord.ts new file mode 100644 index 0000000000..f31b210e08 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useDeleteOneRecord.ts @@ -0,0 +1,17 @@ +import { gql } from '@apollo/client'; + +export const query = gql` + mutation DeleteOnePerson($idToDelete: ID!) { + deletePerson(id: $idToDelete) { + id + } + } +`; + +export const variables = { + idToDelete: 'a7286b9a-c039-4a89-9567-2dfa7953cda9', +}; + +export const responseData = { + id: 'a7286b9a-c039-4a89-9567-2dfa7953cda9', +}; diff --git a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useExecuteQuickActionOnOneRecord.ts b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useExecuteQuickActionOnOneRecord.ts new file mode 100644 index 0000000000..3614410ec2 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useExecuteQuickActionOnOneRecord.ts @@ -0,0 +1,74 @@ +import { gql } from '@apollo/client'; + +export { responseData } from './useUpdateOneRecord'; + +export const query = gql` + mutation ExecuteQuickActionOnOnePerson($idToExecuteQuickActionOn: ID!) { + executeQuickActionOnPerson(id: $idToExecuteQuickActionOn) { + id + opportunities { + edges { + node { + id + } + } + } + xLink { + label + url + } + id + pointOfContactForOpportunities { + edges { + node { + id + } + } + } + createdAt + company { + id + } + city + email + activityTargets { + edges { + node { + id + } + } + } + jobTitle + favorites { + edges { + node { + id + } + } + } + attachments { + edges { + node { + id + } + } + } + name { + firstName + lastName + } + phone + linkedinLink { + label + url + } + updatedAt + avatarUrl + companyId + } + } +`; + +export const variables = { + idToExecuteQuickActionOn: 'a7286b9a-c039-4a89-9567-2dfa7953cda9', +}; diff --git a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useFindManyRecords.ts b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useFindManyRecords.ts new file mode 100644 index 0000000000..3b6e569c2d --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useFindManyRecords.ts @@ -0,0 +1,164 @@ +import { gql } from '@apollo/client'; + +export const query = gql` + query FindManyPeople( + $filter: PersonFilterInput + $orderBy: PersonOrderByInput + $lastCursor: String + $limit: Float = 30 + ) { + people( + filter: $filter + orderBy: $orderBy + first: $limit + after: $lastCursor + ) { + edges { + node { + id + opportunities { + edges { + node { + id + personId + pointOfContactId + updatedAt + companyId + pipelineStepId + probability + closeDate + amount { + amountMicros + currencyCode + } + id + createdAt + } + } + } + xLink { + label + url + } + id + pointOfContactForOpportunities { + edges { + node { + id + personId + pointOfContactId + updatedAt + companyId + pipelineStepId + probability + closeDate + amount { + amountMicros + currencyCode + } + id + createdAt + } + } + } + createdAt + company { + id + xLink { + label + url + } + linkedinLink { + label + url + } + domainName + annualRecurringRevenue { + amountMicros + currencyCode + } + createdAt + address + updatedAt + name + accountOwnerId + employees + id + idealCustomerProfile + } + city + email + activityTargets { + edges { + node { + id + updatedAt + createdAt + personId + activityId + companyId + id + } + } + } + jobTitle + favorites { + edges { + node { + id + id + companyId + createdAt + personId + position + workspaceMemberId + updatedAt + } + } + } + attachments { + edges { + node { + id + updatedAt + createdAt + name + personId + activityId + companyId + id + authorId + type + fullPath + } + } + } + name { + firstName + lastName + } + phone + linkedinLink { + label + url + } + updatedAt + avatarUrl + companyId + } + cursor + } + pageInfo { + hasNextPage + startCursor + endCursor + } + } + } +`; + +export const variables = { limit: 60, filter: undefined, orderBy: undefined }; + +export const responseData = { + id: '', +}; diff --git a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useFindOneRecord.ts b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useFindOneRecord.ts new file mode 100644 index 0000000000..c032d157de --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useFindOneRecord.ts @@ -0,0 +1,79 @@ +import { gql } from '@apollo/client'; + +import { responseData as person } from './useUpdateOneRecord'; + +export const query = gql` + query FindOneperson($objectRecordId: UUID!) { + person(filter: { id: { eq: $objectRecordId } }) { + id + opportunities { + edges { + node { + id + } + } + } + xLink { + label + url + } + id + pointOfContactForOpportunities { + edges { + node { + id + } + } + } + createdAt + company { + id + } + city + email + activityTargets { + edges { + node { + id + } + } + } + jobTitle + favorites { + edges { + node { + id + } + } + } + attachments { + edges { + node { + id + } + } + } + name { + firstName + lastName + } + phone + linkedinLink { + label + url + } + updatedAt + avatarUrl + companyId + } + } +`; + +export const variables = { + objectRecordId: '6205681e-7c11-40b4-9e32-f523dbe54590', +}; + +export const responseData = { + ...person, + id: '6205681e-7c11-40b4-9e32-f523dbe54590', +}; diff --git a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useUpdateOneRecord.ts b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useUpdateOneRecord.ts new file mode 100644 index 0000000000..ef39907e7a --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useUpdateOneRecord.ts @@ -0,0 +1,126 @@ +import { gql } from '@apollo/client'; + +export const query = gql` + mutation UpdateOnePerson($idToUpdate: ID!, $input: PersonUpdateInput!) { + updatePerson(id: $idToUpdate, data: $input) { + id + opportunities { + edges { + node { + id + } + } + } + xLink { + label + url + } + id + pointOfContactForOpportunities { + edges { + node { + id + } + } + } + createdAt + company { + id + } + city + email + activityTargets { + edges { + node { + id + } + } + } + jobTitle + favorites { + edges { + node { + id + } + } + } + attachments { + edges { + node { + id + } + } + } + name { + firstName + lastName + } + phone + linkedinLink { + label + url + } + updatedAt + avatarUrl + companyId + } + } +`; + +const basePerson = { + id: '36abbb63-34ed-4a16-89f5-f549ac55d0f9', + xLink: { + label: '', + url: '', + }, + createdAt: '', + city: '', + email: '', + jobTitle: '', + name: { + firstName: '', + lastName: '', + }, + phone: '', + linkedinLink: { + label: '', + url: '', + }, + updatedAt: '', + avatarUrl: '', + companyId: '', +}; + +const connectedObjects = { + favorites: { + edges: [], + }, + opportunities: { + edges: [], + }, + pointOfContactForOpportunities: { + edges: [], + }, + activityTargets: { + edges: [], + }, + attachments: { + edges: [], + }, + company: { + id: '', + }, +}; + +export const variables = { + idToUpdate: '36abbb63-34ed-4a16-89f5-f549ac55d0f9', + input: { + ...basePerson, + name: { firstName: 'John', lastName: 'Doe' }, + }, +}; + +export const responseData = { + ...basePerson, + ...connectedObjects, +}; diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useCreateManyRecords.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useCreateManyRecords.test.tsx new file mode 100644 index 0000000000..f0da527d46 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useCreateManyRecords.test.tsx @@ -0,0 +1,63 @@ +import { ReactNode } from 'react'; +import { MockedProvider } from '@apollo/client/testing'; +import { act, renderHook } from '@testing-library/react'; +import { RecoilRoot } from 'recoil'; + +import { + query, + responseData, + variables, +} from '@/object-record/hooks/__mocks__/useCreateManyRecords'; +import { useCreateManyRecords } from '@/object-record/hooks/useCreateManyRecords'; + +const people = [ + { id: 'a7286b9a-c039-4a89-9567-2dfa7953cda9' }, + { id: '37faabcd-cb39-4a0a-8618-7e3fda9afca0' }, +]; + +const mocks = [ + { + request: { + query, + variables, + }, + result: jest.fn(() => ({ + data: { + createPeople: people.map((person) => ({ + id: person.id, + ...responseData, + })), + }, + })), + }, +]; + +const Wrapper = ({ children }: { children: ReactNode }) => ( + + + {children} + + +); + +describe('useCreateManyRecords', () => { + it('works as expected', async () => { + const { result } = renderHook( + () => useCreateManyRecords({ objectNameSingular: 'person' }), + { + wrapper: Wrapper, + }, + ); + + await act(async () => { + const res = await result.current.createManyRecords(people); + expect(res).toBeDefined(); + expect(Array.isArray(res)).toBe(true); + expect(res?.length).toBe(2); + expect(res?.[0].id).toBe(people[0].id); + expect(res?.[1].id).toBe(people[1].id); + }); + + expect(mocks[0].result).toHaveBeenCalled(); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useCreateOneRecord.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useCreateOneRecord.test.tsx new file mode 100644 index 0000000000..7deae9134e --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useCreateOneRecord.test.tsx @@ -0,0 +1,54 @@ +import { ReactNode } from 'react'; +import { MockedProvider } from '@apollo/client/testing'; +import { act, renderHook } from '@testing-library/react'; +import { RecoilRoot } from 'recoil'; + +import { + query, + responseData, + variables, +} from '@/object-record/hooks/__mocks__/useCreateOneRecord'; +import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; + +const person = { id: 'a7286b9a-c039-4a89-9567-2dfa7953cda9' }; + +const mocks = [ + { + request: { + query, + variables, + }, + result: jest.fn(() => ({ + data: { + createPerson: { ...person, ...responseData }, + }, + })), + }, +]; + +const Wrapper = ({ children }: { children: ReactNode }) => ( + + + {children} + + +); + +describe('useCreateOneRecord', () => { + it('works as expected', async () => { + const { result } = renderHook( + () => useCreateOneRecord({ objectNameSingular: 'person' }), + { + wrapper: Wrapper, + }, + ); + + await act(async () => { + const res = await result.current.createOneRecord(person); + expect(res).toBeDefined(); + expect(res).toHaveProperty('id', person.id); + }); + + expect(mocks[0].result).toHaveBeenCalled(); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useDeleteManyRecords.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useDeleteManyRecords.test.tsx new file mode 100644 index 0000000000..548c1f0d6a --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useDeleteManyRecords.test.tsx @@ -0,0 +1,57 @@ +import { ReactNode } from 'react'; +import { MockedProvider } from '@apollo/client/testing'; +import { act, renderHook } from '@testing-library/react'; +import { RecoilRoot } from 'recoil'; + +import { + query, + responseData, + variables, +} from '@/object-record/hooks/__mocks__/useDeleteManyRecords'; +import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords'; + +const people = [ + 'a7286b9a-c039-4a89-9567-2dfa7953cda9', + '37faabcd-cb39-4a0a-8618-7e3fda9afca0', +]; + +const mocks = [ + { + request: { + query, + variables, + }, + result: jest.fn(() => ({ + data: { + deletePeople: responseData, + }, + })), + }, +]; + +const Wrapper = ({ children }: { children: ReactNode }) => ( + + + {children} + + +); + +describe('useDeleteManyRecords', () => { + it('works as expected', async () => { + const { result } = renderHook( + () => useDeleteManyRecords({ objectNameSingular: 'person' }), + { + wrapper: Wrapper, + }, + ); + + await act(async () => { + const res = await result.current.deleteManyRecords(people); + expect(res).toBeDefined(); + expect(res).toHaveProperty('id'); + }); + + expect(mocks[0].result).toHaveBeenCalled(); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useDeleteOneRecord.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useDeleteOneRecord.test.tsx new file mode 100644 index 0000000000..731a468a28 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useDeleteOneRecord.test.tsx @@ -0,0 +1,54 @@ +import { ReactNode } from 'react'; +import { MockedProvider } from '@apollo/client/testing'; +import { act, renderHook } from '@testing-library/react'; +import { RecoilRoot } from 'recoil'; + +import { + query, + responseData, + variables, +} from '@/object-record/hooks/__mocks__/useDeleteOneRecord'; +import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; + +const personId = 'a7286b9a-c039-4a89-9567-2dfa7953cda9'; + +const mocks = [ + { + request: { + query, + variables, + }, + result: jest.fn(() => ({ + data: { + deletePerson: responseData, + }, + })), + }, +]; + +const Wrapper = ({ children }: { children: ReactNode }) => ( + + + {children} + + +); + +describe('useDeleteOneRecord', () => { + it('works as expected', async () => { + const { result } = renderHook( + () => useDeleteOneRecord({ objectNameSingular: 'person' }), + { + wrapper: Wrapper, + }, + ); + + await act(async () => { + const res = await result.current.deleteOneRecord(personId); + expect(res).toBeDefined(); + expect(res).toHaveProperty('id', personId); + }); + + expect(mocks[0].result).toHaveBeenCalled(); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useExecuteQuickActionOnOneRecord.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useExecuteQuickActionOnOneRecord.test.tsx new file mode 100644 index 0000000000..100825c3ed --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useExecuteQuickActionOnOneRecord.test.tsx @@ -0,0 +1,62 @@ +import { ReactNode } from 'react'; +import { MockedProvider } from '@apollo/client/testing'; +import { act, renderHook } from '@testing-library/react'; +import { RecoilRoot } from 'recoil'; + +import { + query, + responseData, + variables, +} from '@/object-record/hooks/__mocks__/useExecuteQuickActionOnOneRecord'; +import { useExecuteQuickActionOnOneRecord } from '@/object-record/hooks/useExecuteQuickActionOnOneRecord'; + +const idToExecuteQuickActionOn = 'a7286b9a-c039-4a89-9567-2dfa7953cda9'; + +const mocks = [ + { + request: { + query, + variables, + }, + result: jest.fn(() => ({ + data: { + executeQuickActionOnPerson: { + ...responseData, + id: idToExecuteQuickActionOn, + }, + }, + })), + }, +]; + +const Wrapper = ({ children }: { children: ReactNode }) => ( + + + {children} + + +); + +describe('useExecuteQuickActionOnOneRecord', () => { + it('should work as expected', async () => { + const { result } = renderHook( + () => + useExecuteQuickActionOnOneRecord({ + objectNameSingular: 'person', + }), + { + wrapper: Wrapper, + }, + ); + + await act(async () => { + const res = await result.current.executeQuickActionOnOneRecord( + idToExecuteQuickActionOn, + ); + + expect(res).toHaveProperty('id', idToExecuteQuickActionOn); + }); + + expect(mocks[0].result).toHaveBeenCalled(); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindManyRecords.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindManyRecords.test.tsx new file mode 100644 index 0000000000..240f052209 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindManyRecords.test.tsx @@ -0,0 +1,96 @@ +import { ReactNode } from 'react'; +import { MockedProvider } from '@apollo/client/testing'; +import { renderHook } from '@testing-library/react'; +import { RecoilRoot, useSetRecoilState } from 'recoil'; + +import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; +import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; +import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; +import { + query, + responseData, + variables, +} from '@/object-record/hooks/__mocks__/useFindManyRecords'; +import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; +import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; + +const mocks = [ + { + request: { + query, + variables, + }, + result: jest.fn(() => ({ + data: { + deletePeople: responseData, + }, + })), + }, +]; + +const Wrapper = ({ children }: { children: ReactNode }) => ( + + + + {children} + + + +); + +describe('useFindManyRecords', () => { + it('should skip fetch if currentWorkspace is undefined', async () => { + const { result } = renderHook( + () => useFindManyRecords({ objectNameSingular: 'person' }), + { + wrapper: Wrapper, + }, + ); + + expect(result.current.loading).toBe(false); + expect(result.current.error).toBeUndefined(); + }); + + it('should work as expected', async () => { + const onCompleted = jest.fn(); + + const { result } = renderHook( + () => { + const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState); + setCurrentWorkspace({ + id: '32219445-f587-4c40-b2b1-6d3205ed96da', + displayName: 'cool-workspace', + allowImpersonation: false, + subscriptionStatus: 'incomplete', + }); + + const mockObjectMetadataItems = getObjectMetadataItemsMock(); + + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); + + setMetadataItems(mockObjectMetadataItems); + + return useFindManyRecords({ + objectNameSingular: 'person', + onCompleted, + }); + }, + { + wrapper: Wrapper, + }, + ); + + expect(result.current.loading).toBe(true); + expect(result.current.error).toBeUndefined(); + expect(result.current.records.length).toBe(0); + + // FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory + // await waitFor(() => { + // expect(result.current.loading).toBe(false); + // expect(result.current.records).toBeDefined(); + + // console.log({ res: result.current.records }); + // expect(result.current.records.length > 0).toBe(true); + // }); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindOneRecord.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindOneRecord.test.tsx new file mode 100644 index 0000000000..62e11efe51 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useFindOneRecord.test.tsx @@ -0,0 +1,60 @@ +import { ReactNode } from 'react'; +import { MockedProvider } from '@apollo/client/testing'; +import { renderHook, waitFor } from '@testing-library/react'; +import { RecoilRoot } from 'recoil'; + +import { + query, + responseData, + variables, +} from '@/object-record/hooks/__mocks__/useFindOneRecord'; +import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord'; +import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; + +const mocks = [ + { + request: { + query, + variables, + }, + result: jest.fn(() => ({ + data: { + person: responseData, + }, + })), + }, +]; + +const Wrapper = ({ children }: { children: ReactNode }) => ( + + + + {children} + + + +); + +const objectRecordId = '6205681e-7c11-40b4-9e32-f523dbe54590'; + +describe('useFindOneRecord', () => { + it('should skip fetch if currentWorkspace is undefined', async () => { + const { result } = renderHook( + () => useFindOneRecord({ objectNameSingular: 'person', objectRecordId }), + { + wrapper: Wrapper, + }, + ); + + expect(result.current.loading).toBe(true); + expect(result.current.error).toBeUndefined(); + expect(result.current.record).toBeUndefined(); + + await waitFor(() => { + expect(result.current.loading).toBe(false); + expect(result.current.record).toBeDefined(); + }); + + expect(mocks[0].result).toHaveBeenCalled(); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.test.tsx new file mode 100644 index 0000000000..2b1ef39614 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useGenerateFindManyRecordsForMultipleMetadataItemsQuery.test.tsx @@ -0,0 +1,30 @@ +import { ReactNode } from 'react'; +import { renderHook } from '@testing-library/react'; +import { RecoilRoot } from 'recoil'; + +import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; +import { useGenerateFindManyRecordsForMultipleMetadataItemsQuery } from '@/object-record/hooks/useGenerateFindManyRecordsForMultipleMetadataItemsQuery'; + +const Wrapper = ({ children }: { children: ReactNode }) => ( + {children} +); + +describe('useGenerateFindManyRecordsForMultipleMetadataItemsQuery', () => { + it('should work as expected', async () => { + const { result } = renderHook( + () => { + const mockObjectMetadataItems = getObjectMetadataItemsMock(); + + return useGenerateFindManyRecordsForMultipleMetadataItemsQuery({ + objectMetadataItems: mockObjectMetadataItems.slice(0, 2), + }); + }, + { + wrapper: Wrapper, + }, + ); + + expect(result.current?.kind).toBe('Document'); + expect(result.current?.definitions.length).toBe(1); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useModifyRecordFromCache.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useModifyRecordFromCache.test.tsx new file mode 100644 index 0000000000..ee1556536e --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useModifyRecordFromCache.test.tsx @@ -0,0 +1,52 @@ +import { ReactNode } from 'react'; +import { useApolloClient } from '@apollo/client'; +import { MockedProvider } from '@apollo/client/testing'; +import { act, renderHook } from '@testing-library/react'; +import { RecoilRoot } from 'recoil'; + +import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; +import { useModifyRecordFromCache } from '@/object-record/hooks/useModifyRecordFromCache'; + +const Wrapper = ({ children }: { children: ReactNode }) => ( + + {children} + +); + +const recordId = '91408718-a29f-4678-b573-c791e8664c2a'; + +describe('useModifyRecordFromCache', () => { + it('should work as expected', async () => { + const { result } = renderHook( + () => { + const apolloClient = useApolloClient(); + const mockObjectMetadataItems = getObjectMetadataItemsMock(); + + const personMetadataItem = mockObjectMetadataItems.find( + (item) => item.nameSingular === 'person', + )!; + + return { + modifyRecordFromCache: useModifyRecordFromCache({ + objectMetadataItem: personMetadataItem, + }), + cache: apolloClient.cache, + }; + }, + { + wrapper: Wrapper, + }, + ); + + const spy = jest.spyOn(result.current.cache, 'modify'); + + act(() => { + result.current.modifyRecordFromCache(recordId, {}); + }); + + expect(spy).toHaveBeenCalledWith({ + id: `Person:${recordId}`, + fields: {}, + }); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useObjectRecordBoard.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useObjectRecordBoard.test.tsx new file mode 100644 index 0000000000..eb3a138345 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useObjectRecordBoard.test.tsx @@ -0,0 +1,31 @@ +import { ReactNode } from 'react'; +import { MockedProvider } from '@apollo/client/testing'; +import { renderHook } from '@testing-library/react'; +import { RecoilRoot } from 'recoil'; + +import { useObjectRecordBoard } from '@/object-record/hooks/useObjectRecordBoard'; +import { RecordBoardScope } from '@/object-record/record-board/scopes/RecordBoardScope'; +import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; + +const recordBoardId = '783932a0-28c7-4607-b2ce-6543fa2be892'; + +const Wrapper = ({ children }: { children: ReactNode }) => ( + + + + {children} + + + +); + +describe('useObjectRecordBoard', () => { + it('should skip fetch if currentWorkspace is undefined', async () => { + const { result } = renderHook(() => useObjectRecordBoard(), { + wrapper: Wrapper, + }); + + expect(result.current.loading).toBe(false); + expect(Array.isArray(result.current.opportunities)).toBe(true); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useObjectRecordTable.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useObjectRecordTable.test.tsx new file mode 100644 index 0000000000..1543a413e1 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useObjectRecordTable.test.tsx @@ -0,0 +1,37 @@ +import { ReactNode } from 'react'; +import { MockedProvider } from '@apollo/client/testing'; +import { expect } from '@storybook/test'; +import { renderHook } from '@testing-library/react'; +import { RecoilRoot } from 'recoil'; + +import { useObjectRecordTable } from '@/object-record/hooks/useObjectRecordTable'; +import { RecordTableScope } from '@/object-record/record-table/scopes/RecordTableScope'; +import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; + +const recordTableScopeId = 'people'; +const onColumnsChange = jest.fn(); + +const Wrapper = ({ children }: { children: ReactNode }) => ( + + + + {children} + + + +); + +describe('useObjectRecordTable', () => { + it('should skip fetch if currentWorkspace is undefined', async () => { + const { result } = renderHook(() => useObjectRecordTable(), { + wrapper: Wrapper, + }); + + expect(result.current.loading).toBe(false); + expect(Array.isArray(result.current.records)).toBe(true); + expect(result.current.records.length).toBe(13); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useUpdateOneRecord.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useUpdateOneRecord.test.tsx new file mode 100644 index 0000000000..0ccd92897a --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useUpdateOneRecord.test.tsx @@ -0,0 +1,62 @@ +import { ReactNode } from 'react'; +import { MockedProvider } from '@apollo/client/testing'; +import { act, renderHook } from '@testing-library/react'; +import { RecoilRoot } from 'recoil'; + +import { + query, + responseData, + variables, +} from '@/object-record/hooks/__mocks__/useUpdateOneRecord'; +import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; + +const person = { id: '36abbb63-34ed-4a16-89f5-f549ac55d0f9' }; +const update = { name: { firstName: 'John', lastName: 'Doe' } }; +const updatePerson = { ...person, ...responseData, ...update }; + +const mocks = [ + { + request: { + query, + variables, + }, + result: jest.fn(() => ({ + data: { + updatePerson, + }, + })), + }, +]; + +const Wrapper = ({ children }: { children: ReactNode }) => ( + + + {children} + + +); + +const idToUpdate = '36abbb63-34ed-4a16-89f5-f549ac55d0f9'; + +describe('useUpdateOneRecord', () => { + it('works as expected', async () => { + const { result } = renderHook( + () => useUpdateOneRecord({ objectNameSingular: 'person' }), + { + wrapper: Wrapper, + }, + ); + + await act(async () => { + const res = await result.current.updateOneRecord({ + idToUpdate, + updateOneRecordInput: updatePerson, + }); + expect(res).toBeDefined(); + expect(res).toHaveProperty('id', person.id); + expect(res).toHaveProperty('name', update.name); + }); + + expect(mocks[0].result).toHaveBeenCalled(); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/hooks/useDeleteOneRecord.ts b/packages/twenty-front/src/modules/object-record/hooks/useDeleteOneRecord.ts index cc3e3b4731..01eb92017c 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useDeleteOneRecord.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useDeleteOneRecord.ts @@ -52,7 +52,7 @@ export const useDeleteOneRecord = ({ }); return deletedRecord.data[ - `create${capitalize(objectMetadataItem.nameSingular)}` + `delete${capitalize(objectMetadataItem.nameSingular)}` ] as T; }, [