145 lines
4.7 KiB
TypeScript
145 lines
4.7 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import {
|
|
adminExists,
|
|
decideCardFailure,
|
|
decideRubgramWebhook,
|
|
getScheduleDelay,
|
|
isDatabaseSeeded,
|
|
parseSubscriberMessage,
|
|
shouldRunDatabaseSeed,
|
|
} from "./logic";
|
|
|
|
describe("getScheduleDelay", () => {
|
|
const now = new Date("2026-01-01T00:00:00.000Z").getTime();
|
|
|
|
test("converts numeric seconds to milliseconds", () => {
|
|
expect(getScheduleDelay(0, now)).toBe(0);
|
|
expect(getScheduleDelay(60, now)).toBe(60_000);
|
|
expect(getScheduleDelay(0.5, now)).toBe(500);
|
|
});
|
|
|
|
test("polls in one minute when there are no target dates", () => {
|
|
expect(getScheduleDelay([], now)).toBe(60_000);
|
|
});
|
|
|
|
test("uses the nearest date regardless of input order", () => {
|
|
expect(
|
|
getScheduleDelay(
|
|
[
|
|
new Date(now + 30_000),
|
|
new Date(now + 10_000),
|
|
new Date(now + 20_000),
|
|
],
|
|
now,
|
|
),
|
|
).toBe(10_000);
|
|
});
|
|
|
|
test("retains immediate past deadlines and hourly polling for distant dates", () => {
|
|
expect(getScheduleDelay([new Date(now - 1)], now)).toBe(-1);
|
|
expect(getScheduleDelay([new Date(now + 7_200_000)], now)).toBe(3_600_000);
|
|
});
|
|
});
|
|
|
|
describe("database seed decisions", () => {
|
|
test("runs only in development", () => {
|
|
expect(shouldRunDatabaseSeed("development")).toBeTrue();
|
|
expect(shouldRunDatabaseSeed("production")).toBeFalse();
|
|
expect(shouldRunDatabaseSeed(undefined)).toBeFalse();
|
|
});
|
|
|
|
test("distinguishes empty query results from existing rows", () => {
|
|
expect(isDatabaseSeeded([])).toBeFalse();
|
|
expect(isDatabaseSeeded([{ id: true }])).toBeTrue();
|
|
expect(adminExists([])).toBeFalse();
|
|
expect(adminExists([{ id: "admin" }])).toBeTrue();
|
|
});
|
|
});
|
|
|
|
describe("decideCardFailure", () => {
|
|
test.each([
|
|
[
|
|
"The showcase for this UID is private",
|
|
"ผู้เล่นนี้ไม่มีโชว์เคส มองไม่เห็นตัวละครใดๆ",
|
|
true,
|
|
],
|
|
[
|
|
"Character not found in showcase",
|
|
"ตัวละครที่ผู้เล่นเลือก ไม่ได้อยู่ในโชว์เคส",
|
|
false,
|
|
],
|
|
["Invalid UID Provided", "ผู้เล่นนี้ไม่มีอยู่จริง โดนแบนไปแล้วรีเปล่า", false],
|
|
])("translates known card error %s", (input, error, stopRetrying) => {
|
|
expect(decideCardFailure(input, 500)).toEqual({ error, stopRetrying });
|
|
});
|
|
|
|
test("stops retrying all HTTP 400 responses", () => {
|
|
expect(decideCardFailure("bad request", 400)).toEqual({
|
|
error: "bad request",
|
|
stopRetrying: true,
|
|
});
|
|
});
|
|
|
|
test("uses a retry message for gateway failures and oversized bodies", () => {
|
|
const expected = {
|
|
error: "ไม่สามารถสร้างการ์ดได้ กำลังพยายามลองใหม่",
|
|
stopRetrying: false,
|
|
};
|
|
expect(decideCardFailure("upstream", 502)).toEqual(expected);
|
|
expect(decideCardFailure("x".repeat(2001), 500)).toEqual(expected);
|
|
expect(decideCardFailure("x".repeat(2000), 500).error).toHaveLength(2000);
|
|
});
|
|
|
|
test("stores only the first line of an unknown response", () => {
|
|
expect(decideCardFailure("first line\nstack trace", 500)).toEqual({
|
|
error: "first line",
|
|
stopRetrying: false,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Redis subscriber decisions", () => {
|
|
test("parses a valid subscriber envelope", () => {
|
|
expect(
|
|
parseSubscriberMessage(
|
|
JSON.stringify({
|
|
event: "update",
|
|
data: { type: "submit", sub: "s1" },
|
|
}),
|
|
),
|
|
).toEqual({ event: "update", data: { type: "submit", sub: "s1" } });
|
|
});
|
|
|
|
test.each([
|
|
"not json",
|
|
"null",
|
|
"[]",
|
|
JSON.stringify({ event: "update" }),
|
|
JSON.stringify({ event: 1, data: {} }),
|
|
])("rejects malformed payload %s", (payload) => {
|
|
expect(parseSubscriberMessage(payload)).toBeNull();
|
|
});
|
|
|
|
test.each([
|
|
"submit",
|
|
"paid",
|
|
] as const)("allows configured %s updates", (type) => {
|
|
expect(
|
|
decideRubgramWebhook(
|
|
{ event: "update", data: { type, sub: "submission-1" } },
|
|
"https://webhook.test",
|
|
),
|
|
).toEqual({ type, sub: "submission-1" });
|
|
});
|
|
|
|
test.each([
|
|
[{ event: "other", data: { type: "submit", sub: "s1" } }, "url"],
|
|
[{ event: "update", data: { type: "cancel", sub: "s1" } }, "url"],
|
|
[{ event: "update", data: { type: "submit" } }, "url"],
|
|
[{ event: "update", data: null }, "url"],
|
|
[{ event: "update", data: { type: "submit", sub: "s1" } }, undefined],
|
|
] as const)("ignores ineligible message %#", (message, webhookUrl) => {
|
|
expect(decideRubgramWebhook(message, webhookUrl)).toBeNull();
|
|
});
|
|
});
|