TWNTY-4450 - Add tests for /modules/activities/emails (#4520)

* Add tests for `/modules/activities/emails`

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com>

* Fix tests

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com>

* Remove temporary changes

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com>

---------

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>
This commit is contained in:
gitstart-app[bot] 2024-03-18 17:10:07 +01:00 committed by GitHub
parent bdbd77c696
commit 872fb2bd49
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 334 additions and 5 deletions

View File

@ -0,0 +1,53 @@
import { act, renderHook } from '@testing-library/react';
import { useCalendarEvents } from '@/activities/calendar/hooks/useCalendarEvents';
import { CalendarEvent } from '@/activities/calendar/types/CalendarEvent';
const calendarEvents: CalendarEvent[] = [
{
id: '1234',
externalCreatedAt: '2024-02-17T20:45:43.854Z',
isFullDay: false,
startsAt: '2024-02-17T21:45:27.822Z',
visibility: 'METADATA',
},
{
id: '5678',
externalCreatedAt: '2024-02-18T19:43:37.854Z',
isFullDay: false,
startsAt: '2024-02-18T21:43:27.754Z',
visibility: 'SHARE_EVERYTHING',
},
{
id: '91011',
externalCreatedAt: '2024-02-19T20:45:20.854Z',
isFullDay: true,
startsAt: '2024-02-19T22:05:27.653Z',
visibility: 'METADATA',
},
{
id: '121314',
externalCreatedAt: '2024-02-20T20:45:12.854Z',
isFullDay: true,
startsAt: '2024-02-20T23:15:23.150Z',
visibility: 'SHARE_EVERYTHING',
},
];
describe('useCalendar', () => {
it('returns calendar events', () => {
const { result } = renderHook(() => useCalendarEvents(calendarEvents));
expect(result.current.currentCalendarEvent).toBe(calendarEvents[0]);
expect(result.current.getNextCalendarEvent(calendarEvents[1])).toBe(
calendarEvents[0],
);
act(() => {
result.current.updateCurrentCalendarEvent();
});
expect(result.current.currentCalendarEvent).toBe(calendarEvents[0]);
});
});

View File

@ -0,0 +1,35 @@
import { act, renderHook } from '@testing-library/react';
import { RecoilRoot, useRecoilValue } from 'recoil';
import { useOpenCalendarEventRightDrawer } from '@/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer';
import { viewableCalendarEventIdState } from '@/activities/calendar/states/viewableCalendarEventIdState';
import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState';
describe('useOpenCalendarEventRightDrawer', () => {
it('opens the right drawer with the calendar event', () => {
const { result } = renderHook(
() => {
const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState());
const viewableCalendarEventId = useRecoilValue(
viewableCalendarEventIdState(),
);
return {
...useOpenCalendarEventRightDrawer(),
isRightDrawerOpen,
viewableCalendarEventId,
};
},
{ wrapper: RecoilRoot },
);
expect(result.current.isRightDrawerOpen).toBe(false);
expect(result.current.viewableCalendarEventId).toBeNull();
act(() => {
result.current.openCalendarEventRightDrawer('1234');
});
expect(result.current.isRightDrawerOpen).toBe(true);
expect(result.current.viewableCalendarEventId).toBe('1234');
});
});

View File

@ -4,7 +4,7 @@ import { useRecoilCallback } from 'recoil';
import { EmailThreadNotShared } from '@/activities/emails/components/EmailThreadNotShared';
import { useEmailThread } from '@/activities/emails/hooks/useEmailThread';
import { emailThreadIdWhenEmailThreadWasClosedState } from '@/activities/emails/state/lastViewableEmailThreadIdState';
import { emailThreadIdWhenEmailThreadWasClosedState } from '@/activities/emails/states/lastViewableEmailThreadIdState';
import { CardContent } from '@/ui/layout/card/components/CardContent';
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
import { GRAY_SCALE } from '@/ui/theme/constants/GrayScale';

View File

