Add unit tests on object record mutation and query hooks (#5014)

### Description
Add unit tests on object record mutation and query hooks

### Refs
#4884

### Demo
![Screenshot 2024-04-18 at 15 16
19](https://github.com/twentyhq/twenty/assets/140154534/c75f716a-725e-43eb-a703-3db29065fb18)

Fixes #4884

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
gitstart-twenty 2024-05-07 20:04:55 +08:00 committed by GitHub
parent d0759ad7cc
commit d10efb15d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 727 additions and 0 deletions

View File

@ -0,0 +1,67 @@
import { gql } from '@apollo/client';
import { mockedPeopleData } from '~/testing/mock-data/people';
export const query = gql`
query FindDuplicatePerson($id: UUID) {
personDuplicates(id: $id) {
edges {
node {
__typename
xLink {
label
url
}
id
createdAt
city
email
jobTitle
name {
firstName
lastName
}
phone
linkedinLink {
label
url
}
updatedAt
avatarUrl
companyId
}
cursor
}
pageInfo {
hasNextPage
startCursor
endCursor
}
totalCount
}
}
`;
export const variables = {
id: '6205681e-7c11-40b4-9e32-f523dbe54590',
};
export const responseData = {
personDuplicates: {
edges: [
{
node: { __typename: 'Person', ...mockedPeopleData[0], updatedAt: '' },
cursor: 'cursor1',
},
{
node: { __typename: 'Person', ...mockedPeopleData[1], updatedAt: '' },
cursor: 'cursor2',
},
],
pageInfo: {
hasNextPage: false,
startCursor: 'cursor1',
endCursor: 'cursor2',
},
totalCount: 2,
},
};

View File

@ -0,0 +1,63 @@
import { renderHook } from '@testing-library/react';
import { print } from 'graphql';
import { RecoilRoot } from 'recoil';
import { useCreateManyRecordsMutation } from '@/object-record/hooks/useCreateManyRecordsMutation';
const expectedQueryTemplate = `
mutation CreatePeople($data: [PersonCreateInput!]!) {
createPeople(data: $data) {
__typename
xLink {
label
url
}
id
createdAt
city
email
jobTitle
name {
firstName
lastName
}
phone
linkedinLink {
label
url
}
updatedAt
avatarUrl
companyId
}
}
`.replace(/\s/g, '');
describe('useCreateManyRecordsMutation', () => {
it('should return a valid createManyRecordsMutation', () => {
const objectNameSingular = 'person';
const depth = 2;
const { result } = renderHook(
() =>
useCreateManyRecordsMutation({
objectNameSingular,
depth,
}),
{
wrapper: RecoilRoot,
},
);
const { createManyRecordsMutation } = result.current;
expect(createManyRecordsMutation).toBeDefined();
const printedReceivedQuery = print(createManyRecordsMutation).replace(
/\s/g,
'',
);
expect(printedReceivedQuery).toEqual(expectedQueryTemplate);
});
});

View File

@ -0,0 +1,63 @@
import { renderHook } from '@testing-library/react';
import { print } from 'graphql';
import { RecoilRoot } from 'recoil';
import { useCreateOneRecordMutation } from '@/object-record/hooks/useCreateOneRecordMutation';
const expectedQueryTemplate = `
mutation CreateOnePerson($input: PersonCreateInput!) {
createPerson(data: $input) {
__typename
xLink {
label
url
}
id
createdAt
city
email
jobTitle
name {
firstName
lastName
}
phone
linkedinLink {
label
url
}
updatedAt
avatarUrl
companyId
}
}
`.replace(/\s/g, '');
describe('useCreateOneRecordMutation', () => {
it('should return a valid createOneRecordMutation', () => {
const objectNameSingular = 'person';
const depth = 2;
const { result } = renderHook(
() =>
useCreateOneRecordMutation({
objectNameSingular,
depth,
}),
{
wrapper: RecoilRoot,
},
);
const { createOneRecordMutation } = result.current;
expect(createOneRecordMutation).toBeDefined();
const printedReceivedQuery = print(createOneRecordMutation).replace(
/\s/g,
'',
);
expect(printedReceivedQuery).toEqual(expectedQueryTemplate);
});
});

View File

@ -0,0 +1,40 @@
import { renderHook } from '@testing-library/react';
import { print } from 'graphql';
import { RecoilRoot } from 'recoil';
import { useDeleteManyRecordsMutation } from '@/object-record/hooks/useDeleteManyRecordsMutation';
const expectedQueryTemplate = `
mutation DeleteManyPeople($filter: PersonFilterInput!) {
deletePeople(filter: $filter) {
id
}
}
`.replace(/\s/g, '');
describe('useDeleteManyRecordsMutation', () => {
it('should return a valid deleteManyRecordsMutation', () => {
const objectNameSingular = 'person';
const { result } = renderHook(
() =>
useDeleteManyRecordsMutation({
objectNameSingular,
}),
{
wrapper: RecoilRoot,
},
);
const { deleteManyRecordsMutation } = result.current;
expect(deleteManyRecordsMutation).toBeDefined();
const printedReceivedQuery = print(deleteManyRecordsMutation).replace(
/\s/g,
'',
);
expect(printedReceivedQuery).toEqual(expectedQueryTemplate);
});
});

View File

@ -0,0 +1,40 @@
import { renderHook } from '@testing-library/react';
import { print } from 'graphql';
import { RecoilRoot } from 'recoil';
import { useDeleteOneRecordMutation } from '@/object-record/hooks/useDeleteOneRecordMutation';
const expectedQueryTemplate = `
mutation DeleteOnePerson($idToDelete: UUID!) {
deletePerson(id: $idToDelete) {
id
}
}
`.replace(/\s/g, '');
describe('useDeleteOneRecordMutation', () => {
it('should return a valid deleteOneRecordMutation', () => {
const objectNameSingular = 'person';
const { result } = renderHook(
() =>
useDeleteOneRecordMutation({
objectNameSingular,
}),
{
wrapper: RecoilRoot,
},
);
const { deleteOneRecordMutation } = result.current;
expect(deleteOneRecordMutation).toBeDefined();
const printedReceivedQuery = print(deleteOneRecordMutation).replace(
/\s/g,
'',
);
expect(printedReceivedQuery).toEqual(expectedQueryTemplate);
});
});

View File

@ -0,0 +1,60 @@
import { renderHook } from '@testing-library/react';
import { print } from 'graphql';
import { RecoilRoot } from 'recoil';
import { useExecuteQuickActionOnOneRecordMutation } from '@/object-record/hooks/useExecuteQuickActionOnOneRecordMutation';
const expectedQueryTemplate = `
mutation ExecuteQuickActionOnOnePerson($idToExecuteQuickActionOn: UUID!) {
executeQuickActionOnPerson(id: $idToExecuteQuickActionOn) {
__typename
xLink {
label
url
}
id
createdAt
city
email
jobTitle
name {
firstName
lastName
}
phone
linkedinLink {
label
url
}
updatedAt
avatarUrl
companyId
}
}
`.replace(/\s/g, '');
describe('useExecuteQuickActionOnOneRecordMutation', () => {
it('should return a valid executeQuickActionOnOneRecordMutation', () => {
const objectNameSingular = 'person';
const { result } = renderHook(
() =>
useExecuteQuickActionOnOneRecordMutation({
objectNameSingular,
}),
{
wrapper: RecoilRoot,
},
);
const { executeQuickActionOnOneRecordMutation } = result.current;
expect(executeQuickActionOnOneRecordMutation).toBeDefined();
const printedReceivedQuery = print(
executeQuickActionOnOneRecordMutation,
).replace(/\s/g, '');
expect(printedReceivedQuery).toEqual(expectedQueryTemplate);
});
});

View File

@ -0,0 +1,62 @@
import { ReactNode } from 'react';
import { MockedProvider } from '@apollo/client/testing';
import { renderHook, waitFor } from '@testing-library/react';
import { RecoilRoot } from 'recoil';
import { useFindDuplicateRecords } from '@/object-record/hooks/useFindDuplicateRecords';
import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope';
import {
query,
responseData,
variables,
} from '../__mocks__/useFindDuplicateRecords';
const mocks = [
{
request: {
query,
variables,
},
result: jest.fn(() => ({
data: responseData,
})),
},
];
const Wrapper = ({ children }: { children: ReactNode }) => (
<RecoilRoot>
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
<MockedProvider mocks={mocks} addTypename={false}>
{children}
</MockedProvider>
</SnackBarProviderScope>
</RecoilRoot>
);
describe('useFindDuplicateRecords', () => {
it('should fetch duplicate records and return the correct data', async () => {
const objectRecordId = '6205681e-7c11-40b4-9e32-f523dbe54590';
const objectNameSingular = 'person';
const { result } = renderHook(
() =>
useFindDuplicateRecords({
objectRecordId,
objectNameSingular,
}),
{
wrapper: Wrapper,
},
);
expect(result.current.loading).toBe(true);
await waitFor(() => {
expect(result.current.loading).toBe(false);
expect(result.current.records).toBeDefined();
});
expect(mocks[0].result).toHaveBeenCalled();
});
});

View File

@ -0,0 +1,74 @@
import { renderHook } from '@testing-library/react';
import { print } from 'graphql';
import { RecoilRoot } from 'recoil';
import { useFindDuplicateRecordsQuery } from '@/object-record/hooks/useFindDuplicatesRecordsQuery';
const expectedQueryTemplate = `
query FindDuplicatePerson($id: UUID) {
personDuplicates(id: $id) {
edges {
node {
__typename
xLink {
label
url
}
id
createdAt
city
email
jobTitle
name {
firstName
lastName
}
phone
linkedinLink {
label
url
}
updatedAt
avatarUrl
companyId
}
cursor
}
pageInfo {
hasNextPage
startCursor
endCursor
}
totalCount
}
}
`.replace(/\s/g, '');
describe('useFindDuplicateRecordsQuery', () => {
it('should return a valid findDuplicateRecordsQuery', () => {
const objectNameSingular = 'person';
const depth = 2;
const { result } = renderHook(
() =>
useFindDuplicateRecordsQuery({
objectNameSingular,
depth,
}),
{
wrapper: RecoilRoot,
},
);
const { findDuplicateRecordsQuery } = result.current;
expect(findDuplicateRecordsQuery).toBeDefined();
const printedReceivedQuery = print(findDuplicateRecordsQuery).replace(
/\s/g,
'',
);
expect(printedReceivedQuery).toEqual(expectedQueryTemplate);
});
});

View File

@ -0,0 +1,73 @@
import { renderHook } from '@testing-library/react';
import { print } from 'graphql';
import { RecoilRoot } from 'recoil';
import { useFindManyRecordsQuery } from '@/object-record/hooks/useFindManyRecordsQuery';
const expectedQueryTemplate = `
query FindManyPeople($filter: PersonFilterInput, $orderBy: PersonOrderByInput, $lastCursor: String, $limit: Float) {
people(filter: $filter, orderBy: $orderBy, first: $limit, after: $lastCursor) {
edges {
node {
__typename
xLink {
label
url
}
id
createdAt
city
email
jobTitle
name {
firstName
lastName
}
phone
linkedinLink {
label
url
}
updatedAt
avatarUrl
companyId
}
cursor
}
pageInfo {
hasNextPage
startCursor
endCursor
}
totalCount
}
}
`.replace(/\s/g, '');
describe('useFindManyRecordsQuery', () => {
it('should return a valid findManyRecordsQuery', () => {
const objectNameSingular = 'person';
const depth = 2;
const computeReferences = true;
const { result } = renderHook(
() =>
useFindManyRecordsQuery({
objectNameSingular,
depth,
computeReferences,
}),
{
wrapper: RecoilRoot,
},
);
const { findManyRecordsQuery } = result.current;
expect(findManyRecordsQuery).toBeDefined();
const printedReceivedQuery = print(findManyRecordsQuery).replace(/\s/g, '');
expect(printedReceivedQuery).toEqual(expectedQueryTemplate);
});
});

View File

@ -0,0 +1,60 @@
import { renderHook } from '@testing-library/react';
import { print } from 'graphql';
import { RecoilRoot } from 'recoil';
import { useFindOneRecordQuery } from '@/object-record/hooks/useFindOneRecordQuery';
const expectedQueryTemplate = `
query FindOnePerson($objectRecordId: UUID!) {
person(filter: { id: { eq: $objectRecordId } }) {
__typename
xLink {
label
url
}
id
createdAt
city
email
jobTitle
name {
firstName
lastName
}
phone
linkedinLink {
label
url
}
updatedAt
avatarUrl
companyId
}
}
`.replace(/\s/g, '');
describe('useFindOneRecordQuery', () => {
it('should return a valid findOneRecordQuery', () => {
const objectNameSingular = 'person';
const depth = 2;
const { result } = renderHook(
() =>
useFindOneRecordQuery({
objectNameSingular,
depth,
}),
{
wrapper: RecoilRoot,
},
);
const { findOneRecordQuery } = result.current;
expect(findOneRecordQuery).toBeDefined();
const printedReceivedQuery = print(findOneRecordQuery).replace(/\s/g, '');
expect(printedReceivedQuery).toEqual(expectedQueryTemplate);
});
});

View File

@ -0,0 +1,62 @@
import { ReactNode } from 'react';
import { MockedProvider } from '@apollo/client/testing';
import { act, renderHook, waitFor } from '@testing-library/react';
import { RecoilRoot } from 'recoil';
import {
query,
responseData,
variables,
} from '@/object-record/hooks/__mocks__/useFindOneRecord';
import { useLazyFindOneRecord } from '@/object-record/hooks/useLazyFindOneRecord';
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 }) => (
<RecoilRoot>
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
<MockedProvider mocks={mocks} addTypename={false}>
{children}
</MockedProvider>
</SnackBarProviderScope>
</RecoilRoot>
);
const objectRecordId = '6205681e-7c11-40b4-9e32-f523dbe54590';
describe('useLazyFindOneRecord', () => {
it('fetches record data when called', async () => {
const { result } = renderHook(
() => useLazyFindOneRecord({ objectNameSingular: 'person' }),
{
wrapper: Wrapper,
},
);
act(() => {
result.current.findOneRecord({ objectRecordId: objectRecordId });
});
expect(result.current.loading).toBe(true);
await waitFor(() => {
expect(result.current.loading).toBe(false);
expect(result.current.record).toBeDefined();
});
expect(mocks[0].result).toHaveBeenCalled();
});
});

