Skip to content

deck-plans: fix blanks-first + lift compareWithEmptyLast helper#64

Merged
dynnamitt merged 5 commits into
mainfrom
fix/issue63
May 11, 2026
Merged

deck-plans: fix blanks-first + lift compareWithEmptyLast helper#64
dynnamitt merged 5 commits into
mainfrom
fix/issue63

Conversation

@dynnamitt
Copy link
Copy Markdown
Contributor

Summary

Test plan

  • npm run test — 76/76 pass (6 new deck-plan cases)
  • npm run build — green
  • npm run lint — 0 errors (only pre-existing warnings unrelated to this change)
  • npm run check — Prettier clean
  • Manual smoke on /deck-plan: first load shows populated names, blank rows at the end; toggling Name sort asc↔desc keeps blanks at the end
  • Manual smoke on /vehicle-type: no regression
  • Manual smoke on search-side: typing a query keeps blanks-last ordering

🤖 Generated with Claude Code

dynnamitt and others added 4 commits May 8, 2026 10:47
Fixes #63. /deck-plan exhibited the same blanks-first defect on first
load that PR #62 fixed for /vehicle-type. Lift the empty-last comparator
into a generic src/utils/compareWithEmptyLast.ts and route all three
call sites (vehicle-types, deck-plans, search-side useDataViewTableLogic)
through it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Simplify pass on PR feedback:
- Drop the duplicate getDeckPlanSortValue in deckPlanViewConfig.ts;
  import from the new module instead.
- Replace inline deckPlanSortVal in VehicleTypeDetails.tsx with the
  shared getDeckPlanSortValue + OrderBy from useDeckPlans.
- Convert switch default arms in both *SortValue.ts files to an
  exhaustive `never` check so adding a new OrderBy column is a
  compile error rather than silently falling through to '' (which
  would re-introduce the blanks-last bug for the new column).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Browser-level coverage for the blanks-first defect: stub the DeckPlans
GraphQL query with 5 named + 5 null-name rows, visit /deck-plan, and
assert page 1 lists Plan Alpha → Plan Echo before any null-name rows.
A second test toggles to desc and confirms blanks stay last (not
flipped to the top).

- e2e-tests/fixtures/deck-plans-mock.json: mixed-name fixture payload
- e2e-tests/no-auth/autosys-helpers.ts: interceptDeckPlansQuery helper
- e2e-tests/no-auth/deck-plan-name-sort.spec.ts: the spec

Both tests pass on Chromium and Firefox.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
NOTE: This is a client-side workaround. The real bug is in Sobek's
GraphQL serialization, which emits empty NeTEx Name elements as
whitespace strings (e.g. "\n                ") rather than null or "".
File a Sobek-side issue to fix the source; once that lands, drop the
`v.trim() === ''` branch from compareWithEmptyLast and revert the
e2e fixture to plain nulls.

Why this commit: until Sobek changes, the previous predicate
(`v === '' || v == null`) let whitespace strings through as "real"
values; ASCII '\n' (10) and ' ' (32) are < 'a' (97), so blank-name
rows still dominated page 1 of /deck-plan even after PR #62/#63's
empty-last logic. Fixture-driven unit + e2e tests passed because
they used null, not whitespace.

Patch: add `isEmpty` predicate that trims string values before the
emptiness check. 0 remains a real numeric value (vehicle-types
`length: 0` unaffected).

Verified live against `npm run local`: page 0 now shows named rows
(ids 9 "aa" + 10 "zz") first, whitespace-name rows parked at the end.

- Whitespace regression case added to deckPlanSortValue.test.ts (77/77).
- e2e fixture mixes null + whitespace + tab/newline strings so the
  Playwright spec exercises the predicate (4/4 green).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dynnamitt dynnamitt requested review from GunnarAtEgde and Copilot and removed request for Copilot May 8, 2026 10:26
- src/utils/compareWithEmptyLast.ts: export isEmpty so future call sites
  inherit the same Sobek-aware trim semantics; hoist `dir` constant to
  drop one ternary per branch.
- e2e-tests/no-auth/autosys-helpers.ts: extract interceptGraphQLQuery
  + loadFixture helpers; both interceptVehicleTypesQuery and
  interceptDeckPlansQuery become one-liners.
- src/data/vehicle-types/vehicleTypeSortValue.test.ts: mirror the
  whitespace regression case from deckPlanSortValue.test.ts — same
  comparator, same Sobek backend, same exposure to entur/sobek#121.
- e2e-tests/no-auth/deck-plan-name-sort.spec.ts: drop redundant
  waitForLoadState('networkidle') — the toHaveAttribute assertion on
  total-entries already gates render.

78/78 unit, 24/24 e2e (Chromium + Firefox).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dynnamitt dynnamitt merged commit 751183d into main May 11, 2026
9 checks passed
@dynnamitt dynnamitt deleted the fix/issue63 branch May 11, 2026 09:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

deck-plans: Name column blanks-first on first load (same bug as #61) + DRY shared sort util

1 participant