Files
hackerspace.sh/integration/equipment-overlap.test.ts
T
Moheeb Zara 6403220c92 test(integration): DB-backed harness validating shipped SQL (045/042/044/043)
Root-cause fix for 'correctness depended on post-deploy manual audits'.
Separate psql-driven suite (pnpm test:integration, own vitest config,
integration/ outside __tests__ so the hermetic pnpm test gate is
untouched; self-skips without a DB). 18 tests run against real Postgres:
- 045 class_signup_tx/class_cancel_tx: RETURNS TABLE->array shape the
  actions destructure, capacity/waitlist/dedupe, and the per-session
  advisory lock under TWO concurrent connections (D11 proven, never
  over-enrolls).
- 042 equipment exclusion constraint (overlap 23P01; cancelled/adjacent
  ok). 044 self-change trigger (role + payment cols blocked; service
  bypass). 043 members_update WITH CHECK (cross-space move blocked).
Disproves the pass-52 flagged risk (signup rpc-shape). Non-runtime;
default pnpm test still 532/26 hermetic; build clean.
2026-05-19 13:01:16 -07:00

56 lines
2.1 KiB
TypeScript

// Validates migration 042: the GiST exclusion constraint
// equipment_reservations_no_overlap is the real concurrency arbiter (the app
// check-then-insert was a TOCTOU). Only 'reserved' rows conflict; tstzrange
// '[)' makes adjacent windows non-overlapping.
import { describe, it, expect, beforeAll, afterAll } from 'vitest'
import { dbReady, execService, seedSpace, seedMember, seedEquipment, dropSpace } from './db'
const d = describe.skipIf(!dbReady)
d('equipment_reservations_no_overlap (migration 042)', () => {
let spaceId: string, equipmentId: string, memberId: string
const T = `timestamptz '2026-09-01 18:00:00+00'`
beforeAll(() => {
spaceId = seedSpace().spaceId
equipmentId = seedEquipment(spaceId).equipmentId
memberId = seedMember(spaceId).memberId
})
afterAll(() => dropSpace(spaceId))
const ins = (startOffH: number, endOffH: number, status = 'reserved') =>
execService(
`insert into equipment_reservations (equipment_id, space_id, member_id, starts_at, ends_at, status)
values ('${equipmentId}','${spaceId}','${memberId}',
${T} + interval '${startOffH} hours', ${T} + interval '${endOffH} hours', '${status}');`,
)
it('accepts a first reservation [0h,2h)', () => {
expect(ins(0, 2).ok).toBe(true)
})
it('REJECTS an overlapping reserved [1h,3h) (23P01)', () => {
const r = ins(1, 3)
expect(r.ok).toBe(false)
expect(r.err).toMatch(/exclusion constraint|equipment_reservations_no_overlap|23P01/i)
})
it('allows an overlapping CANCELLED row (only reserved conflicts)', () => {
expect(ins(1, 3, 'cancelled').ok).toBe(true)
})
it('allows an ADJACENT reserved [2h,4h) (tstzrange [) — no overlap)', () => {
expect(ins(2, 4).ok).toBe(true)
})
it('a different equipment is unaffected', () => {
const e2 = seedEquipment(spaceId).equipmentId
expect(
execService(
`insert into equipment_reservations (equipment_id, space_id, member_id, starts_at, ends_at, status)
values ('${e2}','${spaceId}','${memberId}', ${T}, ${T} + interval '2 hours','reserved');`,
).ok,
).toBe(true)
})
})