@ -0,0 +1,69 @@
import { act, renderHook } from '@testing-library/react';
import { RecoilRoot, useRecoilState, useRecoilValue } from 'recoil';
import { useEmailThread } from '@/activities/emails/hooks/useEmailThread';
import { viewableEmailThreadIdState } from '@/activities/emails/states/viewableEmailThreadIdState';
import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState';
const viewableEmailThreadId = '1234';
describe('useEmailThread', () => {
it('should open email thread', () => {
const { result } = renderHook(
() => {
const emailThread = useEmailThread();
const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState());
const viewableEmailThreadId = useRecoilValue(
viewableEmailThreadIdState(),
);
return { ...emailThread, isRightDrawerOpen, viewableEmailThreadId };
},
{ wrapper: RecoilRoot },
);
expect(result.current.isRightDrawerOpen).toBe(false);
expect(result.current.viewableEmailThreadId).toBeNull();
act(() => {
result.current.openEmailThread(viewableEmailThreadId);
});
expect(result.current.isRightDrawerOpen).toBe(true);
expect(result.current.viewableEmailThreadId).toBe(viewableEmailThreadId);
});
it('should close email thread', () => {
const { result } = renderHook(
() => {
const emailThread = useEmailThread();
const [isRightDrawerOpen, setIsRightDrawerOpen] = useRecoilState(
isRightDrawerOpenState(),
);
const [viewableEmailThreadId, setViewableEmailThreadId] =
useRecoilState(viewableEmailThreadIdState());
return {
...emailThread,
isRightDrawerOpen,
viewableEmailThreadId,
setIsRightDrawerOpen,
setViewableEmailThreadId,
};
},
{ wrapper: RecoilRoot },
);
act(() => {
result.current.setIsRightDrawerOpen(true);
result.current.setViewableEmailThreadId(viewableEmailThreadId);
});
act(() => {
result.current.openEmailThread(viewableEmailThreadId);
});
expect(result.current.isRightDrawerOpen).toBe(false);
expect(result.current.viewableEmailThreadId).toBeNull();
});
});

View File

@ -1,4 +1,4 @@
import { emailThreadsPageComponentState } from '@/activities/emails/state/emailThreadsPageComponentState';
import { emailThreadsPageComponentState } from '@/activities/emails/states/emailThreadsPageComponentState';
import { TabListScopeInternalContext } from '@/ui/layout/tab/scopes/scope-internal-context/TabListScopeInternalContext';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';

View File

@ -1,7 +1,7 @@
import { useRecoilCallback } from 'recoil';
import { useOpenEmailThreadRightDrawer } from '@/activities/emails/right-drawer/hooks/useOpenEmailThreadRightDrawer';
import { viewableEmailThreadIdState } from '@/activities/emails/state/viewableEmailThreadIdState';
import { viewableEmailThreadIdState } from '@/activities/emails/states/viewableEmailThreadIdState';
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState';

View File

@ -0,0 +1,16 @@
import { gql } from '@apollo/client';
import { getTimelineThreadsFromCompanyId } from '../getTimelineThreadsFromCompanyId';
jest.mock('@apollo/client', () => ({
gql: jest.fn().mockImplementation((strings) => {
return strings.map((str: string) => str.trim()).join(' ');
}),
}));
describe('getTimelineThreadsFromCompanyId query', () => {
test('should construct the query correctly', () => {
expect(gql).toHaveBeenCalled();
expect(getTimelineThreadsFromCompanyId).toBeDefined();
});
});

View File

@ -0,0 +1,16 @@
import { gql } from '@apollo/client';
import { getTimelineThreadsFromPersonId } from '../getTimelineThreadsFromPersonId';
jest.mock('@apollo/client', () => ({
gql: jest.fn().mockImplementation((strings) => {
return strings.map((str: string) => str.trim()).join(' ');
}),
}));
describe('getTimelineThreadsFromPersonId query', () => {
test('should construct the query correctly', () => {
expect(gql).toHaveBeenCalled();
expect(getTimelineThreadsFromPersonId).toBeDefined();
});
});

View File

@ -6,7 +6,7 @@ import { EmailThreadFetchMoreLoader } from '@/activities/emails/components/Email
import { EmailThreadHeader } from '@/activities/emails/components/EmailThreadHeader';
import { EmailThreadMessage } from '@/activities/emails/components/EmailThreadMessage';
import { useRightDrawerEmailThread } from '@/activities/emails/right-drawer/hooks/useRightDrawerEmailThread';
import { emailThreadIdWhenEmailThreadWasClosedState } from '@/activities/emails/state/lastViewableEmailThreadIdState';
import { emailThreadIdWhenEmailThreadWasClosedState } from '@/activities/emails/states/lastViewableEmailThreadIdState';
import { RIGHT_DRAWER_CLICK_OUTSIDE_LISTENER_ID } from '@/ui/layout/right-drawer/constants/RightDrawerClickOutsideListener';
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';

