Commit c199895
test: fix five load-sensitive flaky tests by moving module loads out of timed windows (#3010)
* test(previews): stop dom-heavy preview tests racing the lazy renderer chunk
DatasetPreview and ReportPreview render their renderers behind
`React.lazy(() => import('@object-ui/plugin-charts' | '@object-ui/plugin-report'))`,
so everything the assertions wait on lives *behind* a Suspense boundary and
does not exist until that chunk resolves. Loading it is unbounded work: under
full-suite parallelism Vite's transform pipeline is saturated (the `dom-heavy`
project alone spends ~60s in transform), and the first import of the package
graph can outlast RTL's 1000ms `waitFor`/`findBy` window.
Instrumenting the import under a real full `dom-heavy` run measured
`import('@object-ui/plugin-report')` at 312ms / 424ms / 976ms across three
runs — that last one consumes 97.6% of the entire assertion budget before a
single render or `queryDataset` call can happen. A captured failure confirms
it: the DOM at timeout still showed the "Loading report renderer…" Suspense
fallback, and `queryDataset` had 0 calls because `ReportRenderer` — the thing
that calls it — had not loaded yet.
That explains exactly which tests flaked:
- ReportPreview.dataset: the *first two* tests, the ones running while the
very first import is still in flight; tests 3-5 find the module warm.
- DatasetPreview: only the ratio-measure test, because its "use the right
axis" caption is the one assertion in the file that sits *inside* the
Suspense boundary. Earlier tests assert on the table, which renders outside
it — so they start the import but never wait for it, leaving the last test
to race a load already in flight.
Fix: resolve each chunk once in `beforeAll`, taking the module load out of
every assertion window rather than widening the windows. ESM caches by
resolved specifier, so warming the same specifier makes the component's own
`React.lazy` factory resolve immediately. No timeout was raised and no file
was moved off the `dom-heavy` list.
Verified: `--project dom-heavy` failed 1 run in 4 before the change (the
captured failure above) and is green 14 consecutive runs after it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test: move unbounded module loads out of timed windows (unit + dom-heavy flakes)
Follow-up to the previous commit, which fixed the two `dom-heavy` preview files
with a `beforeAll` warm-up. Two changes here:
1. Switch that warm-up to a module-scope import. `beforeAll` is bounded by
`hookTimeout` (10s) — *narrower* than the 15s `testTimeout` it replaced. The
import phase has no such bound (a full run logs `import 1523s` cumulative
across 716 files without an import-phase failure), and it is where module
loading naturally belongs. Same idiom now used for every fix below.
2. Extend the same treatment to three more files that share the root cause —
unbounded work billed against a bounded window — found while verifying:
- `anchors.page-seed.test.ts`: `createSeed` reaches the page synthesizer via
`await import('@object-ui/plugin-detail')` (anchors.ts:207), so the cold
transform of that graph is billed to the test body. With `isolate: false`
the `unit` project's shared worker graph makes "who pays the cold
transform" scheduling-dependent, so it blew the 15s budget only sometimes.
Verified a timeout, not a wrong result: `createSeed` swallows failures and
returns `{}`, so a genuine synth failure would read as
`expected false to be true`, which was never observed.
- `plugin-kanban/src/index.test.ts`: was
`beforeAll(async () => { await import('./index') }, 15000)` — already
"fixed" once by raising its timeout, and still timed out under full load
(observed 15021ms, surfacing as 8 skipped tests rather than a failed
assertion). The raised timeout is deleted, not re-raised.
Tests: 15021ms hook -> 2ms.
- `all-locales-key-parity.test.ts`: a genuine quadratic, not a load effect.
Line 64 called `keysOf(builtInLocales[lang])` *inside* the `.filter()`
predicate, re-walking the whole locale tree once per `en` key (~2.5k keys x
a full recursive walk). The sibling assertion below it always hoisted the
call; this one didn't. Hoisting it: tests 7.51s -> 25ms (~300x), same 20
assertions passing. Parity itself is clean — all 9 non-`en` packs have 0
missing and 0 extra keys — so this was never a missing-translation failure.
No timeout was raised and no file was moved to an allowlist.
Verified:
- `--project dom-heavy`: failed 1 run in 4 before; green 20/20 runs after
(14 on the `beforeAll` form, 6 on the final static-import form).
- `--project unit`: the four files above pass; the 7 files that still fail are
a pre-existing broken baseline (real AssertionErrors in spec-subschema-parity,
onMutation, filter-operator-ast-parity x2, view-config-utils,
view-operator-builder-parity, clientValidation.fieldRules) — unchanged by
this commit, and unrelated to timing.
- Full suite before vs after: identical 19 genuine test failures, no new
failures, and no cross-file interference from the module-scope imports
despite `isolate: false`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>1 parent f1c04b6 commit c199895
5 files changed
Lines changed: 63 additions & 7 deletions
File tree
- packages
- app-shell/src/views/metadata-admin
- previews
- i18n/src/__tests__
- plugin-kanban/src
Lines changed: 14 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
4 | 18 | | |
5 | 19 | | |
6 | 20 | | |
| |||
Lines changed: 15 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
5 | 20 | | |
6 | 21 | | |
7 | 22 | | |
| |||
Lines changed: 17 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
5 | 22 | | |
6 | 23 | | |
7 | 24 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
61 | 61 | | |
62 | 62 | | |
63 | 63 | | |
64 | | - | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
65 | 72 | | |
66 | 73 | | |
67 | 74 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
| 9 | + | |
10 | 10 | | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
11 | 19 | | |
12 | 20 | | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | 21 | | |
19 | 22 | | |
20 | 23 | | |
| |||
0 commit comments