Skip to content

Commit e48fac6

Browse files
committed
test: 新增 eventRouter 和 router 的單元測試
1 parent fbebceb commit e48fac6

2 files changed

Lines changed: 124 additions & 0 deletions

File tree

test/eventRouter.test.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { beforeEach, describe, expect, it, vi } from "vitest";
2+
3+
const mocks = vi.hoisted(() => ({
4+
sendMessage: vi.fn(),
5+
markAsRead: vi.fn().mockResolvedValue(undefined),
6+
loadStart: vi.fn().mockResolvedValue(undefined),
7+
}));
8+
9+
vi.mock("../src/utils/eventRoutes", () => ({
10+
sendMessage: mocks.sendMessage,
11+
markAsRead: mocks.markAsRead,
12+
loadStart: mocks.loadStart,
13+
}));
14+
15+
import { eventRouter } from "../src/eventRouter";
16+
17+
describe("eventRouter", () => {
18+
beforeEach(() => {
19+
vi.clearAllMocks();
20+
});
21+
22+
it("handles 'Hi' message", async () => {
23+
const event = {
24+
type: "message",
25+
source: { userId: "U123" },
26+
message: { type: "text", text: "Hi", markAsReadToken: "mark-token" },
27+
replyToken: "reply-token",
28+
};
29+
const ctx = { waitUntil: vi.fn() } as any;
30+
31+
await eventRouter(event, "accessToken", ctx);
32+
33+
expect(ctx.waitUntil).toHaveBeenCalledTimes(1);
34+
expect(mocks.markAsRead).toHaveBeenCalledWith("accessToken", "mark-token");
35+
expect(mocks.loadStart).toHaveBeenCalledWith("accessToken", "U123", 5);
36+
expect(mocks.sendMessage).toHaveBeenCalledWith("accessToken", "reply-token", [
37+
{ type: "text", text: "Hi" },
38+
]);
39+
});
40+
41+
it("handles 'hi' message", async () => {
42+
const event = {
43+
type: "message",
44+
source: { userId: "U123" },
45+
message: { type: "text", text: "hi", markAsReadToken: "mark-token" },
46+
replyToken: "reply-token",
47+
};
48+
const ctx = { waitUntil: vi.fn() } as any;
49+
50+
await eventRouter(event, "accessToken", ctx);
51+
52+
expect(mocks.sendMessage).toHaveBeenCalledWith("accessToken", "reply-token", [
53+
{ type: "text", text: "Hi" },
54+
]);
55+
});
56+
57+
it("handles default text message", async () => {
58+
const event = {
59+
type: "message",
60+
source: { userId: "U123" },
61+
message: { type: "text", text: "unknown", markAsReadToken: "mark-token" },
62+
replyToken: "reply-token",
63+
};
64+
const ctx = { waitUntil: vi.fn() } as any;
65+
66+
await eventRouter(event, "accessToken", ctx);
67+
68+
expect(mocks.sendMessage).toHaveBeenCalledWith("accessToken", "reply-token", [
69+
{ type: "text", text: "Hello from Cloudflare Workers!" },
70+
]);
71+
});
72+
});

test/router.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { beforeEach, describe, expect, it, vi } from "vitest";
2+
import { router } from "../src/router";
3+
4+
const mockEnv = {
5+
LINE_CHANNEL_SECRET: { get: vi.fn() },
6+
LINE_CHANNEL_ACCESS_TOKEN: { get: vi.fn() },
7+
};
8+
9+
describe("router", () => {
10+
beforeEach(() => {
11+
vi.clearAllMocks();
12+
mockEnv.LINE_CHANNEL_SECRET.get.mockResolvedValue("secret");
13+
mockEnv.LINE_CHANNEL_ACCESS_TOKEN.get.mockResolvedValue("accessToken");
14+
});
15+
16+
it("returns 405 for non-POST methods", async () => {
17+
const request = new Request("https://example.com", { method: "GET" });
18+
const response = await router(request, mockEnv as any, {} as any);
19+
20+
expect(response.status).toBe(405);
21+
expect(await response.text()).toBe("Method Not Allowed");
22+
});
23+
24+
it("returns 400 if signature is missing", async () => {
25+
const request = new Request("https://example.com", { method: "POST" });
26+
const response = await router(request, mockEnv as any, {} as any);
27+
28+
expect(response.status).toBe(400);
29+
expect(await response.text()).toBe("Missing signature");
30+
});
31+
32+
it("returns 401 if signature is invalid", async () => {
33+
const request = new Request("https://example.com", {
34+
method: "POST",
35+
headers: { "x-line-signature": "invalid" },
36+
body: JSON.stringify({}),
37+
});
38+
const response = await router(request, mockEnv as any, {} as any);
39+
40+
expect(response.status).toBe(401);
41+
expect(await response.text()).toBe("Invalid signature");
42+
});
43+
44+
it("returns 500 if server is misconfigured", async () => {
45+
mockEnv.LINE_CHANNEL_SECRET.get.mockResolvedValue(null);
46+
const request = new Request("https://example.com", { method: "POST" });
47+
const response = await router(request, mockEnv as any, {} as any);
48+
49+
expect(response.status).toBe(500);
50+
expect(await response.text()).toBe("Server misconfigured");
51+
});
52+
});

0 commit comments

Comments
 (0)