Skip to content

Commit

Permalink
wrote tests for weekly service (#9)
Browse files Browse the repository at this point in the history
chore: write tests for weekly service
  • Loading branch information
moromis authored Apr 3, 2024
1 parent b9a4124 commit 2764e3f
Show file tree
Hide file tree
Showing 18 changed files with 324 additions and 95 deletions.
2 changes: 1 addition & 1 deletion cov-badge.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 15 additions & 10 deletions src/modules/commands/assign.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const services = require("../../services");
const strings = require("../../constants/strings");
const { TABLES } = require("../../constants/tables");
const { CHORE_STATES } = require("../../constants/chores");
const { testUsers, testChores, getTestBody } = require("../../test/structs");
const { testChores, getTestBody, getTestUsers } = require("../../test/structs");

jest.mock("../handler", () => jest.fn(() => {}));
jest.mock("../../services");
Expand All @@ -23,7 +23,7 @@ jest.mock("../../helpers/getChoreMessage");

describe("assign", () => {
beforeAll(() => {
services.updateUsers.mockReturnValue(testUsers);
services.updateUsers.mockReturnValue(getTestUsers());
});
beforeEach(() => {
jest.clearAllMocks();
Expand All @@ -45,28 +45,32 @@ describe("assign", () => {
});
test("if the user already has a chore, the discord.js client should be\
destroyed and a message should be returned indicating the user already has a chore", async () => {
services.getTodoChores.mockReturnValue(testChores.todoChores);
services.getIncompleteChores.mockReturnValue(testChores.incompleteChores);
const todoChores = testChores.getTestTodoChores();
const incompleteChores = testChores.getTestIncompleteChores();
services.getTodoChores.mockReturnValue(todoChores);
services.getIncompleteChores.mockReturnValue(incompleteChores);
const res = await _action(getTestBody("1"));
expect(Client).toHaveBeenCalled();
expect(Client.mock.results[0].value.destroy).toHaveBeenCalled();
expect(res.content).toBe(strings.USER_HAS_CHORE);
});
test("if there aren't any available reviewers, a message should return that fact", async () => {
const incompleteChoresNoReviewersAvailable =
testChores.getTestIncompleteChoresNoReviewersAvailable();
services.getTodoChores.mockReturnValue([]);
services.getIncompleteChores.mockReturnValue(
testChores.incompleteChoresNoReviewersAvailable,
incompleteChoresNoReviewersAvailable,
);
const res = await _action(getTestBody("2"));
expect(Client).toHaveBeenCalled();
expect(Client.mock.results[0].value.destroy).toHaveBeenCalled();
expect(res.content).toBe(strings.NO_REVIEWERS);
});
test("if the user doesn't have a chore, one should be assigned to them", async () => {
services.getTodoChores.mockReturnValue(testChores.todoChores);
services.getIncompleteChores.mockReturnValueOnce(
testChores.incompleteChores,
);
const todoChores = testChores.getTestTodoChores();
const incompleteChores = testChores.getTestIncompleteChores();
services.getTodoChores.mockReturnValue(todoChores);
services.getIncompleteChores.mockReturnValueOnce(incompleteChores);
const res = await _action(getTestBody("2"));
expect(Client).toHaveBeenCalled();
expect(Client.mock.results[0].value.destroy).toHaveBeenCalled();
Expand All @@ -81,8 +85,9 @@ describe("assign", () => {
expect(services.db.put.mock.calls[1][1]).toHaveProperty("currentChore");
});
test("if something goes wrong getting a new chore, the user should be notified, and nothing should be written to the db", async () => {
const incompleteChores = testChores.getTestIncompleteChores();
services.getTodoChores.mockReturnValue([]);
services.getIncompleteChores.mockReturnValue(testChores.incompleteChores);
services.getIncompleteChores.mockReturnValue(incompleteChores);
const res = await _action(getTestBody("2"));
expect(Client).toHaveBeenCalled();
expect(Client.mock.results[0].value.destroy).toHaveBeenCalled();
Expand Down
13 changes: 7 additions & 6 deletions src/modules/commands/chore.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ const globalHandler = require("../handler");
const { Client } = require("discord.js");
const services = require("../../services");
const strings = require("../../constants/strings");
const { TABLES } = require("../../constants/tables");
const { CHORE_STATES } = require("../../constants/chores");
const { testUsers, testChores, getTestBody } = require("../../test/structs");
const { testChores, getTestBody, getTestUsers } = require("../../test/structs");
const getCurrentChoreMessage = require("../../helpers/getCurrentChoreMessage");

jest.mock("../handler", () => jest.fn(() => {}));
Expand Down Expand Up @@ -43,22 +41,25 @@ describe("chore", () => {
});
test("if the user's chore can't be found the discord.js client should be\
destroyed and a message should be returned indicating the user might not have a chore", async () => {
// services.getChore.mockReturnValue(testChores.incompleteChores[0]);
const testUsers = getTestUsers();
services.getUser.mockReturnValue(testUsers[0]);
const res = await _action(getTestBody(testUsers[0].id));
expect(Client).toHaveBeenCalled();
expect(Client.mock.results[0].value.destroy).toHaveBeenCalled();
expect(res.content).toBe(strings.MAYBE_NO_CHORE);
});
test("if the user does have a chore, the user should be DMed with their chore details, and the original message should be deleted", async () => {
services.getChore.mockReturnValue(testChores.incompleteChores[0]);
const testUsers = getTestUsers();
const incompleteChores = testChores.getTestIncompleteChores();
services.getChore.mockReturnValue(incompleteChores[0]);
services.getUser.mockReturnValue(testUsers[0]);
const res = await _action(getTestBody(testUsers[0].id));
expect(Client).toHaveBeenCalled();
expect(Client.mock.results[0].value.destroy).toHaveBeenCalled();
expect(services.dmUser.mock.calls).toHaveLength(1);
const incompleteChoresResult = testChores.getTestIncompleteChores();
expect(services.dmUser.mock.calls[0][2]).toBe(
getCurrentChoreMessage(testChores.incompleteChores[0]),
getCurrentChoreMessage(incompleteChoresResult[0]),
);
expect(res.content).toBe(undefined);
expect(res.delete).toBe(true);
Expand Down
13 changes: 9 additions & 4 deletions src/modules/commands/complete.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { data, handler, _action } = require("./complete");
const globalHandler = require("../handler");
const { Client } = require("discord.js");
const { getTestBody, testChores, testUsers } = require("../../test/structs");
const { getTestBody, testChores, getTestUsers } = require("../../test/structs");
const strings = require("../../constants/strings");
const getChoreCompleteMessage = require("../../helpers/getChoreCompleteMessage");
const { CHORE_STATES } = require("../../constants/chores");
Expand Down Expand Up @@ -49,7 +49,8 @@ describe("complete", () => {
expect(res.content).toBe(strings.NO_ASSIGNED_CHORE);
});
test("if the user has a chore it should be marked as completed, and have no reviewer or user", async () => {
services.getChore.mockReturnValue(testChores.incompleteChores[0]);
const incompleteChores = testChores.getTestIncompleteChores();
services.getChore.mockReturnValue(incompleteChores[0]);
const res = await _action(getTestBody("1"));
expect(Client).toHaveBeenCalled();
expect(Client.mock.results[0].value.destroy).toHaveBeenCalled();
Expand All @@ -61,7 +62,9 @@ describe("complete", () => {
});
test("if the user has a chore the user should be put in the DB\
without a currentChore prop and with scores adjusted correctly", async () => {
services.getChore.mockReturnValue(testChores.incompleteChores[0]);
const testUsers = getTestUsers();
const incompleteChores = testChores.getTestIncompleteChores();
services.getChore.mockReturnValue(incompleteChores[0]);
services.getUser.mockReturnValue({
...testUsers[0],
numCycleChores: 0,
Expand All @@ -78,7 +81,9 @@ describe("complete", () => {
expect(services.db.put.mock.calls[1][1]).not.toHaveProperty("currentChore");
});
test("the user should have properly adjusted scores even if they don't have any beforehand", async () => {
services.getChore.mockReturnValue(testChores.incompleteChores[0]);
const testUsers = getTestUsers();
const incompleteChores = testChores.getTestIncompleteChores();
services.getChore.mockReturnValue(incompleteChores[0]);
services.getUser.mockReturnValue(
_.omit(testUsers[0], ["numCycleChores", "numAllTimeChores"]),
);
Expand Down
29 changes: 18 additions & 11 deletions src/modules/commands/swap.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
const { data, handler, _action } = require("./swap");
const globalHandler = require("../handler");
const { Client } = require("discord.js");
const { getTestBody, testChores, testUsers } = require("../../test/structs");
const { getTestBody, testChores, getTestUsers } = require("../../test/structs");
const strings = require("../../constants/strings");
const getChoreCompleteMessage = require("../../helpers/getChoreCompleteMessage");
const { CHORE_STATES } = require("../../constants/chores");
const services = require("../../services");
const { TABLES } = require("../../constants/tables");
Expand Down Expand Up @@ -35,15 +33,18 @@ describe("swap", () => {
expect(globalHandler).toHaveBeenCalledWith(testEvent, expect.anything());
});
test("if the user doesn't have an assigned chore, the command should let them know", async () => {
const testUsers = getTestUsers();
services.getChore.mockReturnValue(null);
services.getUser.mockReturnValue(testUsers[0]);
const res = await _action(getTestBody("1"));
expect(res.content).toBe(strings.NO_ASSIGNED_CHORE);
});
test("if the user doesn't have a chore the user should be put in the DB\
without a currentChore prop and with scores adjusted correctly", async () => {
removeRandomFromList.mockReturnValue(testChores.incompleteChores[1]);
services.getChore.mockReturnValue(testChores.incompleteChores[0]);
const testUsers = getTestUsers();
const incompleteChores = testChores.getTestIncompleteChores();
removeRandomFromList.mockReturnValue(incompleteChores[1]);
services.getChore.mockReturnValue(incompleteChores[0]);
services.getUser.mockReturnValue({
...testUsers[0],
numCycleChores: 0,
Expand All @@ -55,20 +56,24 @@ describe("swap", () => {
);
expect(services.db.put.mock.calls[0][0]).toBe(TABLES.USERS);
expect(services.db.put.mock.calls[0][1].id).toBe(testUsers[0].id);
const incompleteChoresResult = testChores.getTestIncompleteChores();
expect(services.db.put.mock.calls[0][1].currentChore).toBe(
testChores.incompleteChores[1].id,
incompleteChoresResult[1].id,
);
});
test("both the old chore and the new one should get properly written to the DB", async () => {
removeRandomFromList.mockReturnValue(testChores.incompleteChores[1]);
services.getChore.mockReturnValue(testChores.incompleteChores[0]);
const testUsers = getTestUsers();
const incompleteChores = testChores.getTestIncompleteChores();
removeRandomFromList.mockReturnValue(incompleteChores[1]);
services.getChore.mockReturnValue(incompleteChores[0]);
services.getUser.mockReturnValue(
_.omit(testUsers[0], ["numCycleChores", "numAllTimeChores"]),
);
await _action(getTestBody(testUsers[0].id));
expect(services.db.batchWrite.mock.calls[0][0]).toBe(TABLES.CHORES);
const incompleteChoresResult = testChores.getTestIncompleteChores();
expect(services.db.batchWrite.mock.calls[0][1][0].id).toBe(
testChores.incompleteChores[1].id,
incompleteChoresResult[1].id,
);
expect(services.db.batchWrite.mock.calls[0][1][0].status).toBe(
CHORE_STATES.ASSIGNED,
Expand All @@ -78,7 +83,7 @@ describe("swap", () => {
);
expect(services.db.batchWrite.mock.calls[0][1][0]).toHaveProperty("user");
expect(services.db.batchWrite.mock.calls[0][1][1].id).toBe(
testChores.incompleteChores[0].id,
incompleteChoresResult[0].id,
);
expect(services.db.batchWrite.mock.calls[0][1][1].status).toBe(
CHORE_STATES.TODO,
Expand All @@ -92,8 +97,10 @@ describe("swap", () => {
});
test("if no new chore is given, a message should be returned to\
indicate the command failed, and no DB operations should occur", async () => {
const testUsers = getTestUsers();
const incompleteChores = testChores.getTestIncompleteChores();
removeRandomFromList.mockReturnValue(null);
services.getChore.mockReturnValue(testChores.incompleteChores[0]);
services.getChore.mockReturnValue(incompleteChores[0]);
services.getUser.mockReturnValue(
_.omit(testUsers[0], ["numCycleChores", "numAllTimeChores"]),
);
Expand Down
18 changes: 10 additions & 8 deletions src/modules/jobs/daily/daily.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,30 @@ describe("daily", () => {
expect(Client.mock.results[0].value.destroy).toHaveBeenCalledTimes(1);
});
it("should dm all users to remind them of their chore", async () => {
services.getIncompleteChores.mockReturnValue(testChores.incompleteChores);
const incompleteChores = testChores.getTestIncompleteChores();
services.getIncompleteChores.mockReturnValue(incompleteChores);
await handler();
expect(Client).toHaveBeenCalled();
expect(Client.mock.results[0].value.login).toHaveBeenCalledTimes(1);
expect(Client.mock.results[0].value.destroy).toHaveBeenCalledTimes(1);
const incompleteChoresResult = testChores.getTestIncompleteChores();
expect(services.dmUser.mock.calls.length).toBe(
testChores.incompleteChores.length,
incompleteChoresResult.length,
);
expect(getDMReminderMessage.mock.calls.length).toBe(
testChores.incompleteChores.length,
incompleteChoresResult.length,
);
});
it("should not dm users that have already done their chore", async () => {
services.getIncompleteChores.mockReturnValue(
testChores.incompleteChores.slice(1),
);
const incompleteChores = testChores.getTestIncompleteChores();
services.getIncompleteChores.mockReturnValue(incompleteChores.slice(1));
await handler();
const incompleteChoresResult = testChores.getTestIncompleteChores();
expect(services.dmUser.mock.calls.length).toBe(
testChores.incompleteChores.length - 1,
incompleteChoresResult.length - 1,
);
expect(getDMReminderMessage.mock.calls.length).toBe(
testChores.incompleteChores.length - 1,
incompleteChoresResult.length - 1,
);
});
});
11 changes: 3 additions & 8 deletions src/modules/jobs/monthly/monthly.test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
const { handler } = require("./monthly");
const { Client } = require("discord.js");
const services = require("../../../services");
const {
testChores,
testUsers,
testUsersSortedByScoreDesc,
} = require("../../../test/structs");
const {
getDMReminderMessage,
} = require("../../../helpers/getDMReminderMessage");
const getMonthEndMessage = require("../../../helpers/getMonthEndMessage");
const { getTestUsersSortedByScoreDesc } = require("../../../test/structs");

jest.mock("../../../services");
jest.mock("discord.js", () => ({
Expand All @@ -28,6 +21,7 @@ describe("monthly", () => {
jest.clearAllMocks();
});
it("should message the chores channel if there's users", async () => {
const testUsersSortedByScoreDesc = getTestUsersSortedByScoreDesc();
services.updateUsers.mockReturnValue(testUsersSortedByScoreDesc);
await handler();
expect(Client).toHaveBeenCalled();
Expand All @@ -47,6 +41,7 @@ describe("monthly", () => {
expect(services.messageChoresChannel.mock.calls.length).toBe(0);
});
it("should push updated users to the DB, resetting numCycleChores", async () => {
const testUsersSortedByScoreDesc = getTestUsersSortedByScoreDesc();
services.updateUsers.mockReturnValue(testUsersSortedByScoreDesc);
await handler();
expect(services.db.batchWrite.mock.calls.length).toBe(1);
Expand Down
63 changes: 63 additions & 0 deletions src/modules/jobs/weekly/weekly.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const { handler } = require("./weekly");
const { Client } = require("discord.js");
const services = require("../../../services");
const { testChores, getTestUsers } = require("../../../test/structs");

jest.mock("../../../services");
jest.mock("discord.js", () => ({
Client: jest.fn().mockImplementation(() => ({
login: jest.fn(() => {}),
destroy: jest.fn(() => {}),
})),
GatewayIntentBits: {
Guilds: "guilds",
GuildMembers: "guild-members",
},
}));

describe("weekly", () => {
beforeEach(() => {
jest.clearAllMocks();
jest.resetModules();
});
it("should run", async () => {
const testUsers = getTestUsers();
const incompleteChores = testChores.getTestIncompleteChores();
const todoChores = testChores.getTestTodoChores();
services.getIncompleteChores.mockReturnValue(incompleteChores);
services.updateUsers.mockReturnValue(testUsers);
services.getTodoChores.mockReturnValue(todoChores);
await handler();
expect(Client).toHaveBeenCalled();
expect(Client.mock.results[0].value.login).toHaveBeenCalledTimes(1);
expect(Client.mock.results[0].value.destroy).toHaveBeenCalledTimes(1);
expect(services.messageChoresChannel.mock.calls.length).toBeGreaterThan(0);
});
it("should unassign completed chore if there's no more todo chores", async () => {
const testUsers = getTestUsers();
const incompleteChores = testChores.getTestIncompleteChores();
const todoChores = testChores.getTestTodoChores();
services.getIncompleteChores.mockReturnValue(incompleteChores);
services.updateUsers.mockReturnValue(testUsers.slice(0, todoChores.length));
services.getTodoChores.mockReturnValueOnce([]).mockReturnValue(todoChores);
await handler();
expect(services.unassignCompletedChores).toHaveBeenCalled();
expect(services.getTodoChores).toHaveBeenCalledTimes(2);
});
it("should give a user with `extraPointage` defined more points", async () => {
const testUsers = getTestUsers();
const incompleteChores = testChores.getTestIncompleteChores();
const todoChores = testChores.getTestTodoChores();
const extraPointage = 1;
services.getIncompleteChores.mockReturnValue(incompleteChores);
services.updateUsers.mockReturnValue([
{ ...testUsers[0], extraPointage },
testUsers[1],
]);
services.getTodoChores.mockReturnValue(todoChores);
await handler();
expect(services.db.batchWrite.mock.calls[1][1][0].numCycleChores).toBe(
testUsers[0].numCycleChores + extraPointage,
);
});
});
Loading

0 comments on commit 2764e3f

Please sign in to comment.