43 lines
1.4 KiB
TypeScript
43 lines
1.4 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
|
|
import { decodeJwtExpiry, isJwtExpired } from "../../src/auth/jwt.js";
|
|
|
|
const FIXED_NOW = Date.UTC(2026, 1, 16, 12, 0, 0);
|
|
|
|
function createJwt(expSeconds: number): string {
|
|
const header = Buffer.from(JSON.stringify({ alg: "HS256", typ: "JWT" })).toString("base64url");
|
|
const payload = Buffer.from(JSON.stringify({ exp: expSeconds })).toString("base64url");
|
|
return `${header}.${payload}.signature`;
|
|
}
|
|
|
|
describe("jwt helpers", () => {
|
|
const originalNow = Date.now;
|
|
|
|
beforeEach(() => {
|
|
Date.now = () => FIXED_NOW;
|
|
});
|
|
|
|
afterEach(() => {
|
|
Date.now = originalNow;
|
|
});
|
|
|
|
test("decodeJwtExpiry returns expiry in ms with 5 minute safety margin", () => {
|
|
const expSeconds = Math.floor((FIXED_NOW + 2 * 60 * 60 * 1000) / 1000);
|
|
const token = createJwt(expSeconds);
|
|
|
|
expect(decodeJwtExpiry(token)).toBe(expSeconds * 1000 - 5 * 60 * 1000);
|
|
});
|
|
|
|
test("decodeJwtExpiry falls back to now + 1h when token is malformed", () => {
|
|
expect(decodeJwtExpiry("not-a-jwt")).toBe(FIXED_NOW + 60 * 60 * 1000);
|
|
});
|
|
|
|
test("isJwtExpired honors additional caller-provided buffer", () => {
|
|
const expSeconds = Math.floor((FIXED_NOW + 20 * 60 * 1000) / 1000);
|
|
const token = createJwt(expSeconds);
|
|
|
|
expect(isJwtExpired(token)).toBe(false);
|
|
expect(isJwtExpired(token, 16 * 60 * 1000)).toBe(true);
|
|
});
|
|
});
|