Skip to content

Commit 325cd5b

Browse files
committed
Add unit tests for Tasks service
1 parent c76bb03 commit 325cd5b

File tree

12 files changed

+1468
-25
lines changed

12 files changed

+1468
-25
lines changed

src/models/action-center/tasks.types.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export interface TaskActivity {
9494
activityType: TaskActivityType;
9595
creatorUserId: number;
9696
targetUserId: number | null;
97-
creationTime: string;
97+
createdTime: string;
9898
}
9999

100100
export interface TaskSlaDetail {
@@ -121,20 +121,21 @@ export interface TaskBaseResponse {
121121
folderId: number;
122122
key: string;
123123
isDeleted: boolean;
124-
creationTime: string;
124+
createdTime: string;
125125
id: number;
126126
action: string | null;
127127
externalTag: string | null;
128128
lastAssignedTime: string | null;
129-
completionTime: string | null;
129+
completedTime: string | null;
130130
parentOperationId: string | null;
131131
deleterUserId: number | null;
132-
deletionTime: string | null;
133-
lastModificationTime: string | null;
132+
deletedTime: string | null;
133+
lastModifiedTime: string | null;
134134
}
135135

136136
export interface TaskCreateOptions {
137137
title: string;
138+
data?: Record<string, unknown>;
138139
priority?: TaskPriority;
139140
}
140141

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/**
2+
* Action Center models test exports
3+
*/
4+
5+
export * from './tasks.test';
Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
// ===== IMPORTS =====
2+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
3+
import { createTaskWithMethods } from '../../../../src/models/action-center/tasks.models';
4+
import type { TaskServiceModel } from '../../../../src/models/action-center/tasks.models';
5+
import { TaskType, TaskPriority} from '../../../../src/models/action-center/tasks.types';
6+
import { createBasicTask } from '../../../utils/mocks/tasks';
7+
import { createMockOperationResponse } from '../../../utils/mocks/core';
8+
import { TASK_TEST_CONSTANTS } from '../../../utils/constants/tasks';
9+
import { TEST_CONSTANTS } from '../../../utils/constants/common';
10+
11+
// ===== TEST SUITE =====
12+
describe('Task Models', () => {
13+
let mockService: TaskServiceModel;
14+
15+
beforeEach(() => {
16+
// Create a mock service
17+
mockService = {
18+
assign: vi.fn(),
19+
reassign: vi.fn(),
20+
unassign: vi.fn(),
21+
complete: vi.fn(),
22+
create: vi.fn(),
23+
getAll: vi.fn(),
24+
getById: vi.fn(),
25+
getUsers: vi.fn(),
26+
} as any;
27+
});
28+
29+
afterEach(() => {
30+
vi.clearAllMocks();
31+
});
32+
33+
describe('bound methods on task', () => {
34+
describe('task.assign()', () => {
35+
it('should call task.assign with userId', async () => {
36+
const taskData = createBasicTask();
37+
const task = createTaskWithMethods(taskData, mockService);
38+
39+
const mockResponse = createMockOperationResponse([
40+
{ taskId: TASK_TEST_CONSTANTS.TASK_ID, userId: TASK_TEST_CONSTANTS.USER_ID }
41+
]);
42+
mockService.assign = vi.fn().mockResolvedValue(mockResponse);
43+
44+
45+
const result = await task.assign({ userId: TASK_TEST_CONSTANTS.USER_ID });
46+
47+
48+
expect(mockService.assign).toHaveBeenCalledWith({
49+
taskId: TASK_TEST_CONSTANTS.TASK_ID,
50+
userId: TASK_TEST_CONSTANTS.USER_ID
51+
});
52+
expect(result).toEqual(mockResponse);
53+
});
54+
55+
it('should call task.assign with userNameOrEmail', async () => {
56+
const taskData = createBasicTask();
57+
const task = createTaskWithMethods(taskData, mockService);
58+
59+
const mockResponse = createMockOperationResponse([
60+
{ taskId: TASK_TEST_CONSTANTS.TASK_ID, userNameOrEmail: TASK_TEST_CONSTANTS.USER_EMAIL }
61+
]);
62+
mockService.assign = vi.fn().mockResolvedValue(mockResponse);
63+
64+
65+
const result = await task.assign({ userNameOrEmail: TASK_TEST_CONSTANTS.USER_EMAIL });
66+
67+
68+
expect(mockService.assign).toHaveBeenCalledWith({
69+
taskId: TASK_TEST_CONSTANTS.TASK_ID,
70+
userNameOrEmail: TASK_TEST_CONSTANTS.USER_EMAIL
71+
});
72+
expect(result).toEqual(mockResponse);
73+
});
74+
75+
it('should throw error if taskId is undefined', async () => {
76+
const taskData = createBasicTask({ id: undefined });
77+
const task = createTaskWithMethods(taskData, mockService);
78+
79+
80+
await expect(task.assign({ userId: TASK_TEST_CONSTANTS.USER_ID })).rejects.toThrow('Task ID is undefined');
81+
});
82+
});
83+
84+
describe('task.reassign()', () => {
85+
it('should call task.reassign with userId', async () => {
86+
const taskData = createBasicTask();
87+
const task = createTaskWithMethods(taskData, mockService);
88+
89+
const mockResponse = createMockOperationResponse([
90+
{ taskId: TASK_TEST_CONSTANTS.TASK_ID, userId: TASK_TEST_CONSTANTS.USER_ID }
91+
]);
92+
mockService.reassign = vi.fn().mockResolvedValue(mockResponse);
93+
94+
95+
const result = await task.reassign({ userId: TASK_TEST_CONSTANTS.USER_ID });
96+
97+
98+
expect(mockService.reassign).toHaveBeenCalledWith({
99+
taskId: TASK_TEST_CONSTANTS.TASK_ID,
100+
userId: TASK_TEST_CONSTANTS.USER_ID
101+
});
102+
expect(result).toEqual(mockResponse);
103+
});
104+
105+
it('should call task.reassign with userNameOrEmail', async () => {
106+
const taskData = createBasicTask();
107+
const task = createTaskWithMethods(taskData, mockService);
108+
109+
const mockResponse = createMockOperationResponse([
110+
{ taskId: TASK_TEST_CONSTANTS.TASK_ID, userNameOrEmail: TASK_TEST_CONSTANTS.USER_EMAIL }
111+
]);
112+
mockService.reassign = vi.fn().mockResolvedValue(mockResponse);
113+
114+
115+
const result = await task.reassign({ userNameOrEmail: TASK_TEST_CONSTANTS.USER_EMAIL });
116+
117+
118+
expect(mockService.reassign).toHaveBeenCalledWith({
119+
taskId: TASK_TEST_CONSTANTS.TASK_ID,
120+
userNameOrEmail: TASK_TEST_CONSTANTS.USER_EMAIL
121+
});
122+
expect(result).toEqual(mockResponse);
123+
});
124+
125+
it('should throw error if taskId is undefined', async () => {
126+
const taskData = createBasicTask({ id: undefined });
127+
const task = createTaskWithMethods(taskData, mockService);
128+
129+
130+
await expect(task.reassign({ userId: TASK_TEST_CONSTANTS.USER_ID })).rejects.toThrow('Task ID is undefined');
131+
});
132+
});
133+
134+
describe('task.unassign()', () => {
135+
it('should call task.unassign', async () => {
136+
const taskData = createBasicTask();
137+
const task = createTaskWithMethods(taskData, mockService);
138+
139+
const mockResponse = createMockOperationResponse([
140+
{ taskId: TASK_TEST_CONSTANTS.TASK_ID }
141+
]);
142+
mockService.unassign = vi.fn().mockResolvedValue(mockResponse);
143+
144+
145+
const result = await task.unassign();
146+
147+
148+
expect(mockService.unassign).toHaveBeenCalledWith(TASK_TEST_CONSTANTS.TASK_ID);
149+
expect(result).toEqual(mockResponse);
150+
});
151+
152+
it('should throw error if taskId is undefined', async () => {
153+
const taskData = createBasicTask({ id: undefined });
154+
const task = createTaskWithMethods(taskData, mockService);
155+
156+
157+
await expect(task.unassign()).rejects.toThrow('Task ID is undefined');
158+
});
159+
});
160+
161+
describe('task.complete()', () => {
162+
it('should call task.complete for external task', async () => {
163+
const taskData = createBasicTask({ folderId: TEST_CONSTANTS.FOLDER_ID, type: TaskType.External });
164+
const task = createTaskWithMethods(taskData, mockService);
165+
166+
const mockResponse = createMockOperationResponse({
167+
type: TaskType.External,
168+
taskId: TASK_TEST_CONSTANTS.TASK_ID
169+
});
170+
mockService.complete = vi.fn().mockResolvedValue(mockResponse);
171+
172+
173+
const result = await task.complete({
174+
type: TaskType.External
175+
});
176+
177+
178+
expect(mockService.complete).toHaveBeenCalledWith(
179+
{
180+
type: TaskType.External,
181+
taskId: TASK_TEST_CONSTANTS.TASK_ID,
182+
data: undefined,
183+
action: undefined
184+
},
185+
TEST_CONSTANTS.FOLDER_ID
186+
);
187+
expect(result).toEqual(mockResponse);
188+
});
189+
190+
it('should call task.complete for app task', async () => {
191+
const taskData = createBasicTask({ folderId: TEST_CONSTANTS.FOLDER_ID, type: TaskType.App });
192+
const task = createTaskWithMethods(taskData, mockService);
193+
194+
const mockResponse = createMockOperationResponse({
195+
type: TaskType.App,
196+
taskId: TASK_TEST_CONSTANTS.TASK_ID,
197+
data: {},
198+
action: TASK_TEST_CONSTANTS.ACTION_APPROVE
199+
});
200+
mockService.complete = vi.fn().mockResolvedValue(mockResponse);
201+
202+
203+
const result = await task.complete({
204+
type: TaskType.App,
205+
data: TASK_TEST_CONSTANTS.APP_TASK_DATA,
206+
action: TASK_TEST_CONSTANTS.ACTION_APPROVE
207+
});
208+
209+
210+
expect(mockService.complete).toHaveBeenCalledWith(
211+
{
212+
type: TaskType.App,
213+
taskId: TASK_TEST_CONSTANTS.TASK_ID,
214+
data: TASK_TEST_CONSTANTS.APP_TASK_DATA,
215+
action: TASK_TEST_CONSTANTS.ACTION_APPROVE
216+
},
217+
TEST_CONSTANTS.FOLDER_ID
218+
);
219+
expect(result).toEqual(mockResponse);
220+
});
221+
222+
it('should call task.complete for form task', async () => {
223+
const taskData = createBasicTask({ folderId: TEST_CONSTANTS.FOLDER_ID, type: TaskType.Form });
224+
const task = createTaskWithMethods(taskData, mockService);
225+
226+
const mockResponse = createMockOperationResponse({
227+
type: TaskType.Form,
228+
taskId: TASK_TEST_CONSTANTS.TASK_ID,
229+
data: TASK_TEST_CONSTANTS.FORM_DATA,
230+
action: TASK_TEST_CONSTANTS.ACTION_SUBMIT
231+
});
232+
mockService.complete = vi.fn().mockResolvedValue(mockResponse);
233+
234+
235+
const result = await task.complete({
236+
type: TaskType.Form,
237+
data: TASK_TEST_CONSTANTS.FORM_DATA,
238+
action: TASK_TEST_CONSTANTS.ACTION_SUBMIT
239+
});
240+
241+
242+
expect(mockService.complete).toHaveBeenCalledWith(
243+
{
244+
type: TaskType.Form,
245+
taskId: TASK_TEST_CONSTANTS.TASK_ID,
246+
data: TASK_TEST_CONSTANTS.FORM_DATA,
247+
action: TASK_TEST_CONSTANTS.ACTION_SUBMIT
248+
},
249+
TEST_CONSTANTS.FOLDER_ID
250+
);
251+
expect(result).toEqual(mockResponse);
252+
});
253+
254+
it('should throw error if taskId is undefined', async () => {
255+
const taskData = createBasicTask({ id: undefined });
256+
const task = createTaskWithMethods(taskData, mockService);
257+
258+
259+
await expect(task.complete({
260+
type: TaskType.External,
261+
data: {},
262+
action: TASK_TEST_CONSTANTS.ACTION_SUBMIT
263+
})).rejects.toThrow('Task ID is undefined');
264+
});
265+
266+
it('should throw error if folderId is undefined', async () => {
267+
const taskData = createBasicTask({ folderId: undefined });
268+
const task = createTaskWithMethods(taskData, mockService);
269+
270+
271+
await expect(task.complete({
272+
type: TaskType.External,
273+
data: {},
274+
action: TASK_TEST_CONSTANTS.ACTION_SUBMIT
275+
})).rejects.toThrow('Folder ID is required');
276+
});
277+
});
278+
});
279+
280+
describe('Task data and methods are combined correctly', () => {
281+
it('should preserve all task properties', () => {
282+
const taskData = createBasicTask();
283+
const task = createTaskWithMethods(taskData, mockService);
284+
285+
expect(task.id).toBe(TASK_TEST_CONSTANTS.TASK_ID);
286+
expect(task.title).toBe(TASK_TEST_CONSTANTS.TASK_TITLE);
287+
expect(task.type).toBe(TaskType.External);
288+
expect(task.priority).toBe(TaskPriority.Medium);
289+
expect(task.folderId).toBe(TEST_CONSTANTS.FOLDER_ID);
290+
expect(task.key).toBe(TASK_TEST_CONSTANTS.TASK_KEY);
291+
});
292+
293+
it('should have all methods available', () => {
294+
const taskData = createBasicTask();
295+
const task = createTaskWithMethods(taskData, mockService);
296+
297+
expect(typeof task.assign).toBe('function');
298+
expect(typeof task.reassign).toBe('function');
299+
expect(typeof task.unassign).toBe('function');
300+
expect(typeof task.complete).toBe('function');
301+
});
302+
});
303+
});
304+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/**
2+
* Action Center services test exports
3+
*/
4+
5+
export * from './tasks.test';

0 commit comments

Comments
 (0)