First batch of modules/activities tests (#4446)

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Matheus <matheus_benini@hotmail.com>
Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com>
This commit is contained in:
gitstart-twenty
2024-03-15 12:32:06 -03:00
committed by GitHub
parent 7b83c84fa5
commit c083bb15cd
9 changed files with 428 additions and 0 deletions

View File

@ -0,0 +1,38 @@
import { act, renderHook } from '@testing-library/react';
import { useEmailThread } from '../useEmailThread';
const mockSetViewableEmailThreadId = jest.fn();
const mockUseOpenEmailThreadRightDrawer = jest.fn();
jest.mock('recoil', () => ({
useSetRecoilState: () => mockSetViewableEmailThreadId,
}));
jest.mock(
'@/activities/emails/right-drawer/hooks/useOpenEmailThreadRightDrawer',
() => ({
useOpenEmailThreadRightDrawer: () => mockUseOpenEmailThreadRightDrawer,
}),
);
jest.mock('@/activities/emails/state/viewableEmailThreadIdState', () => ({
viewableEmailThreadIdState: () => 'mockViewableEmailThreadIdState',
}));
describe('useEmailThread hook', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('openEmailThread function', () => {
const { result } = renderHook(() => useEmailThread());
act(() => {
result.current.openEmailThread('mockThreadId');
});
expect(mockSetViewableEmailThreadId).toHaveBeenCalledWith('mockThreadId');
expect(mockUseOpenEmailThreadRightDrawer).toHaveBeenCalled();
});
});

View File

@ -0,0 +1,37 @@
import { renderHook } from '@testing-library/react';
import { useEmailThreadStates } from '@/activities/emails/hooks/internal/useEmailThreadStates';
const mockScopeId = 'mockScopeId';
const mockGetEmailThreadsPageState = jest.fn();
jest.mock(
'@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId',
() => ({
useAvailableScopeIdOrThrow: () => mockScopeId,
}),
);
jest.mock(
'@/ui/utilities/state/component-state/utils/extractComponentState',
() => ({
extractComponentState: () => mockGetEmailThreadsPageState,
}),
);
describe('useEmailThreadStates hook', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('returns the correct scopeId and getEmailThreadsPageState', () => {
const { result } = renderHook(() =>
useEmailThreadStates({ emailThreadScopeId: 'mockEmailThreadScopeId' }),
);
expect(result.current.scopeId).toBe(mockScopeId);
expect(result.current.getEmailThreadsPageState).toBe(
mockGetEmailThreadsPageState,
);
});
});

View File

@ -0,0 +1,35 @@
import { act } from 'react-dom/test-utils';
import { renderHook } from '@testing-library/react';
import { useOpenEmailThreadRightDrawer } from '@/activities/emails/right-drawer/hooks/useOpenEmailThreadRightDrawer';
import { RightDrawerHotkeyScope } from '@/ui/layout/right-drawer/types/RightDrawerHotkeyScope';
import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages';
const mockOpenRightDrawer = jest.fn();
const mockSetHotkeyScope = jest.fn();
jest.mock('@/ui/layout/right-drawer/hooks/useRightDrawer', () => ({
useRightDrawer: () => ({
openRightDrawer: mockOpenRightDrawer,
}),
}));
jest.mock('@/ui/utilities/hotkey/hooks/useSetHotkeyScope', () => ({
useSetHotkeyScope: () => mockSetHotkeyScope,
}));
test('useOpenEmailThreadRightDrawer opens the email thread right drawer', () => {
const { result } = renderHook(() => useOpenEmailThreadRightDrawer());
act(() => {
result.current();
});
expect(mockSetHotkeyScope).toHaveBeenCalledWith(
RightDrawerHotkeyScope.RightDrawer,
{ goto: false },
);
expect(mockOpenRightDrawer).toHaveBeenCalledWith(
RightDrawerPages.ViewEmailThread,
);
});

View File

