From 8d206fd2c868b178f1fbbd2b016b8b9b0673e004 Mon Sep 17 00:00:00 2001 From: "gitstart-app[bot]" <57568882+gitstart-app[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 12:38:21 +0100 Subject: [PATCH] TWNTY-3480 - Add tests for `modules/object-record/relation-picker/hooks` (#3547) Add tests for `modules/object-record/relation-picker/hooks` Co-authored-by: gitstart-twenty Co-authored-by: v1b3m Co-authored-by: RubensRafael --- .../__tests__/useEntitySelectSearch.test.tsx | 29 +++ .../useLimitPerMetadataItem.test.tsx | 58 ++++++ ...attedAsObjectRecordForSelectArray.test.tsx | 93 ++++++++++ .../__tests__/useMultiObjectSearch.test.tsx | 169 ++++++++++++++++++ 4 files changed, 349 insertions(+) create mode 100644 packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useEntitySelectSearch.test.tsx create mode 100644 packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useLimitPerMetadataItem.test.tsx create mode 100644 packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx create mode 100644 packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectSearch.test.tsx diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useEntitySelectSearch.test.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useEntitySelectSearch.test.tsx new file mode 100644 index 000000000..f738620bc --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useEntitySelectSearch.test.tsx @@ -0,0 +1,29 @@ +import { ChangeEvent } from 'react'; +import { act, renderHook } from '@testing-library/react'; +import { RecoilRoot } from 'recoil'; + +import { useEntitySelectSearch } from '@/object-record/relation-picker/hooks/useEntitySelectSearch'; +import { RelationPickerScopeInternalContext } from '@/object-record/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext'; + +const scopeId = 'scopeId'; +const Wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + +); + +describe('useEntitySelectSearch', () => { + it('should update searchFilter after change event', async () => { + const { result } = renderHook(() => useEntitySelectSearch(), { + wrapper: Wrapper, + }); + const filter = 'value'; + + act(() => { + result.current.handleSearchFilterChange({ + currentTarget: { value: filter }, + } as ChangeEvent); + }); + expect(result.current.searchFilter).toBe(filter); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useLimitPerMetadataItem.test.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useLimitPerMetadataItem.test.tsx new file mode 100644 index 000000000..bc30a5a0c --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useLimitPerMetadataItem.test.tsx @@ -0,0 +1,58 @@ +import { renderHook } from '@testing-library/react'; +import { RecoilRoot } from 'recoil'; + +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { useLimitPerMetadataItem } from '@/object-record/relation-picker/hooks/useLimitPerMetadataItem'; +import { RelationPickerScopeInternalContext } from '@/object-record/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext'; + +const scopeId = 'scopeId'; +const Wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + +); + +describe('useLimitPerMetadataItem', () => { + const objectData: ObjectMetadataItem[] = [ + { + createdAt: 'createdAt', + id: 'id', + isActive: true, + isCustom: true, + isSystem: true, + labelPlural: 'labelPlural', + labelSingular: 'labelSingular', + namePlural: 'namePlural', + nameSingular: 'nameSingular', + updatedAt: 'updatedAt', + fields: [], + }, + ]; + + it('should return object with nameSingular and default limit', async () => { + const { result } = renderHook( + () => useLimitPerMetadataItem({ objectMetadataItems: objectData }), + { + wrapper: Wrapper, + }, + ); + + expect(result.current.limitPerMetadataItem).toStrictEqual({ + limitNameSingular: 60, + }); + }); + + it('should return an object with nameSingular and specified limit', async () => { + const { result } = renderHook( + () => + useLimitPerMetadataItem({ objectMetadataItems: objectData, limit: 30 }), + { + wrapper: Wrapper, + }, + ); + + expect(result.current.limitPerMetadataItem).toStrictEqual({ + limitNameSingular: 30, + }); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx new file mode 100644 index 000000000..e0b646bc7 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray.test.tsx @@ -0,0 +1,93 @@ +import { act, renderHook } from '@testing-library/react'; +import { RecoilRoot, useSetRecoilState } from 'recoil'; + +import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; +import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; +import { useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray } from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray'; +import { RelationPickerScopeInternalContext } from '@/object-record/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext'; + +const scopeId = 'scopeId'; +const Wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + +); + +const objectMetadataItemsMock = getObjectMetadataItemsMock(); + +const opportunityId = 'cb702502-4b1d-488e-9461-df3fb096ebf6'; +const personId = 'ab091fd9-1b81-4dfd-bfdb-564ffee032a2'; + +describe('useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray', () => { + it('should return object formatted from objectMetadataItemsState', async () => { + const { result } = renderHook( + () => { + return { + formattedRecord: + useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray( + { + multiObjectRecordsQueryResult: { + opportunities: { + edges: [ + { + node: { + id: opportunityId, + pointOfContactId: + 'e992bda7-d797-4e12-af04-9b427f42244c', + updatedAt: '2023-11-30T11:13:15.308Z', + createdAt: '2023-11-30T11:13:15.308Z', + }, + cursor: 'cursor', + }, + ], + pageInfo: {}, + }, + people: { + edges: [ + { + node: { + id: personId, + updatedAt: '2023-11-30T11:13:15.308Z', + createdAt: '2023-11-30T11:13:15.308Z', + }, + cursor: 'cursor', + }, + ], + pageInfo: {}, + }, + }, + }, + ), + setObjectMetadata: useSetRecoilState(objectMetadataItemsState), + }; + }, + { + wrapper: Wrapper, + }, + ); + act(() => { + result.current.setObjectMetadata(objectMetadataItemsMock); + }); + + expect( + result.current.formattedRecord.objectRecordForSelectArray.length, + ).toBe(2); + + const [opportunityRecordForSelect, personRecordForSelect] = + result.current.formattedRecord.objectRecordForSelectArray; + + expect(opportunityRecordForSelect.objectMetadataItem.namePlural).toBe( + 'opportunities', + ); + expect(opportunityRecordForSelect.record.id).toBe(opportunityId); + expect(opportunityRecordForSelect.recordIdentifier.linkToShowPage).toBe( + `/opportunities/${opportunityId}`, + ); + + expect(personRecordForSelect.objectMetadataItem.namePlural).toBe('people'); + expect(personRecordForSelect.record.id).toBe(personId); + expect(personRecordForSelect.recordIdentifier.linkToShowPage).toBe( + `/object/person/${personId}`, + ); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectSearch.test.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectSearch.test.tsx new file mode 100644 index 000000000..280f5017e --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/__tests__/useMultiObjectSearch.test.tsx @@ -0,0 +1,169 @@ +import { gql } from '@apollo/client'; +import { MockedProvider } from '@apollo/client/testing'; +import { act, renderHook, waitFor } from '@testing-library/react'; +import { RecoilRoot, useSetRecoilState } from 'recoil'; + +import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { useMultiObjectSearch } from '@/object-record/relation-picker/hooks/useMultiObjectSearch'; + +const query = gql` + query FindManyRecordsMultipleMetadataItems( + $filterNameSingular: NameSingularFilterInput + $orderByNameSingular: NameSingularOrderByInput + $lastCursorNameSingular: String + $limitNameSingular: Float = 5 + ) { + namePlural( + filter: $filterNameSingular + orderBy: $orderByNameSingular + first: $limitNameSingular + after: $lastCursorNameSingular + ) { + edges { + node { + id + } + cursor + } + pageInfo { + hasNextPage + startCursor + endCursor + } + } + } +`; +const response = { + namePlural: { + edges: [{ node: { id: 'nodeId' }, cursor: 'cursor' }], + pageInfo: { startCursor: '', hasNextPage: '', endCursor: '' }, + }, +}; + +const mocks = [ + { + request: { + query, + variables: { + filterNameSingular: { and: [{}, { id: { in: ['1'] } }] }, + orderByNameSingular: { createdAt: 'DescNullsLast' }, + limitNameSingular: 60, + }, + }, + result: jest.fn(() => ({ + data: response, + })), + }, + { + request: { + query, + variables: { + filterNameSingular: { id: { in: ['1'] } }, + orderByNameSingular: { createdAt: 'DescNullsLast' }, + limitNameSingular: 60, + }, + }, + result: jest.fn(() => ({ + data: response, + })), + }, + { + request: { + query, + variables: { + limitNameSingular: 60, + filterNameSingular: { and: [{}, { not: { id: { in: ['1'] } } }] }, + orderByNameSingular: { createdAt: 'DescNullsLast' }, + }, + }, + result: jest.fn(() => ({ + data: response, + })), + }, +]; + +const Wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + +); + +describe('useMultiObjectSearch', () => { + it('should return object formatted from objectMetadataItemsState', async () => { + const { result } = renderHook( + () => ({ + multiObjects: useMultiObjectSearch({ + searchFilterValue: '', + selectedObjectRecordIds: [ + { + objectNameSingular: 'nameSingular', + id: '1', + }, + ], + }), + setObjectMetadata: useSetRecoilState(objectMetadataItemsState), + }), + { + wrapper: Wrapper, + }, + ); + const objectData: ObjectMetadataItem[] = [ + { + createdAt: 'createdAt', + id: 'id', + isActive: true, + isCustom: true, + isSystem: false, + labelPlural: 'labelPlural', + labelSingular: 'labelSingular', + namePlural: 'namePlural', + nameSingular: 'nameSingular', + updatedAt: 'updatedAt', + fields: [], + }, + ]; + act(() => { + result.current.setObjectMetadata(objectData); + }); + await waitFor(() => { + expect(mocks[0].result).toHaveBeenCalled(); + expect(mocks[1].result).toHaveBeenCalled(); + expect(mocks[2].result).toHaveBeenCalled(); + }); + const expectedData = [ + { + objectMetadataItem: { + createdAt: 'createdAt', + id: 'id', + isActive: true, + isCustom: true, + isSystem: false, + labelPlural: 'labelPlural', + labelSingular: 'labelSingular', + namePlural: 'namePlural', + nameSingular: 'nameSingular', + updatedAt: 'updatedAt', + fields: [], + }, + record: { id: 'nodeId' }, + recordIdentifier: { + id: 'nodeId', + name: '', + avatarUrl: '', + avatarType: 'rounded', + linkToShowPage: '/object/nameSingular/nodeId', + }, + }, + ]; + expect(result.current.multiObjects.selectedObjectRecords).toStrictEqual( + expectedData, + ); + expect( + result.current.multiObjects.filteredSelectedObjectRecords, + ).toStrictEqual(expectedData); + expect(result.current.multiObjects.objectRecordsToSelect).toStrictEqual( + expectedData, + ); + }); +});