From c8de37860f5a714b12702171555a979401f523b9 Mon Sep 17 00:00:00 2001 From: "gitstart-app[bot]" <57568882+gitstart-app[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 09:29:12 +0100 Subject: [PATCH] TWNTY-3379 - Add tests for `modules/favorites` and `modules/companies` (#3528) * Add tests for `modules/favorites` and `modules/companies` Co-authored-by: v1b3m Co-authored-by: Thiago Nascimbeni * Fix failing test in `object-metadata/hooks` Co-authored-by: v1b3m Co-authored-by: Thiago Nascimbeni --------- Co-authored-by: gitstart-twenty Co-authored-by: v1b3m Co-authored-by: Thiago Nascimbeni --- .../useSpreadsheetCompanyImport.test.tsx | 137 +++++++++++++++ .../favorites/hooks/__mocks__/useFavorites.ts | 166 ++++++++++++++++++ .../hooks/__tests__/useFavorites.test.tsx | 162 +++++++++++++++++ .../useMapToObjectRecordIdentifier.test.tsx | 2 +- 4 files changed, 466 insertions(+), 1 deletion(-) create mode 100644 packages/twenty-front/src/modules/companies/hooks/__tests__/useSpreadsheetCompanyImport.test.tsx create mode 100644 packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts create mode 100644 packages/twenty-front/src/modules/favorites/hooks/__tests__/useFavorites.test.tsx diff --git a/packages/twenty-front/src/modules/companies/hooks/__tests__/useSpreadsheetCompanyImport.test.tsx b/packages/twenty-front/src/modules/companies/hooks/__tests__/useSpreadsheetCompanyImport.test.tsx new file mode 100644 index 000000000..57ac3d8c3 --- /dev/null +++ b/packages/twenty-front/src/modules/companies/hooks/__tests__/useSpreadsheetCompanyImport.test.tsx @@ -0,0 +1,137 @@ +import { ReactNode } from 'react'; +import { gql } from '@apollo/client'; +import { MockedProvider } from '@apollo/client/testing'; +import { act, renderHook, waitFor } from '@testing-library/react'; +import { RecoilRoot, useRecoilValue } from 'recoil'; + +import { spreadsheetImportState } from '@/spreadsheet-import/states/spreadsheetImportState'; +import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; + +import { useSpreadsheetCompanyImport } from '../useSpreadsheetCompanyImport'; + +const companyId = 'cb2e9f4b-20c3-4759-9315-4ffeecfaf71a'; + +jest.mock('uuid', () => ({ + v4: jest.fn(() => companyId), +})); + +jest.mock('@/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery', () => ({ + useMapFieldMetadataToGraphQLQuery: () => () => '\n', +})); + +const companyMocks = [ + { + request: { + query: gql` + mutation CreateCompanies($data: [CompanyCreateInput!]!) { + createCompanies(data: $data) { + id + } + } + `, + variables: { + data: [ + { + name: 'Example Company', + domainName: 'example.com', + idealCustomerProfile: true, + address: undefined, + employees: undefined, + id: companyId, + }, + ], + }, + }, + result: jest.fn(() => ({ + data: { + createCompanies: [ + { + id: companyId, + }, + ], + }, + })), + }, +]; + +const fakeCsv = () => { + const csvContent = 'name\nExample Company'; + const blob = new Blob([csvContent], { type: 'text/csv' }); + return new File([blob], 'fakeData.csv', { type: 'text/csv' }); +}; + +const Wrapper = ({ children }: { children: ReactNode }) => ( + + + + {children} + + + +); + +describe('useSpreadsheetCompanyImport', () => { + it('should work as expected', async () => { + const { result } = renderHook( + () => { + const spreadsheetImport = useRecoilValue(spreadsheetImportState); + const { openCompanySpreadsheetImport } = useSpreadsheetCompanyImport(); + return { openCompanySpreadsheetImport, spreadsheetImport }; + }, + { + wrapper: Wrapper, + }, + ); + + const { spreadsheetImport, openCompanySpreadsheetImport } = result.current; + + expect(spreadsheetImport.isOpen).toBe(false); + expect(spreadsheetImport.options).toBeNull(); + + await act(async () => { + openCompanySpreadsheetImport(); + }); + + const { spreadsheetImport: updatedImport } = result.current; + + expect(updatedImport.isOpen).toBe(true); + expect(updatedImport.options).toHaveProperty('onSubmit'); + expect(updatedImport.options?.onSubmit).toBeInstanceOf(Function); + expect(updatedImport.options).toHaveProperty('fields'); + expect(Array.isArray(updatedImport.options?.fields)).toBe(true); + + act(() => { + updatedImport.options?.onSubmit( + { + validData: [ + { + id: companyId, + name: 'Example Company', + domainName: 'example.com', + idealCustomerProfile: true, + address: undefined, + employees: undefined, + }, + ], + invalidData: [], + all: [ + { + id: companyId, + name: 'Example Company', + domainName: 'example.com', + __index: 'cbc3985f-dde9-46d1-bae2-c124141700ac', + idealCustomerProfile: true, + address: undefined, + employees: undefined, + }, + ], + }, + fakeCsv(), + ); + }); + + await waitFor(() => { + expect(companyMocks[0].result).toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts b/packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts new file mode 100644 index 000000000..f45c0c7ae --- /dev/null +++ b/packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts @@ -0,0 +1,166 @@ +import { gql } from '@apollo/client'; + +import { AvatarType } from '@/users/components/Avatar'; +import { ColorScheme } from '@/workspace-member/types/WorkspaceMember'; + +export const mockId = '8f3b2121-f194-4ba4-9fbf-2d5a37126806'; +export const favoriteId = 'f088c8c9-05d2-4276-b065-b863cc7d0b33'; +export const mockRecord = { id: 'f088c8c9-05d2-4276-b065-b863cc7d0b33' }; + +export const initialFavorites = [ + { + id: '1', + position: 0, + key: mockId, + labelIdentifier: 'favoriteLabel', + avatarUrl: 'example.com', + avatarType: 'squared' as AvatarType, + link: 'example.com', + recordId: '1', + person: { id: '1', name: 'John Doe' }, + company: { id: '2', name: 'ABC Corp' }, + }, + { + id: '2', + position: 1, + key: mockId, + labelIdentifier: 'favoriteLabel', + avatarUrl: 'example.com', + avatarType: 'squared' as AvatarType, + link: 'example.com', + recordId: '1', + person: { id: '3', name: 'Jane Doe' }, + company: { id: '4', name: 'Company Test' }, + }, + { + id: '3', + position: 2, + key: mockId, + labelIdentifier: 'favoriteLabel', + avatarUrl: 'example.com', + avatarType: 'squared' as AvatarType, + link: 'example.com', + recordId: '1', + }, +]; + +export const sortedFavorites = [ + { + id: '1', + recordId: '1', + position: 0, + avatarType: 'rounded', + avatarUrl: '', + labelIdentifier: ' ', + link: '/object/person/1', + }, + { + id: '2', + recordId: '3', + position: 1, + avatarType: 'rounded', + avatarUrl: '', + labelIdentifier: ' ', + link: '/object/person/3', + }, + { + id: '3', + position: 2, + key: '8f3b2121-f194-4ba4-9fbf-2d5a37126806', + labelIdentifier: 'favoriteLabel', + avatarUrl: 'example.com', + avatarType: 'squared', + link: 'example.com', + recordId: '1', + }, +]; + +export const mocks = [ + { + request: { + query: gql` + mutation CreateOneFavorite($input: FavoriteCreateInput!) { + createFavorite(data: $input) { + id + } + } + `, + variables: { + input: { + id: mockId, + favoritesId: favoriteId, + favorites: { id: favoriteId }, + position: 4, + workspaceMemberId: '1', + }, + }, + }, + result: jest.fn(() => ({ + data: { + createFavorite: { + id: favoriteId, + }, + }, + })), + }, + { + request: { + query: gql` + mutation DeleteOneFavorite($idToDelete: ID!) { + deleteFavorite(id: $idToDelete) { + id + } + } + `, + variables: { idToDelete: favoriteId }, + }, + result: jest.fn(() => ({ + data: { + deleteFavorite: { + id: favoriteId, + }, + }, + })), + }, + { + request: { + query: gql` + mutation UpdateOneFavorite( + $idToUpdate: ID! + $input: FavoriteUpdateInput! + ) { + updateFavorite(id: $idToUpdate, data: $input) { + id + } + } + `, + variables: { + idToUpdate: '1', + input: { + position: 2, + }, + }, + }, + result: jest.fn(() => ({ + data: { + updateFavorite: { + id: favoriteId, + }, + }, + })), + }, +]; + +export const mockWorkspaceMember = { + id: '1', + name: { + firstName: 'First', + lastName: 'Last', + }, + avatarUrl: '', + locale: 'en-US', + colorScheme: 'Dark' as ColorScheme, + createdAt: '', + updatedAt: '', + userId: '1', +}; diff --git a/packages/twenty-front/src/modules/favorites/hooks/__tests__/useFavorites.test.tsx b/packages/twenty-front/src/modules/favorites/hooks/__tests__/useFavorites.test.tsx new file mode 100644 index 000000000..0b0ce2b4f --- /dev/null +++ b/packages/twenty-front/src/modules/favorites/hooks/__tests__/useFavorites.test.tsx @@ -0,0 +1,162 @@ +import { ReactNode } from 'react'; +import { MockedProvider } from '@apollo/client/testing'; +import { DropResult, ResponderProvided } from '@hello-pangea/dnd'; +import { act, renderHook, waitFor } from '@testing-library/react'; +import { RecoilRoot, useSetRecoilState } from 'recoil'; + +import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; +import { useFavorites } from '@/favorites/hooks/useFavorites'; +import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; +import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; +import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; + +import { + favoriteId, + initialFavorites, + mockId, + mockRecord, + mocks, + mockWorkspaceMember, + sortedFavorites, +} from '../__mocks__/useFavorites'; + +jest.mock('uuid', () => ({ + v4: jest.fn(() => mockId), +})); + +jest.mock('@/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery', () => ({ + useMapFieldMetadataToGraphQLQuery: () => () => '\n', +})); + +jest.mock('@/object-record/hooks/useFindManyRecords', () => ({ + useFindManyRecords: () => ({ records: initialFavorites }), +})); + +const mockObjectMetadataItems = getObjectMetadataItemsMock(); + +const Wrapper = ({ children }: { children: ReactNode }) => ( + + + + {children} + + + +); + +describe('useFavorites', () => { + it('should fetch favorites successfully', async () => { + const { result } = renderHook( + () => { + const setCurrentWorkspaceMember = useSetRecoilState( + currentWorkspaceMemberState, + ); + setCurrentWorkspaceMember(mockWorkspaceMember); + + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); + setMetadataItems(mockObjectMetadataItems); + + return useFavorites(); + }, + { + wrapper: Wrapper, + }, + ); + + expect(result.current.favorites).toEqual(sortedFavorites); + }); + + it('should createOneFavorite successfully', async () => { + const { result } = renderHook( + () => { + const setCurrentWorkspaceMember = useSetRecoilState( + currentWorkspaceMemberState, + ); + setCurrentWorkspaceMember(mockWorkspaceMember); + + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); + setMetadataItems(mockObjectMetadataItems); + + return useFavorites(); + }, + { + wrapper: Wrapper, + }, + ); + + result.current.createFavorite(mockRecord, 'favorites'); + + await waitFor(() => { + expect(mocks[0].result).toHaveBeenCalled(); + }); + }); + + it('should deleteOneRecord successfully', async () => { + const { result } = renderHook( + () => { + const setCurrentWorkspaceMember = useSetRecoilState( + currentWorkspaceMemberState, + ); + setCurrentWorkspaceMember(mockWorkspaceMember); + + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); + setMetadataItems(mockObjectMetadataItems); + + return useFavorites(); + }, + { + wrapper: Wrapper, + }, + ); + + result.current.deleteFavorite(favoriteId); + + await waitFor(() => { + expect(mocks[1].result).toHaveBeenCalled(); + }); + }); + + it('should handle reordering favorites successfully', async () => { + const { result } = renderHook( + () => { + const setCurrentWorkspaceMember = useSetRecoilState( + currentWorkspaceMemberState, + ); + setCurrentWorkspaceMember(mockWorkspaceMember); + + const setMetadataItems = useSetRecoilState(objectMetadataItemsState); + setMetadataItems(mockObjectMetadataItems); + + return useFavorites(); + }, + { + wrapper: Wrapper, + }, + ); + + act(() => { + const dragAndDropResult: DropResult = { + source: { index: 0, droppableId: 'droppableId' }, + destination: { index: 2, droppableId: 'droppableId' }, + combine: null, + mode: 'FLUID', + draggableId: 'draggableId', + type: 'type', + reason: 'DROP', + }; + + const responderProvided: ResponderProvided = { + announce: (message: string) => console.log(message), + }; + + result.current.handleReorderFavorite( + dragAndDropResult, + responderProvided, + ); + }); + + await waitFor(() => { + expect(mocks[2].result).toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useMapToObjectRecordIdentifier.test.tsx b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useMapToObjectRecordIdentifier.test.tsx index 03c09f5d6..11fb35d6e 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useMapToObjectRecordIdentifier.test.tsx +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useMapToObjectRecordIdentifier.test.tsx @@ -26,7 +26,7 @@ describe('useMapToObjectRecordIdentifier', () => { expect(result.current).toEqual({ id: 'id', name: 'Sheldon Cooper', - avatarUrl: null, + avatarUrl: '', avatarType: 'rounded', linkToShowPage: '/object/person/id', });