@ -0,0 +1,51 @@
import { renderHook } from '@testing-library/react';
import { useAttachments } from '../useAttachments';
jest.mock('@/object-record/hooks/useFindManyRecords', () => ({
useFindManyRecords: jest.fn(),
}));
describe('useAttachments', () => {
afterEach(() => {
jest.clearAllMocks();
});
it('fetches attachments correctly for a given targetableObject', () => {
const mockAttachments = [
{ id: '1', name: 'Attachment 1' },
{ id: 2, name: 'Attachment 2' },
];
const mockTargetableObject = {
id: '1',
targetObjectNameSingular: 'SomeObject',
};
const useFindManyRecordsMock = jest.requireMock(
'@/object-record/hooks/useFindManyRecords',
);
useFindManyRecordsMock.useFindManyRecords.mockReturnValue({
records: mockAttachments,
});
const { result } = renderHook(() => useAttachments(mockTargetableObject));
expect(result.current.attachments).toEqual(mockAttachments);
});
it('handles case when there are no attachments', () => {
const mockTargetableObject = {
id: '1',
targetObjectNameSingular: 'SomeObject',
};
const useFindManyRecordsMock = jest.requireMock(
'@/object-record/hooks/useFindManyRecords',
);
useFindManyRecordsMock.useFindManyRecords.mockReturnValue({ records: [] });
const { result } = renderHook(() => useAttachments(mockTargetableObject));
expect(result.current.attachments).toEqual([]);
});
});

View File

@ -0,0 +1,38 @@
import { renderHook } from '@testing-library/react';
import { RecoilRoot } from 'recoil';
import { useActivityById } from '../useActivityById';
jest.mock('@/object-record/hooks/useFindOneRecord', () => ({
useFindOneRecord: jest.fn(() => ({
record: {
activity: {
id: 'test-activity-id',
name: 'Test Activity',
description: 'This is a test activity',
},
},
loading: false,
})),
}));
describe('useActivityById', () => {
it('fetches activity by id and returns the activity and loading state', async () => {
const activityId = 'test-activity-id';
const { result } = renderHook(() => useActivityById({ activityId }), {
wrapper: RecoilRoot,
});
expect(result.current.loading).toBe(false);
expect(result.current.activity).toEqual({
activity: {
id: 'test-activity-id',
name: 'Test Activity',
description: 'This is a test activity',
},
activityTargets: [],
comments: [],
});
});
});

View File

@ -0,0 +1,52 @@
import { renderHook } from '@testing-library/react';
import { useInjectIntoActivityTargetInlineCellCache } from '@/activities/inline-cell/hooks/useInjectIntoActivityTargetInlineCellCache';
import { Activity } from '@/activities/types/Activity';
jest.mock('@/object-metadata/hooks/useObjectMetadataItemOnly', () => ({
useObjectMetadataItemOnly: jest.fn(() => ({
objectMetadataItem: { exampleMetadataItem: 'example' },
})),
}));
jest.mock(
'@/object-record/cache/hooks/useUpsertFindManyRecordsQueryInCache',
() => ({
useUpsertFindManyRecordsQueryInCache: jest.fn(() => ({
upsertFindManyRecordsQueryInCache: jest.fn(),
})),
}),
);
describe('useInjectIntoActivityTargetInlineCellCache', () => {
it('should inject into activity target inline cell cache as expected', () => {
const { result } = renderHook(() =>
useInjectIntoActivityTargetInlineCellCache(),
);
const { injectIntoActivityTargetInlineCellCache } = result.current;
const mockActivityId = 'mockId';
const mockActivityTargetsToInject = [
{
id: '1',
name: 'Example Activity Target',
createdAt: '2022-01-01',
updatedAt: '2022-01-01',
activity: {
id: '1',
createdAt: '2022-01-01',
updatedAt: '2022-01-01',
} as Pick<Activity, 'id' | 'createdAt' | 'updatedAt'>,
},
];
injectIntoActivityTargetInlineCellCache({
activityId: mockActivityId,
activityTargetsToInject: mockActivityTargetsToInject,
});
expect(
result.current.injectIntoActivityTargetInlineCellCache,
).toBeDefined();
});
});

View File

@ -0,0 +1,45 @@
import { renderHook } from '@testing-library/react';
import { useNotes } from '@/activities/notes/hooks/useNotes';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
jest.mock('@/activities/hooks/useActivities', () => ({
useActivities: jest.fn(() => ({
activities: [{ id: '1', content: 'Example Note' }],
initialized: true,
loading: false,
})),
}));
jest.mock('recoil', () => {
const actualRecoil = jest.requireActual('recoil');
return {
...actualRecoil,
useRecoilState: jest.fn(() => {
const mockCurrentNotesQueryVariables = {
filter: {
type: { eq: 'Note' },
},
orderBy: 'mockOrderBy',
};
return [mockCurrentNotesQueryVariables, jest.fn()];
}),
atom: jest.fn(),
};
});
describe('useNotes', () => {
it('should return notes, initialized, and loading as expected', () => {
const mockTargetableObject: ActivityTargetableObject = {
id: '1',
targetObjectNameSingular: 'Example Target',
};
const { result } = renderHook(() => useNotes(mockTargetableObject));
expect(result.current.notes).toEqual([
{ id: '1', content: 'Example Note' },
]);
expect(result.current.initialized).toBe(true);
expect(result.current.loading).toBe(false);
});
});

