Fix Team Race duplicate-membership bug and two related team-roster gaps

Reported by the user: creating a team, adding the wrong driver, then
moving that driver to another team by ticking them on the new team's
edit form left the driver on both teams at once. Root cause: there
was never a "move" action - the edit form only ever added a driver to
the team being saved, never removed them from wherever they already
were. Live laps from a driver on two teams were then silently
credited to only the first-matching team, with no clear error.

reassignTeamMembers (event_race_logic.js) now strips a driver/car
being saved onto one team out of every other team in the same event,
and the team checkbox list shows which team a driver is already on
before you move them.

Also fixed two related gaps found while investigating, at the user's
request to fix everything: getTeamDriverPool had regressed to
ignoring the event's class/participant scoping entirely (showing
every driver in the club), and deleting a driver or car left them
behind in team rosters forever. Added a duplicate_team_members Race
Day preflight check as defense in depth for any already-corrupted
saved state.

Verified with new unit tests for reassignTeamMembers, getTeamDriverPool
and the new preflight check, plus a new permanent browser test
reproducing the user's exact reported scenario end to end.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
larssand
2026-09-10 17:07:45 +02:00
parent 71b3451b13
commit 15b574a37d
16 changed files with 261 additions and 15 deletions

View File

@@ -189,6 +189,25 @@ Fixed 2026-09-09, reported while exporting an old race from the new Results arch
Verified 2026-09-09: a new integration test (`tests/server_persistence.integration.test.js`) exports a PDF with a Swedish title and a table row containing å/ä/ö/Å/Ä/Ö, asserts the font declares WinAnsiEncoding, asserts the correct single-byte WinAnsi sequence is present in the raw PDF bytes, and explicitly asserts the old UTF-8 byte sequence is *not* present - confirmed this test genuinely fails against the pre-fix code (not a tautology) by re-running it with the fix reverted.
## Team Race roster duplicate-membership bug
Reported 2026-09-10 by the user: creating a team, adding a driver to it by mistake, then "moving" that driver to a different team by ticking them on the new team's edit form left the driver on *both* teams at once. Investigated before fixing, per the user's own account of the exact steps that triggered it.
Root cause: there was never a "move driver to another team" action - the only way to reassign someone was to tick their checkbox on the *new* team's edit form (`event_manager_controller.js`'s `teamForm`/`teamEditForm` submit handlers). That handler only ever wrote the team being saved; it never checked whether the driver/car was already listed on a different team, so ticking them there added them without ever removing them from wherever they already were. Consequence found while investigating: `findEventTeamForPassing` (`event_race_logic.js`) resolves a team by the *first* array match, so a driver on two teams had every one of their live laps silently credited to only one of them - the other team got nothing, with no error surfaced anywhere except a misleading "duplicate transponders" preflight warning (and only when the driver actually had a transponder set).
Two related bugs surfaced in the same code while investigating, at the user's request to fix everything found:
- `getTeamDriverPool` (`event_race_logic.js`) had been reduced, in an earlier change, to unconditionally return every driver in the club regardless of the event's class or configured participants - the class/participant-scoped filtering (with a documented fallback to "show everyone" only when the scoped list is empty) existed in an earlier version of this function and had been silently dropped.
- Deleting a driver or car (`core_views.js`) cleaned up session assignments but never removed them from any team's roster, so a deleted driver/car stayed a permanent "member" of whichever teams they'd been added to, inflating team member counts forever.
Fixed:
- [x] `reassignTeamMembers` (`event_race_logic.js`, new) strips a driver/car being saved onto one team out of every *other* team in the same event - both the create-team and edit-team submit handlers now call it before writing, so ticking a driver onto a new team genuinely moves them rather than duplicating them.
- [x] The team edit/create checkbox list now shows "Redan i &lt;team&gt; - kryssar du i flyttas den hit" next to a driver/car already on a different team, so the move is visible *before* saving, not just after.
- [x] `getTeamDriverPool` restored to scope by the event's class/configured participants first, falling back to every driver only when that scoped list is empty (so a team can still be set up before participants exist, without silently showing the whole club's roster once they do).
- [x] Deleting a driver or car now also removes them from every team's `driverIds`/`carIds`, and from a session's `driverIds`/`manualGridIds`, alongside the existing assignment cleanup.
- [x] Added a `duplicate_team_members` Race Day preflight check specifically for `team_race` sessions, naming the driver/car by name - defense in depth for any state saved before this fix, so it's diagnosed accurately instead of surfacing as a confusing "duplicate transponders" error (or nothing at all, if the shared driver has no transponder).
Verified 2026-09-10: new unit tests (`tests/race_timing_logic.test.js`) cover `reassignTeamMembers` (strips from other teams, leaves the team being saved and non-overlapping teams untouched) and `getTeamDriverPool`'s scoped-then-fallback behavior; new tests (`tests/race_day_logic.test.js`) cover the `duplicate_team_members` preflight check both tripping (naming the shared driver) and staying clear when teams don't overlap. A new permanent browser test (`tests/browser_team_membership.js`) reproduces the user's exact reported scenario end to end against a real race-mode event with a team_race session: creates Team A with Driver A, creates Team B with Driver B, opens Team B's edit form and confirms the "already on Team A" warning appears *before* saving, ticks Driver A onto Team B and saves, confirms Driver A is gone from Team A's roster and present on Team B's (the reported bug, now fixed), then deletes Driver B entirely and confirms they're gone from Team B's roster too.
## In-app update checker and one-click updater
Implemented 2026-09-09, requested by the user: an easy way to see a new version is available in the GUI, and an easy way to update for someone not comfortable with `git pull` on their own.