Skip to content

Commit 3ba4c10

Browse files
committed
feat: Added test cases for departed users api changes.
1 parent 36e067d commit 3ba4c10

File tree

6 files changed

+439
-3
lines changed

6 files changed

+439
-3
lines changed
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
const usersData = [
2+
{
3+
id: "user1_id",
4+
discordId: "123456789",
5+
github_id: "github_user1",
6+
username: "archived_user1",
7+
first_name: "Archived",
8+
last_name: "User One",
9+
linkedin_id: "archived_user1",
10+
github_display_name: "archived-user-1",
11+
phone: "1234567890",
12+
13+
roles: {
14+
archived: true,
15+
in_discord: false,
16+
},
17+
discordJoinedAt: "2024-01-01T00:00:00.000Z",
18+
picture: {
19+
publicId: "profile/user1",
20+
url: "https://example.com/user1.jpg",
21+
},
22+
},
23+
{
24+
id: "user2_id",
25+
discordId: "987654321",
26+
github_id: "github_user2",
27+
username: "archived_user2",
28+
first_name: "Archived",
29+
last_name: "User Two",
30+
linkedin_id: "archived_user2",
31+
github_display_name: "archived-user-2",
32+
phone: "0987654321",
33+
34+
roles: {
35+
archived: true,
36+
in_discord: false,
37+
},
38+
discordJoinedAt: "2024-01-02T00:00:00.000Z",
39+
picture: {
40+
publicId: "profile/user2",
41+
url: "https://example.com/user2.jpg",
42+
},
43+
},
44+
{
45+
id: "user3_id",
46+
discordId: "555555555",
47+
github_id: "github_user3",
48+
username: "active_user",
49+
first_name: "Active",
50+
last_name: "User",
51+
linkedin_id: "active_user",
52+
github_display_name: "active-user",
53+
phone: "5555555555",
54+
55+
roles: {
56+
archived: false,
57+
in_discord: true,
58+
},
59+
discordJoinedAt: "2024-01-03T00:00:00.000Z",
60+
picture: {
61+
publicId: "profile/user3",
62+
url: "https://example.com/user3.jpg",
63+
},
64+
},
65+
];
66+
67+
const tasksData = [
68+
{
69+
id: "task1_id",
70+
title: "Abandoned Task 1",
71+
type: "feature",
72+
status: "IN_PROGRESS",
73+
priority: "HIGH",
74+
percentCompleted: 50,
75+
createdAt: 1727027666,
76+
updatedAt: 1727027999,
77+
startedOn: 1727027777,
78+
endsOn: 1731542400,
79+
assignee: "archived_user1",
80+
assigneeId: "user1_id",
81+
github: {
82+
issue: {
83+
html_url: "https://github.com/org/repo/issues/1",
84+
url: "https://api.github.com/repos/org/repo/issues/1",
85+
},
86+
},
87+
dependsOn: [],
88+
},
89+
{
90+
id: "task2_id",
91+
title: "Abandoned Task 2",
92+
type: "bug",
93+
status: "BLOCKED",
94+
priority: "MEDIUM",
95+
percentCompleted: 30,
96+
createdAt: 1727027666,
97+
updatedAt: 1727027999,
98+
startedOn: 1727027777,
99+
endsOn: 1731542400,
100+
assignee: "archived_user2",
101+
assigneeId: "user2_id",
102+
github: {
103+
issue: {
104+
html_url: "https://github.com/org/repo/issues/2",
105+
url: "https://api.github.com/repos/org/repo/issues/2",
106+
},
107+
},
108+
dependsOn: [],
109+
},
110+
{
111+
id: "task3_id",
112+
title: "Completed Archived Task",
113+
type: "feature",
114+
status: "DONE",
115+
priority: "LOW",
116+
percentCompleted: 100,
117+
createdAt: 1727027666,
118+
updatedAt: 1727027999,
119+
startedOn: 1727027777,
120+
endsOn: 1731542400,
121+
assignee: "archived_user1",
122+
assigneeId: "user1_id",
123+
github: {
124+
issue: {
125+
html_url: "https://github.com/org/repo/issues/3",
126+
url: "https://api.github.com/repos/org/repo/issues/3",
127+
},
128+
},
129+
dependsOn: [],
130+
},
131+
{
132+
id: "task4_id",
133+
title: "Active User Task",
134+
type: "feature",
135+
status: "IN_PROGRESS",
136+
priority: "HIGH",
137+
percentCompleted: 75,
138+
createdAt: 1727027666,
139+
updatedAt: 1727027999,
140+
startedOn: 1727027777,
141+
endsOn: 1731542400,
142+
assignee: "active_user",
143+
assigneeId: "user3_id",
144+
github: {
145+
issue: {
146+
html_url: "https://github.com/org/repo/issues/4",
147+
url: "https://api.github.com/repos/org/repo/issues/4",
148+
},
149+
},
150+
dependsOn: [],
151+
},
152+
];
153+
154+
module.exports = { usersData, tasksData };

