brackt/app/models/__tests__/commissioner.test.ts
Claude f462d0f0c7
Address code review feedback on settings/account deletion
1. Wrap anonymizeUserAccount in a DB transaction so partial failures
   (e.g. session delete succeeds but user update fails) can't leave
   accounts in an inconsistent state
2. Escape user email and notes with escapeHtml() before interpolating
   into the data request email body
3. Reset AlertDialog confirmed state when dialog is dismissed via
   backdrop click or Escape key (onOpenChange handler)
4. Extract accounts DB query to app/models/account.ts (findLinkedAccountsByUserId)
   to comply with the "always query through app/models/" convention
5. Replace dynamic imports() in action handlers with static top-level imports
6. Remove the unused hard-delete deleteUser() function
7. Add lastDataRequestAt timestamp to users (migration 0101) and enforce
   a 30-day server-side cooldown on data export requests
8. Replace fragile actionData type casts with a proper ActionData
   discriminated union; narrowing now works without `as` assertions
9. Strengthen tests: verify which schema tables are passed to delete()
   and that operations run inside the transaction

https://claude.ai/code/session_017Hvmof82Xr3UwKFc3pnC4X
2026-05-10 20:47:33 +00:00

131 lines
4.2 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from "vitest";
vi.mock("~/models/user", () => ({
isUserAdmin: vi.fn(),
}));
import * as schema from "~/database/schema";
vi.mock("~/database/context", () => ({
database: vi.fn(),
}));
import { isCommissioner, hasCommissionerRecord, removeAllCommissionersByUserId } from "../commissioner";
import { isUserAdmin } from "~/models/user";
import { database } from "~/database/context";
const LEAGUE_ID = "league-1";
const USER_ID = "user-uuid-1";
function makeMockDb(commissionerRow: object | null) {
return {
query: {
commissioners: {
findFirst: vi.fn().mockResolvedValue(commissionerRow),
},
},
};
}
beforeEach(() => {
vi.clearAllMocks();
});
describe("isCommissioner", () => {
it("returns true for a site admin without a commissioner record", async () => {
vi.mocked(isUserAdmin).mockResolvedValue(true);
vi.mocked(database).mockReturnValue(makeMockDb(null) as never);
const result = await isCommissioner(LEAGUE_ID, USER_ID);
expect(result).toBe(true);
});
it("returns true for a user with a commissioner record", async () => {
vi.mocked(isUserAdmin).mockResolvedValue(false);
vi.mocked(database).mockReturnValue(
makeMockDb({ id: "comm-1", leagueId: LEAGUE_ID, userId: USER_ID }) as never
);
const result = await isCommissioner(LEAGUE_ID, USER_ID);
expect(result).toBe(true);
});
it("returns true for a site admin who also has a commissioner record", async () => {
vi.mocked(isUserAdmin).mockResolvedValue(true);
vi.mocked(database).mockReturnValue(
makeMockDb({ id: "comm-1", leagueId: LEAGUE_ID, userId: USER_ID }) as never
);
const result = await isCommissioner(LEAGUE_ID, USER_ID);
expect(result).toBe(true);
});
it("returns false for a non-admin user without a commissioner record", async () => {
vi.mocked(isUserAdmin).mockResolvedValue(false);
vi.mocked(database).mockReturnValue(makeMockDb(null) as never);
const result = await isCommissioner(LEAGUE_ID, USER_ID);
expect(result).toBe(false);
});
it("runs the admin check and DB query in parallel", async () => {
const order: string[] = [];
vi.mocked(isUserAdmin).mockImplementation(async () => {
order.push("admin");
return false;
});
const db = makeMockDb(null);
db.query.commissioners.findFirst = vi.fn().mockImplementation(async () => {
order.push("db");
return null;
});
vi.mocked(database).mockReturnValue(db as never);
await isCommissioner(LEAGUE_ID, USER_ID);
// Both should have been called; order is non-deterministic for parallel calls
expect(order).toContain("admin");
expect(order).toContain("db");
});
});
describe("hasCommissionerRecord", () => {
it("returns true when a commissioner record exists", async () => {
vi.mocked(database).mockReturnValue(
makeMockDb({ id: "comm-1", leagueId: LEAGUE_ID, userId: USER_ID }) as never
);
const result = await hasCommissionerRecord(LEAGUE_ID, USER_ID);
expect(result).toBe(true);
});
it("returns false when no commissioner record exists", async () => {
vi.mocked(database).mockReturnValue(makeMockDb(null) as never);
const result = await hasCommissionerRecord(LEAGUE_ID, USER_ID);
expect(result).toBe(false);
});
it("returns false for a site admin without a commissioner record", async () => {
// hasCommissionerRecord must NOT consult the admin flag
vi.mocked(database).mockReturnValue(makeMockDb(null) as never);
const result = await hasCommissionerRecord(LEAGUE_ID, USER_ID);
expect(result).toBe(false);
expect(isUserAdmin).not.toHaveBeenCalled();
});
});
describe("removeAllCommissionersByUserId", () => {
it("deletes from the commissioners table for the given user", async () => {
const whereFn = vi.fn().mockResolvedValue(undefined);
const deleteFn = vi.fn().mockReturnValue({ where: whereFn });
vi.mocked(database).mockReturnValue({ delete: deleteFn } as never);
await removeAllCommissionersByUserId(USER_ID);
expect(deleteFn).toHaveBeenCalledTimes(1);
expect(deleteFn).toHaveBeenCalledWith(schema.commissioners);
expect(whereFn).toHaveBeenCalledTimes(1);
});
});