mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-08-29 03:55:38 -04:00
- Block all non-health API requests with 503 while a database restore is in progress (`withDatabaseAccessBlocked` in `@sofa/db/client`); pause and resume cron jobs around the restore window - Replace the two-hook first-user admin promotion with an atomic `claimInitialAdmin` query that uses a DB-level unique constraint so concurrent sign-ups during the first-run window can't each see `userCount === 0` - Fix `refreshAvailability` to always call `replaceAvailabilityTransaction` (clearing stale rows) even when TMDB returns no US providers, instead of returning early and leaving old data in place - Fix `performUpdateCheck` to read `release_url` (snake_case) from the public API response instead of `releaseUrl` - Fix `createJob` import handler to catch `SQLITE_CONSTRAINT_UNIQUE` and surface it as an `IMPORT_ALREADY_RUNNING` conflict error instead of a 500 - Relax public API telemetry schema to accept `string | number` for `users` and `titles` fields - Add tests for availability clearing, import deduplication, and `claimInitialAdmin`
93 lines
2.8 KiB
TypeScript
93 lines
2.8 KiB
TypeScript
import { beforeEach, describe, expect, test } from "bun:test";
|
|
|
|
import { user } from "@sofa/db/schema";
|
|
import { clearAllTables, eq, insertUser, testDb } from "@sofa/db/test-utils";
|
|
|
|
import {
|
|
claimInitialAdmin,
|
|
getSetting,
|
|
getUserCount,
|
|
isRegistrationOpen,
|
|
setSetting,
|
|
} from "../src/settings";
|
|
|
|
beforeEach(() => {
|
|
clearAllTables();
|
|
});
|
|
|
|
// ── getSetting / setSetting ─────────────────────────────────────────
|
|
|
|
describe("getSetting / setSetting", () => {
|
|
test("returns null for missing key", () => {
|
|
expect(getSetting("nonexistent")).toBeNull();
|
|
});
|
|
|
|
test("stores and retrieves a value", () => {
|
|
setSetting("theme", "dark");
|
|
expect(getSetting("theme")).toBe("dark");
|
|
});
|
|
|
|
test("upserts: overwrites existing value", () => {
|
|
setSetting("theme", "dark");
|
|
setSetting("theme", "light");
|
|
expect(getSetting("theme")).toBe("light");
|
|
});
|
|
});
|
|
|
|
// ── getUserCount ────────────────────────────────────────────────────
|
|
|
|
describe("getUserCount", () => {
|
|
test("returns 0 when no users", () => {
|
|
expect(getUserCount()).toBe(0);
|
|
});
|
|
|
|
test("returns correct count", () => {
|
|
insertUser("user-1");
|
|
insertUser("user-2");
|
|
expect(getUserCount()).toBe(2);
|
|
});
|
|
});
|
|
|
|
// ── isRegistrationOpen ──────────────────────────────────────────────
|
|
|
|
describe("isRegistrationOpen", () => {
|
|
test("returns true when no users exist (first-run)", () => {
|
|
expect(isRegistrationOpen()).toBe(true);
|
|
});
|
|
|
|
test("returns false when users exist and setting is not set", () => {
|
|
insertUser();
|
|
expect(isRegistrationOpen()).toBe(false);
|
|
});
|
|
|
|
test("returns true when users exist and setting is 'true'", () => {
|
|
insertUser();
|
|
setSetting("registrationOpen", "true");
|
|
expect(isRegistrationOpen()).toBe(true);
|
|
});
|
|
|
|
test("returns false when users exist and setting is 'false'", () => {
|
|
insertUser();
|
|
setSetting("registrationOpen", "false");
|
|
expect(isRegistrationOpen()).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("claimInitialAdmin", () => {
|
|
test("promotes the earliest user to admin and closes registration", () => {
|
|
insertUser("user-1");
|
|
insertUser("user-2");
|
|
|
|
expect(claimInitialAdmin("user-2")).toBe(false);
|
|
expect(claimInitialAdmin("user-1")).toBe(true);
|
|
expect(claimInitialAdmin("user-1")).toBe(false);
|
|
|
|
const firstUser = testDb.select().from(user).where(eq(user.id, "user-1")).get();
|
|
const secondUser = testDb.select().from(user).where(eq(user.id, "user-2")).get();
|
|
|
|
expect(firstUser?.role).toBe("admin");
|
|
expect(secondUser?.role).toBe("user");
|
|
expect(getSetting("registrationOpen")).toBe("false");
|
|
});
|
|
});
|