Sporalize-api / tests /workspace-performance.test.ts
Shoraky's picture
Bound auth upstream waits and preserve sessions during outages
35243f1
Raw History Blame Contribute Delete
8.46 kB
import assert from "node:assert/strict";
import { spawn } from "node:child_process";
import { once } from "node:events";
import { createServer } from "node:http";
import type { AddressInfo } from "node:net";
import { test } from "node:test";
test("optimized workspace reads preserve authorization, scores and fresh permission checks", { timeout: 30_000 }, async () => {
const owner = "11111111-1111-4111-8111-111111111111";
const other = "22222222-2222-4222-8222-222222222222";
const playerId = "33333333-3333-4333-8333-333333333333";
const otherPlayerId = "44444444-4444-4444-8444-444444444444";
const calls: { method: string; url: URL }[] = [];
let role = "user";
let revoked = false;
let authUnavailable = false;
let failActions = false;
const user = { id: owner, email: "test@example.com", email_confirmed_at: new Date().toISOString(), user_metadata: {} };
const plan = { subscription_id: "plan", plan: "Pro", price: 10, player_limit: 5, session_limit: 10 };
const player = { player_id: playerId, user_id: owner, fname: "Own", lname: "Player", bdate: "2000-01-01", gender: "male", image_path: null };
const sessions = [
{ session_id: "s1", player_id: playerId, user_id: owner, created_at: "2026-01-02T00:00:00Z", status: "completed", name: "Own session", player },
{ session_id: "s2", player_id: otherPlayerId, user_id: other, created_at: "2026-01-01T00:00:00Z", status: "completed", name: "Other session", player: { fname: "Other" } },
];
const actions = [
{ action_id: "a1", session_id: "s1", type: "Pass", annotation: { score: 7 } },
{ action_id: "a2", session_id: "s1", type: "Pass", annotation: null },
{ action_id: "a3", session_id: "s2", type: "Pass", annotation: { score: 10 } },
];
const upstream = createServer((req, res) => {
const url = new URL(req.url!, "http://stub");
calls.push({ method: req.method!, url });
res.setHeader("Content-Type", "application/json");
if (url.pathname === "/auth/v1/user") {
if (authUnavailable) { res.statusCode = 503; return res.end(JSON.stringify({ message: "Temporarily unavailable" })); }
res.statusCode = revoked ? 401 : 200;
return res.end(JSON.stringify(revoked ? { message: "Revoked" } : user));
}
if (url.pathname === "/auth/v1/token") {
return res.end(JSON.stringify({ user, access_token: "access", refresh_token: "refresh", expires_in: 3600, token_type: "bearer" }));
}
const table = url.pathname.split("/").at(-1);
if (table === "actions" && failActions) {
res.statusCode = 400;
return res.end(JSON.stringify({ message: "Unavailable" }));
}
let rows: Record<string, unknown>[] = table === "users" ? [{ user_id: owner, email: user.email, account_role: role }]
: table === "users_subscriptions" ? [{ user_id: owner, subscription_id: "plan", startdate: "2000-01-01", enddate: "2099-01-01", num_players: 1, num_sessions: 1, plan }]
: table === "players" ? [player, { player_id: otherPlayerId, user_id: other, fname: "Other" }]
: table === "sessions" ? sessions : table === "actions" ? actions : [];
for (const [key, filter] of url.searchParams) {
if (filter.startsWith("eq.")) rows = rows.filter((row) => String(row[key]) === filter.slice(3));
if (filter.startsWith("in.(")) {
const values = filter.slice(4, -1).split(",");
rows = rows.filter((row) => values.includes(String(row[key])));
}
}
const from = Number(url.searchParams.get("offset") ?? 0);
const limit = Number(url.searchParams.get("limit") ?? rows.length);
res.end(JSON.stringify(rows.slice(from, from + limit)));
});
upstream.listen(0, "127.0.0.1");
await once(upstream, "listening");
const portProbe = createServer();
portProbe.listen(0, "127.0.0.1");
await once(portProbe, "listening");
const port = (portProbe.address() as AddressInfo).port;
await new Promise<void>((resolve) => portProbe.close(() => resolve()));
const origin = `http://127.0.0.1:${port}`;
const child = spawn(process.execPath, ["--import", "tsx", "src/server.ts"], {
env: { ...process.env, NODE_ENV: "test", PORT: String(port), FRONTEND_URL: origin, BACKEND_URL: origin,
SUPABASE_URL: `http://127.0.0.1:${(upstream.address() as AddressInfo).port}`,
SUPABASE_ANON_KEY: "test-anon", SUPABASE_SERVICE_ROLE_KEY: "test-service", ANALYSIS_PROXY_SECRET: "x".repeat(32) },
stdio: ["ignore", "pipe", "pipe"],
});
try {
await new Promise<void>((resolve, reject) => {
child.stdout.on("data", (data) => { if (String(data).includes("API listening")) resolve(); });
child.once("exit", (code) => reject(new Error(`API exited: ${code}`)));
child.once("error", reject);
});
const request = (path: string, init: RequestInit = {}) => fetch(`${origin}${path}`, {
...init, signal: AbortSignal.timeout(10000), headers: { Cookie: "sp_access=access", Origin: origin, ...init.headers },
}).catch((error) => { throw new Error(`Request failed: ${path}`, { cause: error }); });
assert.equal((await fetch(`${origin}/api/players-overview`)).status, 401);
authUnavailable = true;
const outage = await request("/api/auth/me", { headers: { Cookie: "sp_access=access; sp_refresh=refresh" } });
assert.equal(outage.status, 500);
assert.equal(outage.headers.get("set-cookie"), null, "an outage must preserve session cookies");
assert.equal(calls.some((call) => call.url.pathname === "/auth/v1/token"), false, "an outage must not rotate refresh tokens");
authUnavailable = false;
const meStart = calls.length;
const me = await (await request("/api/auth/me")).json();
assert.equal(me.access.active, true);
assert.equal(me.access.subscription.plan, "Pro");
assert.equal(calls.length - meStart, 3); // auth + role + joined assignment/plan
const rosterResponse = await request("/api/players-overview");
assert.equal(rosterResponse.status, 200);
const roster = (await rosterResponse.json()).players;
assert.equal(roster.length, 1);
assert.equal(roster[0].scores.overall, 70);
assert.equal(roster[0].actionCount, 2);
assert.equal(roster[0].scores.scoredActions, 1);
const list = (await (await request("/api/sessions-overview")).json()).sessions;
assert.equal(list.length, 1);
assert.equal(list[0].playerName, "Own Player");
assert.equal(list[0].actionBreakdown.Pass, 2);
const detail = await (await request(`/api/players-overview/${playerId}`)).json();
assert.equal(detail.scores.overall, 70);
assert.equal(detail.playerCount, 1);
assert.equal((await request(`/api/players-overview/${otherPlayerId}`)).status, 404);
const billing = await (await request("/api/plan-billing")).json();
assert.equal(billing.subscription.name, "Pro");
assert.equal(billing.usage.sessions, 1);
assert.ok(!calls.some(({ url }) => url.pathname.endsWith("/annotations")));
const login = await request("/api/auth/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: user.email, password: "password123" }) });
assert.equal(login.status, 200);
assert.ok(!calls.some(({ method }) => method === "PATCH"));
role = "admin";
const adminPlayers = await (await request("/api/admin/players")).json();
assert.equal(adminPlayers.players.find((row: { player_id: string }) => row.player_id === playerId).sessionCount, 1);
const adminSessions = await (await request("/api/admin/sessions")).json();
assert.equal(adminSessions.sessions.find((row: { session_id: string }) => row.session_id === "s1").actionCount, 2);
const adminUsers = await (await request("/api/admin/users")).json();
assert.equal(adminUsers.users[0].dataCounts.sessions, 1);
const adminRows = (await (await request("/api/players-overview")).json()).players;
assert.equal(adminRows.length, 2);
role = "user";
assert.equal((await (await request("/api/players-overview")).json()).players.length, 1);
failActions = true;
assert.equal((await request("/api/sessions-overview")).status, 500);
revoked = true;
assert.equal((await request("/api/sessions-overview")).status, 401);
} finally {
if (child.exitCode === null && child.signalCode === null) {
const exited = once(child, "exit");
child.kill();
await exited;
}
upstream.closeAllConnections();
await new Promise<void>((resolve) => upstream.close(() => resolve()));
}
});