chore: sql tests#338
Merged
Merged
Conversation
… rosters - add shared testcontainers boot helper (bootMigratedDb / seedRegionWithServer / runAsUser) that runs the real HasuraService.setup() pipeline and provisions the fivestack.app_key GUC needed by the servers trigger - add match-lifecycle spec: lineup provisioning, region resolution, map materialization, pending-match guard, scheduling rules, Live/Veto redirection, check-in auto-cancel, server release, delete cleanup - add player-stats spec: kill/assist/death/headshot/weapon aggregates, decrement-on-delete reparse balance, season attribution on/off - add team-rosters spec: owner bootstrap, invite conversion, captain rules, lineup captain election, ban enforcement, VAC flag clearing - fix seasons spec: seed a region+server so tbi_match's region sanitizer passes on a fresh install, compare timestamptz columns as ISO strings, drop an enum insert that violates e_match_types.description NOT NULL Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015gwbJtuPEvjR2D2eyGdz6U
…oring - map-veto spec: rulebook patterns (BO1/BO3), type/turn/side/pool enforcement, auto-Decider with map materialization and Live transition, Pick+Side side assignment, pick deletion removing its map, cancel wiping picks; documents that out-of-phase picks are gated by the Hasura permission function (lineup_is_picking_map_veto), not verify_map_veto_pick - region-veto spec: region cleared on Veto entry, turn order, LAN ban guard, last-available-region guard, auto-Decider locking the region and going Live (or staying in Veto when map veto is pending), cancel wiping picks - match-scoring spec: latest-round-snapshot scoring, BO1/BO3 series winner determination via update_match_state, tied maps deciding nothing, forfeit protection, map Live/Paused arming and disarming the live-match timeout Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015gwbJtuPEvjR2D2eyGdz6U
- tournaments spec: status-transition guards (stages required, past start date, non-organizer, manual finish), stage size validation, registration roster copy + eligibility (below-minimum, capacity overflow, revocation), single-elim bracket seeding on registration close, winner propagation into the final, automatic finish with trophy placement, min-teams auto-cancel, leave protection after the tournament is decided, trophy toggle wipe/rebuild - lobbies spec: creator bootstrap as accepted captain, single-lobby membership on accept, captain succession on leave, lobby teardown when the last accepted player leaves - match-options spec: edit lock after finish, invite-code lock outside PickingPlayers, structural field freeze during Live, cosmetic edits still allowed, map re-sync on pool swap, custom-pool garbage collection - widen PostgresService bindings type with boolean/null (accepted by pg at runtime; lets specs pass booleans without casts) - clean up cleanup order in tournaments beforeEach: matches before tournaments, otherwise bracket cascade triggers modify mid-delete tuples Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015gwbJtuPEvjR2D2eyGdz6U
- add test/utils/fixtures.ts: a typed Fixtures builder (players, map pools, match options, matches, bare imported matches, teams+rosters, seasons, kills/assists, round scores) that seeds through the real triggers, and refactor the SQL specs onto it, removing the per-spec copies of the same seed helpers - expose HasuraService from bootMigratedDb so suites can drive apply() - add test/fixtures.spec.ts guarding the LOAD_FIXTURES=true dev seeding path: fixtures.sql applies cleanly on a fresh install, seeds the documented dataset, re-enables every trigger it disabled, and cleanup.sql + re-apply round-trips (the scripts write with triggers disabled, so nothing else catches schema drift) - fix hasura/fixtures/fixtures.sql: the LAN game-server node referenced a 'LAN' region that was never inserted (the install seed spells it 'Lan'), so loading fixtures on a fresh database failed the game_server_nodes region FK; insert 'Lan' and point the node at it Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015gwbJtuPEvjR2D2eyGdz6U
…bugs New specs: - tournament-stages: RoundRobin full-schedule seeding, per-round scheduling, complete-table playthrough; Swiss (Valve format, 16 teams) pool structure, W/L pool routing, exact results-distribution playthrough; stage minimum halving propagation; RoundRobin -> SingleElimination multi-stage advancement with the stage-1 leader among the advancers - tournament-reset: preview chain, downstream match deletion with per-feeder slot clearing, source match reopening, finished-tournament rollback with trophy revocation, corrected-winner repropagation, and the live/foreign- winner/non-bracket guards - shared TournamentFixtures helper for tournament flows SQL fixes (found by the new tests): - find_adjacent_swiss_team: assigning NULL to a RECORD leaves it unassigned, so the IS NOT NULL checks raised 'record preferred_pool is not assigned yet' the first time an odd Swiss pool needed cross-pool pairing, breaking result reporting; track candidate pools with scalars instead. 8-team Swiss still surfaces a clean 'Odd number of teams in pool' error (the Valve pool math needs 16 teams) — documented by a regression test. - tai_player_kills: headshot_percentage is now also set on the very first kill (insert path) instead of reading 0% until the second kill; same for the season-stats insert - verify_map_veto_pick: reject picks when no veto step is active instead of letting NULL comparisons silently pass every guard Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015gwbJtuPEvjR2D2eyGdz6U
…ollision New coverage: - tournament-stages DoubleElimination: WB/LB/grand-final bracket shape, loser drops into the losers bracket, WB-final loser meeting the LB survivor, grand final pairing WB champion vs LB champion, full playthrough with an undefeated champion and 6 win/loss pairs - stat-recompute spec: finalized-round gating (events only count once their round lands), per-map kill/headshot/death/assist/damage aggregation, team-kill exclusion, exclusive multi-kill buckets, round deletion dropping events back out, the app.skip_round_recompute bulk import switch, and detect_round_clutch won/lost/saved/none outcomes - Fixtures: kills/damage/rounds now carry team sides, rounds and damage builders added SQL fix (found by the new tests): - assign_team_to_bracket_slot ranked a bracket's feeders by round and match_number only; the grand final's two feeders (WB final, LB final) tie on both, so the ordering was non-deterministic, both winners resolved to the same slot, and the second finisher overwrote the first. The half-filled grand final then resolved as a bye: the match was never played and the losers-bracket winner was crowned over the undefeated WB champion. Add a WB-before-LB ordering key, mirrored in reset_tournament_match's slot-clearing so resets unwind the same slots. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015gwbJtuPEvjR2D2eyGdz6U
- elo spec: 5000 baseline with symmetric expectations, rating chaining across matches (the favorite's expected score rises), series map differential scaling (2-0 sweep moves ratings twice as far as 2-1), recompute idempotency (delete + reinsert per match), external-source and undecided-match guards, per-season ladder isolation (new season restarts from baseline with its own season_id), tournament matches rating on the season-independent track, and the loss-protection transform (strong performers on losing teams lose less) - scrims/invites spec: already-rostered invite guard, one open scrim request per team pair in either direction (partial unique on LEAST/GREATEST), a resolved pair can re-request, terminal statuses clear actionable notifications while outcome notifications survive, and deleting a matched scrim's match cancels the request while freezing match_outcome and per-team check-in state for reputation Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015gwbJtuPEvjR2D2eyGdz6U
… counters - servers-and-nodes spec: node creation populating on-demand servers across the port range (paired game/tv ports), dedicated servers claiming the lowest node slot (requested port overridden) and releasing it on delete, rcon passwords encrypted at rest with re-encryption on change, the node server guards (no type change, no node removal, no orphan node servers), node deletion cascading its servers, and region server counts following node enablement - pools-players-clips spec: map-pool membership sync re-syncing pending matches on a map swap, refusing to shrink a pool below a pending match's best_of, leaving Live matches untouched; registered-name uniqueness and the role-hierarchy guards (cannot touch peers/superiors, cannot promote beyond own role, within-ceiling promotion works); match_maps clip summary counters through insert, publish, and delete Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015gwbJtuPEvjR2D2eyGdz6U
- draft-membership spec: join status resolution (host auto-accept, open-room accept, approval rooms requesting, host invites bypassing approval), the 5000 default elo snapshot, capacity waitlisting with promotion when seats free up, single-draft membership on accept, host succession to the oldest accepted member, draft teardown when the last player leaves or anyone leaves a started draft - streams-and-ranks spec: match stream priority reordering (move up pushes displaced streams down, move down pulls them up, deletion compacts the sequence) and premier-rank history rollback (players.premier_rank follows the latest remaining observation and clears when history empties) With this the trigger surface is covered end to end; the only remaining uncovered trigger bodies are two updated_at stamps and the settings-driven update_map_pools() hook, whose function does not exist in this repo (defined externally). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015gwbJtuPEvjR2D2eyGdz6U
Correction to the previous commit note: update_map_pools() does exist (hasura/enums/maps.sql). The taiu_settings trigger fires it when the update_map_pools setting flips to 'true'; the new test drops a map from the seeded Competitive pool and asserts the hook restores it from the active roster. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015gwbJtuPEvjR2D2eyGdz6U
- add .github/workflows/tests.yml: a fast unit job (typecheck of the test tree via the new tsconfig.spec.json, then src unit tests) and a sql job that runs the 22 testcontainers-backed SQL suites against the real migration pipeline (Docker ships on GitHub-hosted runners) - add test:unit / test:sql / typecheck:tests scripts - add tsconfig.spec.json so test files are actually typechecked — the root tsconfig only includes src/, which is how two impossible assertions reached main earlier on this branch's findings list - fix a latent type error in the kubernetes-client-node jest stub that the new typecheck surfaced Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015gwbJtuPEvjR2D2eyGdz6U
…esult-report deadlock New coverage: - views spec: v_player_match_map_hltv (per-round rates + the HLTV 2.0 formula, per-hit damage capping documented), v_match_clutches, v_player_elo ledger semantics, get_player_elo profile aggregation across seasons-off / seasons-on / tournament tracks, v_team_ranks roster averaging that ignores missing sources, v_team_reputation (completed scrims, no-shows pinned to the non-checked-in team even after match GC, late cancels charged only to the bailing team), and the elo leaderboard - permissions spec: can_check_in (window, membership, Captains setting), can_start_match (organizer path, empty lineups, both-lineups-checked-in path), can_cancel_match (organizer-only, never after a result), is_in_another_match (live/imminent only), is_in_lobby / is_in_draft, the escalating matchmaking cooldown scoped to the player's own session, and can_change_team_role (owner / roster admin / administrator) - concurrency spec: simultaneous veto picks serialize to exactly one Ban, simultaneous semifinal reports both propagate into distinct final slots, and racing waitlist promotions never over-fill a draft - fixtures spec: warm re-apply — wipe the stored file digests and re-run setup() over a data-full database, proving every enum/function/view/ trigger file applies cleanly against live data with all triggers left enabled (the upgrade path production actually takes) SQL fix (found by the concurrency spec): - update_tournament_bracket: two results reported at the same moment interleaved row locks in opposite orders (own bracket -> shared parent -> standings cache -> start-time sweep) and deadlocked; Postgres aborted one transaction, silently losing that match result. Lock the stage row first so every reporter takes locks in the same order. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015gwbJtuPEvjR2D2eyGdz6U
Bug #12: calculate_tournament_trophies derived silver and bronze from v_team_stage_results, but with a third-place match the runner-up and the decider's winner both finish 1-1, so the view's wins-based tiebreakers (round ratio, team KDR, team id) picked the medals arbitrarily. Medals now come straight from the brackets when the final stage is SingleElimination with a played third-place decider: final winner/loser take gold/silver, the decider's winner takes bronze. Anything else (RoundRobin last rounds, unfinished deciders) falls through to the view-based placements as before. New coverage: - test/tournament-edge-cases.spec.ts: byes for 5/6-team fields, the third-place decider routing both semifinal losers and awarding bronze to its winner (plus the trophies leaderboard mirroring all three medals), a seeded-PRNG upset run across 16-team Swiss landing on the exact Valve pool distribution, and a deep reset of a quarterfinal after the bracket finished, replayed to completion. - test/views.spec.ts: get_leaderboard categories best_kdr (deathless fallback, kill/death detail), best_win_rate, highest_hs_pct, the day window (0 = all time), get_player_leaderboard_rank, and the invalid category error. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015gwbJtuPEvjR2D2eyGdz6U
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.