• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kobotoolbox / kpi / 37782804264
86%
master: 76%

Build:
Build:
LAST BUILD BRANCH: dev-3198-paired-data-missing-file
DEFAULT BRANCH: master
Ran 08 Oct 2026 01:19PM UTC
Jobs 10
Files 920
Run time 3min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

08 Oct 2026 01:14PM UTC coverage: 83.132% (-0.005%) from 83.137%
37782804264

push

github

web-flow
fix(library): avoid null legacy router crash in library stores DEV-3061 (#7673)

### 💭 Notes

Fixes an intermittent `npm-test` failure in the Storybook test step,
e.g. [run
37465024804](https://github.com/kobotoolbox/kpi/actions/runs/37465024804)
(attempt 1, Firefox):

```
Features/LibraryUploadModal → UploadForm → play-test
can't access property "subscribe", _router_legacy__WEBPACK_IMPORTED_MODULE_7__.QB is null
```

Root cause: `LibraryUploadModal` imports `myLibraryStore`, whose
constructor (like `managedCollectionsStore`, `publicCollectionsStore`
and `singleCollectionStore`) schedules `setTimeout(() =>
router!.subscribe(...))`. The legacy `router` is only injected by
`router.tsx`, which Storybook never loads, so it stays `null` and the
callback throws on every Storybook run, in every browser. The test
runner only reports errors thrown while a play function is running, so
the test failed only when that timer happened to fire during the play
function.

Fix: use `router?.subscribe(...)` in the four library stores, as the
comment on `router` in `router/legacy.tsx` already recommends for
non-component callers ("may need to check null status").

- No change in the app: `router.tsx` injects the router when it loads,
before these timers fire.
- No change in the stories: the subscription only re-fetches data on
route changes, which never happen in Storybook. The other route checks
in the stores read `window.location.hash`, not the legacy `router`.
- Not a Storybook-side mock router: the timer is set when the story file
is imported, before any decorator runs, so injecting a router from a
decorator could still lose the race. A global router in
`.storybook/preview.tsx` would also clash with
`ProjectSettings.stories.tsx`, which resets the router to `null` when
its story unmounts.
- `router!.subscribe` in `ProjectSettings.tsx` and
`mainHeader.component.tsx` is left as is: those calls run when a
component mounts, not on import.

Out of scope: the more frequent `... (continued)

10499 of 13862 branches covered (75.74%)

33483 of 40277 relevant lines covered (83.13%)

5.49 hits per line

Jobs
ID Job ID Ran Files Coverage
1 37782804264.1 08 Oct 2026 01:19PM UTC 917
50.79
2 37782804264.2 08 Oct 2026 01:19PM UTC 915
43.46
3 37782804264.3 08 Oct 2026 01:19PM UTC 915
52.54
4 37782804264.4 08 Oct 2026 01:19PM UTC 915
49.55
5 37782804264.5 08 Oct 2026 01:21PM UTC 917
53.78
6 37782804264.6 08 Oct 2026 01:21PM UTC 917
44.74
7 37782804264.7 08 Oct 2026 01:22PM UTC 915
58.35
8 37782804264.8 08 Oct 2026 01:24PM UTC 918
67.82
9 37782804264.9 08 Oct 2026 01:25PM UTC 917
59.43
10 37782804264.10 08 Oct 2026 01:26PM UTC 920
70.26
Source Files on build 37782804264
  • Tree
  • List 920
  • Changed 1
  • Source Changed 0
  • Coverage Changed 1
Coverage ∆ File Lines Relevant Covered Missed Hits/Line Branch Hits Branch Misses
  • Back to Repo
  • b39346ab on github
  • Prev Build on main (#37778043158)
  • Next Build on main (#37783639365)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc