/**
* 指示書I 段階1 の `verifyToken()` 期待値表をそのまま固定したテスト。
*/
import { describe, expect, it } from "vitest";
import { verifyToken } from "@/lib/auth/token";
describe("verifyToken() — 定数時間比較", () => {
const cases: Array<{
input: string;
expected: string | undefined;
result: boolean;
note: string;
}> = [
{ input: "abc", expected: "abc", result: true, note: "一致" },
{ input: "abc", expected: "abd", result: false, note: "不一致" },
{
input: "abc",
expected: "abcd",
result: false,
note: "★長さ違いで例外を投げないこと(timingSafeEqual は長さが違うと throw する)★",
},
{ input: "", expected: "abc", result: false, note: "空入力" },
{
input: "abc",
expected: "",
result: false,
note: "★AUTH_TOKEN が未設定なら誰も通さない(空を『何でも通す』にしない)★",
},
{
input: "abc",
expected: undefined,
result: false,
note: "★同上(未設定)★",
},
];
for (const c of cases) {
it(`input=${JSON.stringify(c.input)} / expected=${JSON.stringify(
c.expected
)} → ${c.result}(${c.note})`, () => {
expect(verifyToken(c.input, c.expected)).toBe(c.result);
});
}
it("★長さ違いでも例外を投げない★(明示。ここが壊れると 500 になる)", () => {
expect(() => verifyToken("a", "aaaaaaaaaaaaaaaaaaaa")).not.toThrow();
expect(() => verifyToken("aaaaaaaaaaaaaaaaaaaa", "a")).not.toThrow();
expect(verifyToken("a", "aaaaaaaaaaaaaaaaaaaa")).toBe(false);
});
it("input が null / undefined でも false", () => {
expect(verifyToken(null, "abc")).toBe(false);
expect(verifyToken(undefined, "abc")).toBe(false);
});
it("両方 undefined でも false(★全公開にならないこと★)", () => {
expect(verifyToken(undefined, undefined)).toBe(false);
});
it("マルチバイト文字を含むトークンでも一致・不一致が正しい", () => {
expect(verifyToken("トークンあ", "トークンあ")).toBe(true);
expect(verifyToken("トークンあ", "トークンい")).toBe(false);
});
it("長いトークンの一致", () => {
const token = "x".repeat(64);
expect(verifyToken(token, token)).toBe(true);
expect(verifyToken(token, "x".repeat(63) + "y")).toBe(false);
});
});