@ -1,14 +1,17 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { MockedProvider, MockedResponse } from '@apollo/client/testing';
|
||||
import { act, renderHook, waitFor } from '@testing-library/react';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { ReactNode } from 'react';
|
||||
import { RecoilRoot, useSetRecoilState } from 'recoil';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
import { useActivities } from '@/activities/hooks/useActivities';
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope';
|
||||
import { mockWorkspaceMembers } from '~/testing/mock-data/workspace-members';
|
||||
|
||||
jest.mock('@/activities/hooks/useActivityTargetsForTargetableObjects', () => ({
|
||||
useActivityTargetsForTargetableObjects: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('@/object-record/hooks/useFindManyRecords', () => ({
|
||||
useFindManyRecords: jest.fn(),
|
||||
}));
|
||||
|
||||
const mockActivityTarget = {
|
||||
__typename: 'ActivityTarget',
|
||||
@ -22,6 +25,7 @@ const mockActivityTarget = {
|
||||
|
||||
const mockActivity = {
|
||||
__typename: 'Task',
|
||||
companyId: '123',
|
||||
updatedAt: '2021-08-03T19:20:06.000Z',
|
||||
createdAt: '2021-08-03T19:20:06.000Z',
|
||||
status: 'DONE',
|
||||
@ -33,168 +37,35 @@ const mockActivity = {
|
||||
id: '234',
|
||||
};
|
||||
|
||||
const defaultResponseData = {
|
||||
pageInfo: {
|
||||
hasNextPage: false,
|
||||
startCursor: '',
|
||||
endCursor: '',
|
||||
},
|
||||
totalCount: 1,
|
||||
};
|
||||
|
||||
const mocks: MockedResponse[] = [
|
||||
{
|
||||
request: {
|
||||
query: gql`
|
||||
query FindManyActivityTargets(
|
||||
$filter: ActivityTargetFilterInput
|
||||
$orderBy: [ActivityTargetOrderByInput]
|
||||
$lastCursor: String
|
||||
$limit: Int
|
||||
) {
|
||||
activityTargets(
|
||||
filter: $filter
|
||||
orderBy: $orderBy
|
||||
first: $limit
|
||||
after: $lastCursor
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
updatedAt
|
||||
createdAt
|
||||
activityId
|
||||
id
|
||||
}
|
||||
cursor
|
||||
}
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
hasPreviousPage
|
||||
startCursor
|
||||
endCursor
|
||||
}
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
filter: { companyId: { eq: '123' } },
|
||||
limit: undefined,
|
||||
orderBy: undefined,
|
||||
},
|
||||
},
|
||||
result: jest.fn(() => ({
|
||||
data: {
|
||||
activityTargets: {
|
||||
...defaultResponseData,
|
||||
edges: [
|
||||
{
|
||||
node: mockActivityTarget,
|
||||
cursor: '1',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
})),
|
||||
},
|
||||
{
|
||||
request: {
|
||||
query: gql`
|
||||
query FindManyTasks(
|
||||
$filter: TaskFilterInput
|
||||
$orderBy: [TaskOrderByInput]
|
||||
$lastCursor: String
|
||||
$limit: Int
|
||||
) {
|
||||
tasks(
|
||||
filter: $filter
|
||||
orderBy: $orderBy
|
||||
first: $limit
|
||||
after: $lastCursor
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
title
|
||||
id
|
||||
updatedAt
|
||||
createdAt
|
||||
body
|
||||
status
|
||||
dueAt
|
||||
}
|
||||
cursor
|
||||
}
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
hasPreviousPage
|
||||
startCursor
|
||||
endCursor
|
||||
}
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
filter: { id: { in: ['234'] } },
|
||||
limit: undefined,
|
||||
orderBy: [{}],
|
||||
},
|
||||
},
|
||||
result: jest.fn(() => ({
|
||||
data: {
|
||||
activities: {
|
||||
...defaultResponseData,
|
||||
edges: [
|
||||
{
|
||||
node: mockActivity,
|
||||
cursor: '1',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
})),
|
||||
},
|
||||
];
|
||||
|
||||
const Wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<RecoilRoot>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
||||
{children}
|
||||
</SnackBarProviderScope>
|
||||
</MockedProvider>
|
||||
</RecoilRoot>
|
||||
<RecoilRoot>{children}</RecoilRoot>
|
||||
);
|
||||
|
||||
describe('useActivities', () => {
|
||||
it('returns default response', () => {
|
||||
const { result } = renderHook(
|
||||
() =>
|
||||
useActivities({
|
||||
objectNameSingular: CoreObjectNameSingular.Task,
|
||||
targetableObjects: [],
|
||||
activitiesFilters: {},
|
||||
activitiesOrderByVariables: [{}],
|
||||
skip: false,
|
||||
}),
|
||||
{ wrapper: Wrapper },
|
||||
);
|
||||
|
||||
expect(result.current).toEqual({
|
||||
activities: [],
|
||||
loading: false,
|
||||
});
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('fetches activities', async () => {
|
||||
const useActivityTargetsForTargetableObjectsMock = jest.requireMock(
|
||||
'@/activities/hooks/useActivityTargetsForTargetableObjects',
|
||||
);
|
||||
useActivityTargetsForTargetableObjectsMock.useActivityTargetsForTargetableObjects.mockReturnValue(
|
||||
{
|
||||
activityTargets: [mockActivityTarget],
|
||||
loadingActivityTargets: false,
|
||||
},
|
||||
);
|
||||
|
||||
const useFindManyRecordsMock = jest.requireMock(
|
||||
'@/object-record/hooks/useFindManyRecords',
|
||||
);
|
||||
useFindManyRecordsMock.useFindManyRecords.mockReturnValue({
|
||||
records: [mockActivity],
|
||||
});
|
||||
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
const setCurrentWorkspaceMember = useSetRecoilState(
|
||||
currentWorkspaceMemberState,
|
||||
);
|
||||
|
||||
const activities = useActivities({
|
||||
objectNameSingular: CoreObjectNameSingular.Task,
|
||||
targetableObjects: [
|
||||
@ -204,21 +75,11 @@ describe('useActivities', () => {
|
||||
activitiesOrderByVariables: [{}],
|
||||
skip: false,
|
||||
});
|
||||
return { activities, setCurrentWorkspaceMember };
|
||||
return activities;
|
||||
},
|
||||
{ wrapper: Wrapper },
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.setCurrentWorkspaceMember(mockWorkspaceMembers[0]);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.activities.loading).toBe(false);
|
||||
});
|
||||
|
||||
const { activities } = result.current;
|
||||
|
||||
expect(activities.activities).toEqual([mockActivity]);
|
||||
expect(result.current.activities).toEqual([mockActivity]);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,11 +1,17 @@
|
||||
import { renderHook } from '@testing-library/react';
|
||||
|
||||
import { useTimelineActivities } from '@/activities/timelineActivities/hooks/useTimelineActivities';
|
||||
import { ReactNode } from 'react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
jest.mock('@/object-record/hooks/useFindManyRecords', () => ({
|
||||
useFindManyRecords: jest.fn(),
|
||||
}));
|
||||
|
||||
const Wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<RecoilRoot>{children}</RecoilRoot>
|
||||
);
|
||||
|
||||
describe('useTimelineActivities', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
@ -52,8 +58,9 @@ describe('useTimelineActivities', () => {
|
||||
records: mockedTimelineActivities,
|
||||
});
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useTimelineActivities(mockTargetableObject),
|
||||
const { result } = renderHook(
|
||||
() => useTimelineActivities(mockTargetableObject),
|
||||
{ wrapper: Wrapper },
|
||||
);
|
||||
|
||||
expect(result.current.timelineActivities).toEqual(mockedTimelineActivities);
|
||||
@ -1,12 +1,20 @@
|
||||
import { TimelineActivity } from '@/activities/timelineActivities/types/TimelineActivity';
|
||||
import { filterOutInvalidTimelineActivities } from '@/activities/timelineActivities/utils/filterOutInvalidTimelineActivities';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
|
||||
const noteObjectMetadataItem = {
|
||||
nameSingular: CoreObjectNameSingular.Note,
|
||||
namePlural: 'notes',
|
||||
fields: [{ name: 'field1' }, { name: 'field2' }, { name: 'field3' }],
|
||||
} as ObjectMetadataItem;
|
||||
|
||||
describe('filterOutInvalidTimelineActivities', () => {
|
||||
it('should filter out TimelineActivities with deleted fields from the properties diff', () => {
|
||||
const events = [
|
||||
{
|
||||
id: '1',
|
||||
name: 'event1',
|
||||
properties: {
|
||||
diff: {
|
||||
field1: { before: 'value1', after: 'value2' },
|
||||
@ -17,6 +25,7 @@ describe('filterOutInvalidTimelineActivities', () => {
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'event2',
|
||||
properties: {
|
||||
diff: {
|
||||
field1: { before: 'value7', after: 'value8' },
|
||||
@ -36,12 +45,13 @@ describe('filterOutInvalidTimelineActivities', () => {
|
||||
const filteredEvents = filterOutInvalidTimelineActivities(
|
||||
events,
|
||||
'objectNameSingular',
|
||||
[mainObjectMetadataItem],
|
||||
[mainObjectMetadataItem, noteObjectMetadataItem],
|
||||
);
|
||||
|
||||
expect(filteredEvents).toEqual([
|
||||
{
|
||||
id: '1',
|
||||
name: 'event1',
|
||||
properties: {
|
||||
diff: {
|
||||
field1: { before: 'value1', after: 'value2' },
|
||||
@ -52,6 +62,7 @@ describe('filterOutInvalidTimelineActivities', () => {
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'event2',
|
||||
properties: {
|
||||
diff: {
|
||||
field1: { before: 'value7', after: 'value8' },
|
||||
@ -66,6 +77,7 @@ describe('filterOutInvalidTimelineActivities', () => {
|
||||
const events = [
|
||||
{
|
||||
id: '1',
|
||||
name: 'event1',
|
||||
properties: {
|
||||
diff: {
|
||||
field3: { before: 'value5', after: 'value6' },
|
||||
@ -74,6 +86,7 @@ describe('filterOutInvalidTimelineActivities', () => {
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'event2',
|
||||
properties: {
|
||||
diff: {
|
||||
field4: { before: 'value11', after: 'value12' },
|
||||
@ -83,13 +96,15 @@ describe('filterOutInvalidTimelineActivities', () => {
|
||||
] as TimelineActivity[];
|
||||
|
||||
const mainObjectMetadataItem = {
|
||||
nameSingular: 'objectNameSingular',
|
||||
namePlural: 'objectNamePlural',
|
||||
fields: [{ name: 'field1' }, { name: 'field2' }],
|
||||
} as ObjectMetadataItem;
|
||||
|
||||
const filteredEvents = filterOutInvalidTimelineActivities(
|
||||
events,
|
||||
'objectNameSingular',
|
||||
[mainObjectMetadataItem],
|
||||
[mainObjectMetadataItem, noteObjectMetadataItem],
|
||||
);
|
||||
|
||||
expect(filteredEvents).toEqual([]);
|
||||
@ -99,22 +114,26 @@ describe('filterOutInvalidTimelineActivities', () => {
|
||||
const events = [
|
||||
{
|
||||
id: '1',
|
||||
name: 'event1',
|
||||
properties: {},
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'event2',
|
||||
properties: {},
|
||||
},
|
||||
] as TimelineActivity[];
|
||||
|
||||
const mainObjectMetadataItem = {
|
||||
nameSingular: 'objectNameSingular',
|
||||
namePlural: 'objectNamePlural',
|
||||
fields: [{ name: 'field1' }, { name: 'field2' }],
|
||||
} as ObjectMetadataItem;
|
||||
|
||||
const filteredEvents = filterOutInvalidTimelineActivities(
|
||||
events,
|
||||
'objectNameSingular',
|
||||
[mainObjectMetadataItem],
|
||||
[mainObjectMetadataItem, noteObjectMetadataItem],
|
||||
);
|
||||
|
||||
expect(filteredEvents).toEqual(events);
|
||||
|
||||
@ -43,7 +43,8 @@ export const filterOutInvalidTimelineActivities = (
|
||||
|
||||
const validDiffEntries = Object.entries(diff).filter(([diffKey]) =>
|
||||
isNoteOrTask
|
||||
? noteFieldMetadataItemMap.has(diffKey)
|
||||
? // Note and Task objects have the same field metadata
|
||||
noteFieldMetadataItemMap.has(diffKey)
|
||||
: fieldMetadataItemMap.has(diffKey),
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user