Skip to content

fix(web): show only the latest edition of each instrument in the repository view - #1823

Merged
joshunrau merged 4 commits into
mainfrom
fix/instrument-repo-preview-latest-edition
Oct 27, 2026
Merged

joshunrau merged 4 commits into
mainfrom
fix/instrument-repo-preview-latest-edition

Conversation

@thomasbeaudry

@thomasbeaudry thomasbeaudry commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

The admin Instrument Repositories view (eye icon) listed every edition an instrument repository
had ever contributed. Sync deliberately unions instrument ids so superseded editions keep their
provenance for existing records, but the view should show what the repository currently provides.
Example: CPPQ's CPP_GENERAL_INFORMATION showed as both edition 4 and edition 5 after a bump.

  • View dialog: keep only the latest edition per internal name for each repository (series
    instruments, which have no edition, are kept individually).
  • Instruments count column: uses the same latest-edition count once instrument info has loaded
    (falls back to instrumentIds.length otherwise).
  • Sync behaviour and stored instrumentIds are unchanged.

Addressing the review

The four TS2322 errors are fixed at the root rather than patched. Spreading scalarFixture and
re-adding internal makes the property fresh, so it was excess-property-checked against the
series branch of TranslatedInstrumentInfo, which has no internal. The internal name is now a
parameter of the fixture, so nothing is overridden after the spread and no cast is needed.

Two follow-up commits, typed test and refactor so this PR still produces exactly one changelog
entry:

  • The lookup previously keyed scalars by internal name and series by id in one map, which forced a
    current.kind !== 'SERIES' guard to compare editions — a branch no test can reach, since a series
    id would have to equal a scalar's internal name. It now maps each internal name to its highest
    edition and filters, which removes the guard, removes the key-space collision, and keeps the view
    in the order the API returned.
  • That surfaced a genuine gap: both original tests fed editions in ascending order, so the
    "superseded edition arrives second" comparison was never exercised. Added a descending-order case.

No end-to-end test

admin-instrument-repos.spec.ts already documents why: creating an InstrumentRepo is only
possible through POST /v1/instrument-repos, which downloads a zipball from GitHub, and
SetupService skips seeding the default repository under NODE_ENV=test. With no repository row,
the view dialog and the instruments count cannot be reached from a spec, and there is no seeding
path that avoids the network. Flagging this rather than adding a test that cannot assert the
behaviour.

Test plan

  • pnpm lint — 34/34 tasks, tsc clean in apps/web
  • pnpm test:coverage — 412 files, 4723 tests, 100% statements/branches/functions/lines
  • pnpm test:e2e — 288/292. Two pre-existing failures unrelated to this change:
    record-file-deletion (local .env has STORAGE_ENABLED=false; CI generates from
    .env.template, which has it on) and subject-detail, which passes on its own and fails only
    under local parallelism — CI runs workers: 1.
  • Each new test proven load-bearing by reverting index.tsx and watching it fail.

🤖 Generated with Claude Code

…sitory view

A sync keeps superseded editions attached to a repository, since records may
still reference them, so a form whose edition was bumped appeared once per
edition in the repository's instrument list and inflated its count.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

@joshunrau joshunrau left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lint-and-test CI check is failing on this branch, so review is on hold.

tsc in apps/web reports four TS2322 errors in src/routes/_app/admin/instrument-repos/__tests__/index.test.tsx (lines 283, 287, 302 and 306): each fixture object passes an internal property, and TranslatedInstrumentInfo does not declare one ("Object literal may only specify known properties, and 'internal' does not exist in type …").

Please fix the fixtures, or the type they are checked against, so pnpm lint passes, then push. Review resumes once CI is green.

Failing run: https://github.com/DouglasNeuroInformatics/OpenDataCapture/actions/runs/39824053917/job/119982511911

Reviewed at commit 362b134.

…verriding it

Spreading `scalarFixture` and re-adding `internal` makes the property fresh, so
it was checked against the series branch of `TranslatedInstrumentInfo`, which
has none: four TS2322 errors that stopped `tsc` in apps/web. The internal name
is now a parameter, so nothing is overridden after the spread.
The lookup held instruments keyed by internal name for scalars and by id for
series, so narrowing the stored value back off `kind` was needed to compare
editions — a branch no test can reach, since a series id would have to equal a
scalar's internal name. It now maps each internal name to its highest edition
and filters, which also keeps the view in the order the API returned.
@joshunrau
joshunrau merged commit 35e4f47 into main Oct 27, 2026
6 checks passed
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.

2 participants