import assert from "node:assert/strict"; import { mkdtemp, writeFile } from "node:fs/promises"; import { join } from "node:path"; import { tmpdir } from "node:os"; import { test } from "node:test"; import { loadToken, saveToken, tokenFileMode, tokenNeedsRefresh } from "../src/token-store.js"; test("saves and loads token without changing values", async () => { const root = await mkdtemp(join(tmpdir(), "spotify-token-")); const tokenPath = join(root, "token.json"); const token = { accessToken: "access-secret", refreshToken: "refresh-secret", expiresAt: 123456 }; await saveToken(token, { tokenPath }); assert.deepEqual(await loadToken({ tokenPath }), token); }); test("writes token file with owner-only mode when supported", async () => { const root = await mkdtemp(join(tmpdir(), "spotify-token-")); const tokenPath = join(root, "token.json"); await saveToken({ accessToken: "a", refreshToken: "r", expiresAt: 123 }, { tokenPath }); const mode = await tokenFileMode({ tokenPath }); assert.equal(mode, 0o600); }); test("rejects invalid token shape", async () => { const root = await mkdtemp(join(tmpdir(), "spotify-token-")); const tokenPath = join(root, "token.json"); await saveToken({ accessToken: "a", refreshToken: "r", expiresAt: 123 }, { tokenPath }); await writeFile(tokenPath, JSON.stringify({ accessToken: "a" })); await assert.rejects(() => loadToken({ tokenPath }), /invalid token shape/); }); test("identifies tokens needing refresh with skew", () => { assert.equal(tokenNeedsRefresh({ accessToken: "a", refreshToken: "r", expiresAt: 1_050 }, 1_000, 100), true); assert.equal(tokenNeedsRefresh({ accessToken: "a", refreshToken: "r", expiresAt: 1_200 }, 1_000, 100), false); });