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 <gitstart-twenty@users.noreply.github.com>
Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: RubensRafael <rubensrafael2@live.com>
This commit is contained in:
gitstart-app[bot]
2024-01-19 12:38:21 +01:00
committed by GitHub
parent 1bb7ff3730
commit 8d206fd2c8
4 changed files with 349 additions and 0 deletions

View File

@ -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 }) => (
<RelationPickerScopeInternalContext.Provider value={{ scopeId }}>
<RecoilRoot>{children}</RecoilRoot>
</RelationPickerScopeInternalContext.Provider>
);
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<HTMLInputElement>);
});
expect(result.current.searchFilter).toBe(filter);
});
});

View File

@ -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 }) => (
<RelationPickerScopeInternalContext.Provider value={{ scopeId }}>
<RecoilRoot>{children}</RecoilRoot>
</RelationPickerScopeInternalContext.Provider>
);
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,
});
});
});

View File

@ -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 }) => (
<RelationPickerScopeInternalContext.Provider value={{ scopeId }}>
<RecoilRoot>{children}</RecoilRoot>
</RelationPickerScopeInternalContext.Provider>
);
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}`,
);
});
});

View File

@ -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 }) => (
<MockedProvider mocks={mocks} addTypename={false}>
<RecoilRoot>{children}</RecoilRoot>
</MockedProvider>
);
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,
);
});
});