refactor(core): dedupe gateway runtime and config tests

This commit is contained in:
Peter Steinberger
2026-02-22 07:37:11 +00:00
parent ad1c07e7c0
commit b109fa53ea
20 changed files with 699 additions and 561 deletions

View File

@@ -26,6 +26,14 @@ const createLocationMessage = (location: {
});
describe("deliverLineAutoReply", () => {
const baseDeliveryParams = {
to: "line:user:1",
replyToken: "token",
replyTokenUsed: false,
accountId: "acc",
textLimit: 5000,
};
function createDeps(overrides?: Partial<LineAutoReplyDeps>) {
const replyMessageLine = vi.fn(async () => ({}));
const pushMessageLine = vi.fn(async () => ({}));
@@ -72,13 +80,9 @@ describe("deliverLineAutoReply", () => {
const { deps, replyMessageLine, pushMessagesLine, createQuickReplyItems } = createDeps();
const result = await deliverLineAutoReply({
...baseDeliveryParams,
payload: { text: "hello", channelData: { line: lineData } },
lineData,
to: "line:user:1",
replyToken: "token",
replyTokenUsed: false,
accountId: "acc",
textLimit: 5000,
deps,
});
@@ -108,13 +112,9 @@ describe("deliverLineAutoReply", () => {
});
const result = await deliverLineAutoReply({
...baseDeliveryParams,
payload: { channelData: { line: lineData } },
lineData,
to: "line:user:1",
replyToken: "token",
replyTokenUsed: false,
accountId: "acc",
textLimit: 5000,
deps,
});
@@ -151,13 +151,9 @@ describe("deliverLineAutoReply", () => {
});
await deliverLineAutoReply({
...baseDeliveryParams,
payload: { text: "hello", channelData: { line: lineData } },
lineData,
to: "line:user:1",
replyToken: "token",
replyTokenUsed: false,
accountId: "acc",
textLimit: 5000,
deps,
});
@@ -181,4 +177,33 @@ describe("deliverLineAutoReply", () => {
const replyOrder = replyMessageLine.mock.invocationCallOrder[0];
expect(pushOrder).toBeLessThan(replyOrder);
});
it("falls back to push when reply token delivery fails", async () => {
const lineData = {
flexMessage: { altText: "Card", contents: { type: "bubble" } },
};
const failingReplyMessageLine = vi.fn(async () => {
throw new Error("reply failed");
});
const { deps, pushMessagesLine } = createDeps({
processLineMessage: () => ({ text: "", flexMessages: [] }),
chunkMarkdownText: () => [],
replyMessageLine: failingReplyMessageLine as LineAutoReplyDeps["replyMessageLine"],
});
const result = await deliverLineAutoReply({
...baseDeliveryParams,
payload: { channelData: { line: lineData } },
lineData,
deps,
});
expect(result.replyTokenUsed).toBe(true);
expect(failingReplyMessageLine).toHaveBeenCalledTimes(1);
expect(pushMessagesLine).toHaveBeenCalledWith(
"line:user:1",
[createFlexMessage("Card", { type: "bubble" })],
{ accountId: "acc" },
);
});
});

View File

@@ -37,6 +37,20 @@ function createPostWebhookTestHarness(rawBody: string, secret = "secret") {
return { bot, handler, secret };
}
const runSignedPost = async (params: {
handler: (req: IncomingMessage, res: ServerResponse) => Promise<void>;
rawBody: string;
secret: string;
res: ServerResponse;
}) =>
await params.handler(
{
method: "POST",
headers: { "x-line-signature": sign(params.rawBody, params.secret) },
} as unknown as IncomingMessage,
params.res,
);
describe("createLineNodeWebhookHandler", () => {
it("returns 200 for GET", async () => {
const bot = { handleWebhook: vi.fn(async () => {}) };
@@ -68,6 +82,17 @@ describe("createLineNodeWebhookHandler", () => {
expect(bot.handleWebhook).not.toHaveBeenCalled();
});
it("returns 405 for non-GET/non-POST methods", async () => {
const { bot, handler } = createPostWebhookTestHarness(JSON.stringify({ events: [] }));
const { res, headers } = createRes();
await handler({ method: "PUT", headers: {} } as unknown as IncomingMessage, res);
expect(res.statusCode).toBe(405);
expect(headers.allow).toBe("GET, POST");
expect(bot.handleWebhook).not.toHaveBeenCalled();
});
it("rejects missing signature when events are non-empty", async () => {
const rawBody = JSON.stringify({ events: [{ type: "message" }] });
const { bot, handler } = createPostWebhookTestHarness(rawBody);
@@ -98,13 +123,7 @@ describe("createLineNodeWebhookHandler", () => {
const { bot, handler, secret } = createPostWebhookTestHarness(rawBody);
const { res } = createRes();
await handler(
{
method: "POST",
headers: { "x-line-signature": sign(rawBody, secret) },
} as unknown as IncomingMessage,
res,
);
await runSignedPost({ handler, rawBody, secret, res });
expect(res.statusCode).toBe(200);
expect(bot.handleWebhook).toHaveBeenCalledWith(
@@ -117,13 +136,7 @@ describe("createLineNodeWebhookHandler", () => {
const { bot, handler, secret } = createPostWebhookTestHarness(rawBody);
const { res } = createRes();
await handler(
{
method: "POST",
headers: { "x-line-signature": sign(rawBody, secret) },
} as unknown as IncomingMessage,
res,
);
await runSignedPost({ handler, rawBody, secret, res });
expect(res.statusCode).toBe(400);
expect(bot.handleWebhook).not.toHaveBeenCalled();