Skip to content

Commit

Permalink
🧪 add test for app
Browse files Browse the repository at this point in the history
  • Loading branch information
kawamataryo committed Mar 4, 2024
1 parent f8a869c commit 2ec4530
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 52 deletions.
82 changes: 82 additions & 0 deletions src/app.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {
InteractionResponseType,
InteractionType,
} from "discord-api-types/v10";
import { testClient } from "hono/testing";
import { beforeEach, describe, expect, it, vi } from "vitest";
import app, { interactionRoot } from "./app";
import { handleApplicationCommands } from "./interactions/handleApplicationCommands";
import { handleModalSubmits } from "./interactions/handleModalSubmit";
import { verifyDiscordInteraction } from "./middleware/verifyDiscordInteraction";

vi.mock("./middleware/verifyDiscordInteraction", () => {
return {
verifyDiscordInteraction: vi.fn(async (c, next) => await next()),
};
});
vi.mock("./interactions/handleApplicationCommands", () => ({
handleApplicationCommands: vi.fn(async () => ({ res: "ok" })),
}));
vi.mock("./interactions/handleModalSubmit", () => ({
handleModalSubmits: vi.fn(async () => ({ res: "ok" })),
}));

const mockEnv = {
DB: {},
DISCORD_TOKEN: "test-token",
MOKUMOKU_CHANNEL_ID: "test-channel-id",
};

describe("intensions", () => {
beforeEach(() => {
vi.clearAllMocks();
});

it.each([
{
type: InteractionType.ApplicationCommand,
handler: handleApplicationCommands,
},
{
type: InteractionType.ModalSubmit,
handler: handleModalSubmits,
},
])(
"should call correct handler based on interaction type",
async ({ type, handler }) => {
const res = await testClient<typeof interactionRoot>(
app,
mockEnv,
).interaction.$post({
json: {
type,
data: {},
},
});

expect(verifyDiscordInteraction).toHaveBeenCalled();
expect(handler).toHaveBeenCalled();
expect(await res.json()).toEqual({ res: "ok" });
},
);

it("should return error response if un handle interaction type is received", async () => {
const res = await testClient<typeof interactionRoot>(
app,
mockEnv,
).interaction.$post({
json: {
type: "UNHANDLED_TYPE",
data: {},
},
});

expect(await res.json()).toEqual({
type: InteractionResponseType.ChannelMessageWithSource,
data: {
content: "🚨 エラーが発生しました",
embeds: expect.any(Array),
},
});
});
});
93 changes: 48 additions & 45 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,54 +18,57 @@ import { Bindings, Clients, Repositories } from "./types";

const app = new Hono<{ Bindings: Bindings }>();

app.post("/interaction", verifyDiscordInteraction, async (c) => {
const body = await c.req.json();
export const interactionRoot = app.post(
"/interaction",
verifyDiscordInteraction,
async (c) => {
const body = await c.req.json();

const repositories: Repositories = {
usersRepository: new UsersRepository(c.env.DB),
checkinsRepository: new CheckinsRepository(c.env.DB),
eventsRepository: new EventsRepository(c.env.DB),
eventsToCheckinsRepository: new EventsToCheckinsRepository(c.env.DB),
};
const repositories: Repositories = {
usersRepository: new UsersRepository(c.env.DB),
checkinsRepository: new CheckinsRepository(c.env.DB),
eventsRepository: new EventsRepository(c.env.DB),
eventsToCheckinsRepository: new EventsToCheckinsRepository(c.env.DB),
};

const clients: Clients = {
discordClient: new DiscordClient(c.env.DISCORD_TOKEN),
connpassClient: new ConnpassClient(),
};
const clients: Clients = {
discordClient: new DiscordClient(c.env.DISCORD_TOKEN),
connpassClient: new ConnpassClient(),
};

try {
switch (body.type) {
case InteractionType.APPLICATION_COMMAND:
return c.json(
await handleApplicationCommands({
repositories,
clients,
intentObj: body,
commands: [
checkinCommand,
mokumokuStartCommand,
generateEventDescription,
],
}),
);
case InteractionType.MODAL_SUBMIT:
return c.json(
await handleModalSubmits({
repositories,
clients,
modalSubmitObj: body,
modals: [checkinModal],
}),
);
default:
throw new Error("Invalid interaction");
try {
switch (body.type) {
case InteractionType.APPLICATION_COMMAND:
return c.json(
await handleApplicationCommands({
repositories,
clients,
intentObj: body,
commands: [
checkinCommand,
mokumokuStartCommand,
generateEventDescription,
],
}),
);
case InteractionType.MODAL_SUBMIT:
return c.json(
await handleModalSubmits({
repositories,
clients,
modalSubmitObj: body,
modals: [checkinModal],
}),
);
default:
throw new Error("Invalid interaction");
}
} catch (e) {
return c.json(
errorResponse(e instanceof Error ? e.message : "Unknown error"),
);
}
} catch (e) {
console.error(e);
return c.json(
errorResponse(e instanceof Error ? e.message : "Unknown error"),
);
}
});
},
);

export default app;
6 changes: 1 addition & 5 deletions src/interactions/applicationCommands/checkin.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { describe, expect, it, vi } from "vitest";
import { buildCheckinModalResponse } from "../../responses/checkinCommandResponse";
import { Repositories } from "../../types";
import { ApplicationCommandObj } from "../handleApplicationCommands";
import checkinCommand from "./checkin";

describe("handler function", () => {
beforeEach(() => {
vi.resetAllMocks();
});

it("should throw an error when member is not present", async () => {
const intentObj = {} as ApplicationCommandObj;
const repositories = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import generateEventDescriptionCommand from "./generateEventDescription";

describe("handler", () => {
beforeEach(() => {
vi.resetAllMocks();
vi.clearAllMocks();
});

it("should throw an error if no previous event is found", async () => {
Expand Down
2 changes: 1 addition & 1 deletion src/interactions/applicationCommands/mokumokuStart.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ vi.mock("dayjs", () => ({

describe("handler", () => {
beforeEach(() => {
vi.resetAllMocks();
vi.clearAllMocks();
});

it("should create new Event if today's event is not found", async () => {
Expand Down
4 changes: 4 additions & 0 deletions src/interactions/modalSubmits/checkinModal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import { ModalSubmitObj } from "../handleModalSubmit";
import checkinModal from "./checkinModal";

describe("handler", () => {
beforeEach(() => {
vi.clearAllMocks();
});

it("should throw an error if modalSubmitObj.member or modalSubmitObj.data is not present", async () => {
const repositories = {
usersRepository: {},
Expand Down

0 comments on commit 2ec4530

Please sign in to comment.