View File

@ -0,0 +1,63 @@
import { renderHook } from '@testing-library/react';
import { print } from 'graphql';
import { RecoilRoot } from 'recoil';
import { useUpdateOneRecordMutation } from '@/object-record/hooks/useUpdateOneRecordMutation';
const expectedQueryTemplate = `
mutation UpdateOnePerson($idToUpdate: UUID!, $input: PersonUpdateInput!) {
updatePerson(id: $idToUpdate, data: $input) {
__typename
xLink {
label
url
}
id
createdAt
city
email
jobTitle
name {
firstName
lastName
}
phone
linkedinLink {
label
url
}
updatedAt
avatarUrl
companyId
}
}
`.replace(/\s/g, '');
describe('useUpdateOneRecordMutation', () => {
it('should return a valid createManyRecordsMutation', () => {
const objectNameSingular = 'person';
const depth = 2;
const { result } = renderHook(
() =>
useUpdateOneRecordMutation({
objectNameSingular,
depth,
}),
{
wrapper: RecoilRoot,
},
);
const { updateOneRecordMutation } = result.current;
expect(updateOneRecordMutation).toBeDefined();
const printedReceivedQuery = print(updateOneRecordMutation).replace(
/\s/g,
'',
);
expect(printedReceivedQuery).toEqual(expectedQueryTemplate);
});
});