View File

@ -0,0 +1,40 @@
import { MockedProvider } from '@apollo/client/testing';
import { renderHook } from '@testing-library/react';
import { RecoilRoot } from 'recoil';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { useRightDrawerEmailThread } from '../useRightDrawerEmailThread';
jest.mock('@/object-record/hooks/useFindManyRecords', () => ({
__esModule: true,
useFindManyRecords: jest.fn(),
}));
describe('useRightDrawerEmailThread', () => {
it('should return correct values', async () => {
const mockMessages = [
{ id: '1', text: 'Message 1' },
{ id: '2', text: 'Message 2' },
];
const mockFetchMoreRecords = jest.fn();
(useFindManyRecords as jest.Mock).mockReturnValue({
records: mockMessages,
loading: false,
fetchMoreRecords: mockFetchMoreRecords,
});
const { result } = renderHook(() => useRightDrawerEmailThread(), {
wrapper: ({ children }) => (
<MockedProvider mocks={[]} addTypename={false}>
<RecoilRoot>{children}</RecoilRoot>
</MockedProvider>
),
});
expect(result.current.thread).toBeDefined();
expect(result.current.messages).toEqual(mockMessages);
expect(result.current.loading).toBeFalsy();
expect(result.current.fetchMoreMessages).toBeInstanceOf(Function);
});
});

View File

@ -3,7 +3,7 @@ import { useApolloClient } from '@apollo/client';
import gql from 'graphql-tag';
import { useRecoilValue } from 'recoil';
import { viewableEmailThreadIdState } from '@/activities/emails/state/viewableEmailThreadIdState';
import { viewableEmailThreadIdState } from '@/activities/emails/states/viewableEmailThreadIdState';
import { EmailThreadMessage as EmailThreadMessageType } from '@/activities/emails/types/EmailThreadMessage';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';

View File

@ -0,0 +1,100 @@
import { EmailThreadMessageParticipant } from '@/activities/emails/types/EmailThreadMessageParticipant';
import { getDisplayNameFromParticipant } from '../getDisplayNameFromParticipant';
describe('getDisplayNameFromParticipant', () => {
const participantWithName: EmailThreadMessageParticipant = {
displayName: '',
handle: '',
role: 'from',
person: {
id: '1',
createdAt: '',
updatedAt: '',
deletedAt: null,
name: {
firstName: 'John',
lastName: 'Doe',
},
avatarUrl: '',
jobTitle: '',
linkedinLink: {
url: '',
label: '',
},
xLink: {
url: '',
label: '',
},
city: '',
email: '',
phone: '',
companyId: '',
},
workspaceMember: {
id: '1',
name: {
firstName: 'Jane',
lastName: 'Smith',
},
locale: '',
createdAt: '',
updatedAt: '',
userEmail: '',
userId: '',
},
};
const participantWithHandle: any = {
displayName: '',
handle: 'user_handle',
role: 'from',
};
const participantWithDisplayName: any = {
displayName: 'User123',
handle: '',
role: 'from',
};
const participantWithoutInfo: any = {
displayName: '',
handle: '',
role: 'from',
};
it('should return full name when shouldUseFullName is true', () => {
expect(
getDisplayNameFromParticipant({
participant: participantWithName,
shouldUseFullName: true,
}),
).toBe('John Doe');
});
it('should return first name when shouldUseFullName is false', () => {
expect(
getDisplayNameFromParticipant({ participant: participantWithName }),
).toBe('John');
});
it('should return displayName if it is a non-empty string', () => {
expect(
getDisplayNameFromParticipant({
participant: participantWithDisplayName,
}),
).toBe('User123');
});
it('should return handle if displayName is not available', () => {
expect(
getDisplayNameFromParticipant({ participant: participantWithHandle }),
).toBe('user_handle');
});
it('should return Unknown if no suitable information is available', () => {
expect(
getDisplayNameFromParticipant({ participant: participantWithoutInfo }),
).toBe('Unknown');
});
});