test/integration/users.test.js

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,13 @@ const { userPhotoVerificationData } = require("../fixtures/user/photo-verificati
4141
const Sinon = require("sinon");
4242
const { INTERNAL_SERVER_ERROR, SOMETHING_WENT_WRONG } = require("../../constants/errorMessages");
4343
const photoVerificationModel = firestore.collection("photo-verification");
44-
44+
const userModel = firestore.collection("users");
45+
const taskModel = firestore.collection("tasks");
46+
const {
47+
usersData: abandonedUsersData,
48+
tasksData: abandonedTasksData,
49+
} = require("../fixtures/abandoned-tasks/departed-users");
50+
const userService = require("../../services/users");
4551
chai.use(chaiHttp);
4652

4753
describe("Users", function () {
@@ -1441,6 +1447,56 @@ describe("Users", function () {
14411447
});
14421448
});
14431449

1450+
describe("GET /users?departed", function () {
1451+
beforeEach(async function () {
1452+
await cleanDb();
1453+
const userPromises = abandonedUsersData.map((user) => userModel.doc(user.id).set(user));
1454+
await Promise.all(userPromises);
1455+
1456+
const taskPromises = abandonedTasksData.map((task) => taskModel.add(task));
1457+
await Promise.all(taskPromises);
1458+
});
1459+
1460+
afterEach(async function () {
1461+
Sinon.restore();
1462+
await cleanDb();
1463+
});
1464+
1465+
it("should return a list of users with abandoned tasks", async function () {
1466+
const res = await chai.request(app).get("/users?dev=true&departed=true");
1467+
expect(res).to.have.status(200);
1468+
expect(res.body).to.have.property("message").that.equals("Users with abandoned tasks fetched successfully");
1469+
expect(res.body).to.have.property("users").to.be.an("array").with.lengthOf(2);
1470+
});
1471+
1472+
it("should return an empty array when no users have abandoned tasks", async function () {
1473+
await cleanDb();
1474+
const user = abandonedUsersData[2];
1475+
await userModel.add(user);
1476+
1477+
const task = abandonedTasksData[3];
1478+
await taskModel.add(task);
1479+
const res = await chai.request(app).get("/users?dev=true&departed=true");
1480+
1481+
expect(res).to.have.status(204);
1482+
});
1483+
1484+
it("should fail if dev flag is not passed", async function () {
1485+
const res = await chai.request(app).get("/users?departed=true");
1486+
expect(res).to.have.status(404);
1487+
expect(res.body.message).to.be.equal("Route not found");
1488+
});
1489+
1490+
it("should handle errors gracefully if getUsersWithIncompleteTasks fails", async function () {
1491+
Sinon.stub(userService, "getUsersWithIncompleteTasks").rejects(new Error(INTERNAL_SERVER_ERROR));
1492+
1493+
const res = await chai.request(app).get("/users?departed=true&dev=true");
1494+
1495+
expect(res).to.have.status(500);
1496+
expect(res.body.message).to.be.equal(INTERNAL_SERVER_ERROR);
1497+
});
1498+
});
1499+
14441500
describe("PUT /users/self/intro", function () {
14451501
let userStatusData;
14461502

test/unit/models/tasks.test.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ const dependencyModel = firestore.collection("TaskDependencies");
1717
const tasksModel = firestore.collection("tasks");
1818
const userData = require("../../fixtures/user/user");
1919
const addUser = require("../../utils/addUser");
20+
const {
21+
usersData: abandonedUsersData,
22+
tasksData: abandonedTasksData,
23+
} = require("../../fixtures/abandoned-tasks/departed-users");
2024

2125
describe("tasks", function () {
2226
afterEach(async function () {
@@ -352,4 +356,42 @@ describe("tasks", function () {
352356
}
353357
});
354358
});
359+
360+
describe("fetchIncompleteTaskForUser", function () {
361+
beforeEach(async function () {
362+
await cleanDb();
363+
364+
const taskPromises = abandonedTasksData.map((task) => tasksModel.add(task));
365+
await Promise.all(taskPromises);
366+
});
367+
368+
afterEach(async function () {
369+
await cleanDb();
370+
sinon.restore();
371+
});
372+
373+
it("should fetch tasks which are incomplete for the given user", async function () {
374+
const inactiveUser = abandonedUsersData[0];
375+
const incompleteTasks = await tasks.fetchIncompleteTaskForUser(inactiveUser.id);
376+
expect(incompleteTasks.docs.length).to.be.equal(1);
377+
});
378+
379+
it("should return an empty array if there are no tasks incomplete for the user", async function () {
380+
await cleanDb();
381+
const activeUser = abandonedUsersData[2];
382+
const incompleteTasks = await tasks.fetchIncompleteTaskForUser(activeUser.id);
383+
expect(incompleteTasks.docs.length).to.be.equal(0);
384+
});
385+
386+
it("should handle errors gracefully if the database query fails", async function () {
387+
sinon.stub(tasks, "fetchIncompleteTaskForUser").throws(new Error("Database query failed"));
388+
389+
try {
390+
await tasks.fetchIncompleteTaskForUser();
391+
expect.fail("Expected function to throw an error");
392+
} catch (error) {
393+
expect(error.message).to.equal("Database query failed");
394+
}
395+
});
396+
});
355397
});

test/unit/models/users.test.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const photoVerificationModel = firestore.collection("photo-verification");
2121
const userData = require("../../fixtures/user/user");
2222
const addUser = require("../../utils/addUser");
2323
const { userState } = require("../../../constants/userStatus");
24+
const { usersData: abandonedUsersData } = require("../../fixtures/abandoned-tasks/departed-users");
2425
/**
2526
* Test the model functions and validate the data stored
2627
*/
@@ -527,4 +528,48 @@ describe("users", function () {
527528
expect(userDoc.user.roles.super_user).to.be.equal(false);
528529
});
529530
});
531+
532+
describe("fetchPaginatedUsers - Departed Users", function () {
533+
beforeEach(async function () {
534+
await cleanDb();
535+
536+
const userPromises = abandonedUsersData.map((user) => userModel.add(user));
537+
await Promise.all(userPromises);
538+
});
539+
540+
afterEach(async function () {
541+
await cleanDb();
542+
sinon.restore();
543+
});
544+
545+
it("should fetch users not in discord server", async function () {
546+
const result = await users.fetchPaginatedUsers({ departed: "true" });
547+
expect(result.allUsers.length).to.be.equal(2);
548+
});
549+
550+
it("should return no users if departed flag is false", async function () {
551+
const result = await users.fetchPaginatedUsers({ departed: "false" });
552+
expect(result.allUsers.length).to.be.equal(0);
553+
});
554+
555+
it("should return an empty array if there are no departed users in the database", async function () {
556+
await cleanDb();
557+
const activeUser = abandonedUsersData[2];
558+
await userModel.add(activeUser);
559+
560+
const result = await users.fetchPaginatedUsers({ departed: "true" });
561+
expect(result.allUsers.length).to.be.equal(0);
562+
});
563+
564+
it("should handle errors gracefully if the database query fails", async function () {
565+
sinon.stub(users, "fetchPaginatedUsers").throws(new Error("Database query failed"));
566+
567+
try {
568+
await users.fetchPaginatedUsers();
569+
expect.fail("Expected function to throw an error");
570+
} catch (error) {
571+
expect(error.message).to.equal("Database query failed");
572+
}
573+
});
574+
});
530575
});

0 commit comments

Comments
 (0)