View File

@ -0,0 +1,47 @@
import { renderHook } from '@testing-library/react';
import { useCompleteTask } from '@/activities/tasks/hooks/useCompleteTask';
const mockUpdateOneRecord = jest.fn();
jest.mock('@/object-record/hooks/useUpdateOneRecord', () => ({
useUpdateOneRecord: () => ({
updateOneRecord: mockUpdateOneRecord,
}),
}));
describe('useCompleteTask', () => {
it('should complete the task when called with true', async () => {
const taskId = 'test-task-id';
const { result } = renderHook(() =>
useCompleteTask({ id: taskId, completedAt: null }),
);
const { completeTask } = result.current;
completeTask(true);
expect(mockUpdateOneRecord).toHaveBeenCalledWith({
idToUpdate: taskId,
updateOneRecordInput: {
completedAt: expect.any(String),
},
});
});
it('should uncomplete the task when called with false', async () => {
const taskId = 'test-task-id';
const { result } = renderHook(() =>
useCompleteTask({ id: taskId, completedAt: '2021-01-01T00:00:00' }),
);
const { completeTask } = result.current;
completeTask(false);
expect(mockUpdateOneRecord).toHaveBeenCalledWith({
idToUpdate: taskId,
updateOneRecordInput: {
completedAt: null,
},
});
});
});

View File

@ -0,0 +1,85 @@
import { renderHook } from '@testing-library/react';
import { useInjectIntoActivitiesQueries } from '@/activities/hooks/useInjectIntoActivitiesQueries';
import { useInjectIntoTimelineActivitiesQueries } from '@/activities/timeline/hooks/useInjectIntoTimelineActivitiesQueries';
import { Activity } from '@/activities/types/Activity';
import { ActivityTarget } from '@/activities/types/ActivityTarget';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
jest.mock('@/activities/hooks/useInjectIntoActivitiesQueries', () => ({
useInjectIntoActivitiesQueries: jest.fn(() => ({
injectActivitiesQueries: jest.fn(),
})),
}));
describe('useInjectIntoTimelineActivitiesQueries', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('should inject activities into timeline activities queries correctly', () => {
const mockActivityToInject: Activity = {
id: 'activity1',
createdAt: '2022-01-01T00:00:00',
updatedAt: '2022-01-01T00:00:00',
completedAt: '2022-01-01T00:00:00',
__typename: 'Activity',
reminderAt: '2022-01-01T00:00:00',
dueAt: '2022-01-01T00:00:00',
type: 'Task',
activityTargets: [],
title: 'Activity 1',
body: 'Activity 1 body',
author: {
id: 'author1',
name: {
firstName: 'John',
lastName: 'Doe',
},
avatarUrl: 'https://example.com/avatar1.jpg',
},
authorId: 'author1',
assignee: null,
assigneeId: null,
comments: [],
};
const mockActivityTargetsToInject: ActivityTarget[] = [
{
id: 'target1',
updatedAt: '2022-01-01T00:00:00',
createdAt: '2022-01-01T00:00:00',
activity: {
id: 'activity1',
createdAt: '2022-01-01T00:00:00',
updatedAt: '2022-01-01T00:00:00',
},
},
{
id: 'target2',
updatedAt: '2022-01-01T00:00:00',
createdAt: '2022-01-01T00:00:00',
activity: {
id: 'activity1',
createdAt: '2022-01-01T00:00:00',
updatedAt: '2022-01-01T00:00:00',
},
},
];
const mockTimelineTargetableObject: ActivityTargetableObject = {
id: 'timelineTarget1',
targetObjectNameSingular: 'Timeline',
};
const { result } = renderHook(() =>
useInjectIntoTimelineActivitiesQueries(),
);
result.current.injectIntoTimelineActivitiesQueries({
activityToInject: mockActivityToInject,
activityTargetsToInject: mockActivityTargetsToInject,
timelineTargetableObject: mockTimelineTargetableObject,
});
expect(useInjectIntoActivitiesQueries).toHaveBeenCalledTimes(1);
});
});