Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

flaky: DatasetWidget.dottedDimensionTable's "issues the ONE read" case asserts a fetch AFTER waiting only on the rendered cell #4487

Closed

Description

@yinlianghui

Observed on an unrelated PR (#4485, the plugin-chatbot DOM-prop whitelist — it touches no dashboard code). Test (shard 1/4) went red on:

FAIL dom packages/plugin-dashboard/src/__tests__/DatasetWidget.dottedDimensionTable.test.tsx
  > renders a LOCAL-only table exactly as the server sent it, and issues the ONE read (#4330)
AssertionError: expected [] to deeply equal [ 'crm_opportunity' ]
- [ "crm_opportunity" ]
+ []
 ❯ packages/plugin-dashboard/src/__tests__/DatasetWidget.dottedDimensionTable.test.tsx:207:23
 Test Files  1 failed | 331 passed (332)

Job: https://github.com/objectstack-ai/objectui/actions/runs/31632075546/job/94233072634 (shard duration 329.91s, import 650.16s — a saturated run).

Not the change under test, and not reproducible in isolation:

The race, as the source reads

await waitFor(() => expect(firstRowCells()[0]).toBe('Education'));
expect(requested).toEqual(['crm_opportunity']);

The wait is on the RENDERED CELL, but the assertion is about a metadata READ recorded by installMetaRouter. On the local path the row renders from the server's own rows — it does not depend on that read having resolved or even having been issued — so the two are only incidentally ordered. Under load the render wins and requested is still empty. This is AGENTS.md 测试纪律's profile exactly: an unbounded async step judged inside a window bounded by something else.

Not a timeout bump

AGENTS.md forbids fixing this class by raising a timeout or moving the file into heavyDomTests — both hide the race. The fix is to wait on the thing being asserted, e.g. await waitFor(() => expect(requested).toEqual(['crm_opportunity'])), keeping the rendered-cell assertion as its own step. The "exactly ONE read" property (the point of the case, per #4330) is preserved: a waitFor on set equality still fails on a second read.

Filed unassigned while implementing #4431; not fixed there — out of that card's surface.

Activity

  1. added theissue type on Aug 13, 2026
  2. hotlong commented on Aug 13, 2026

    @hotlong
    Contributor

    Triage: pm:queue, type: Bug (flaky test). Root cause and fix are both already pinned by the filer: the waitFor is bound to the rendered cell while the assertion is about a separately-resolving fetch — fix is to wait on the thing actually being asserted, not raise a timeout or move the file to heavyDomTests (AGENTS.md forbids both, per the filer). No decision pending.

    Size/model suggestion: S, mode:subagent, model: sonnet.


    Generated by Claude Code

  3. yinlianghui commented on Aug 13, 2026

    @yinlianghui
    ContributorAuthor

    Fresh live occurrence, recorded here rather than as a twin issue — it red-lighted an unrelated PR (#4552, a plugin-grid locale one-liner) on 2026-08-13.

    Where: CI run 31680222020, job Test (shard 1/4) attempt 1 — https://github.com/objectstack-ai/objectui/actions/runs/31680222020/job/94383748499

    Verbatim:

    FAIL  dom  packages/plugin-dashboard/src/__tests__/DatasetWidget.dottedDimensionTable.test.tsx
      > renders a LOCAL-only table exactly as the server sent it, and issues the ONE read (#4330)
    AssertionError: expected [] to deeply equal [ 'crm_opportunity' ]
    - Expected
    + Received
    - [
    -   "crm_opportunity",
    - ]
    + []
     ❯ packages/plugin-dashboard/src/__tests__/DatasetWidget.dottedDimensionTable.test.tsx:207:23
    

    Shard totals that attempt: 1 failed | 4437 passed | 1 skipped.

    Confirmed flake, not a break. Re-running the failed job with zero code change (attempt 2, same head sha 426a4d3a) went green: https://github.com/objectstack-ai/objectui/actions/runs/31680222020/job/94386051468. It also passes in isolation locally (6/6), and main's own Test (coverage) job at 479cc7b4 — that PR's exact base — was green, so it only surfaces under the sharded PR runs.

    Mechanism, as this issue already states, confirmed from the source: the case waits only on the rendered cell —

    await waitFor(() => expect(firstRowCells()[0]).toBe('Education'));
    expect(requested).toEqual(['crm_opportunity']);
    

    — and the file's own amended-pin comment explains why that wait cannot cover the fetch: with no bundle mounted the display equals the authored label, so relabelDimensions returns the server's rows by identity and the cell reads Education on the very first paint. The waitFor is therefore satisfied before the async GET /meta/object/:name has pushed into requested, and the next line asserts an unsynchronized side effect. Under a loaded shard the fetch loses that race; alone on a quiet runner it wins. The sibling case two blocks up is exposed the same way — it asserts ['crm_opportunity', 'crm_account'] after the same single-cell wait, so it is the same defect with a wider target.

    Suggested shape (not implemented here — out of scope for #4552): wait on the effect being asserted, e.g. await waitFor(() => expect(requested).toEqual(['crm_opportunity'])), keeping the cell assertion as the separate identity pin it is meant to be.


    Generated by Claude Code


    Generated by Claude Code

  4. yinlianghui commented on Aug 15, 2026

    @yinlianghui
    ContributorAuthor

    Second site of the same race, measured today while implementing #4683 (session session_01RnQd8iMMUwXQEV1crFmQiQ). Attaching here rather than filing a duplicate, so one fix closes the class.

    packages/plugin-dashboard/src/__tests__/DatasetWidget.dottedDimension.test.tsx:269 — the sibling file of the one this card names — has the identical shape:

    await waitFor(() => expect(categoriesOf('bogus')).toEqual(['education']));
    // Only the base object was ever asked for.
    expect(requested).toEqual(['crm_opportunity']);

    in falls through gracefully when the relationship segment is not a relationship. The wait is on the rendered category; the assertion is on installMetaRouter's requested. Same failure text this card quotes:

    AssertionError: expected [] to deeply equal [ 'crm_opportunity' ]
    - [ "crm_opportunity" ]
    + []
     ❯ packages/plugin-dashboard/src/__tests__/DatasetWidget.dottedDimension.test.tsx:269:23
    

    Same non-reproducibility profile, and measured on BOTH sides of my change so it is not that change:

    • full pnpm exec vitest run packages/plugin-dashboard/ with my guard applied: 1 failed | 461 passed (the line above);
    • same command with the guard ablated (git checkout origin/main -- AdvancedChartImpl.tsx): 58 passed (58) · 462 passed;
    • same command with the guard restored: 58 passed (58) · 462 passed;
    • the file alone: green.

    So it is load/order dependent exactly as described here, and the remedy this card already prescribes — wait on the thing being asserted, keeping the rendered assertion as its own step — applies verbatim at line 269. Whoever takes this card should sweep the other installMetaRouter call sites for the same pattern rather than fix the two known lines.


    Generated by Claude Code

  5. self-assigned this
    on Aug 15, 2026
  6. yinlianghui commented on Aug 15, 2026

    @yinlianghui
    ContributorAuthor

    Claim: PM loop round 12
    Session: session_01RnQd8iMMUwXQEV1crFmQiQ
    Branch: claude/issue-4487-dotted-dimension-race
    Worktree: objectui-issue-4487
    Domain: repo:objectui
    File surface: the two measured race sites — packages/plugin-dashboard/src/__tests__/DatasetWidget.dottedDimensionTable.test.tsx (:207 per this card) and DatasetWidget.dottedDimension.test.tsx (:269, second site attached 2026-08-15 from the #4683 run) — plus any sibling in the same file family with the identical waitFor-then-bare-assertion shape found during re-derivation (name each in the report). Tests-only; ⛔ no production source, ⛔ no skip-changeset label (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: sonnet
    Serial constraints cleared: in-flight is objectstack#8830 (other repo) and #4701 (app-shell previews test — disjoint); no open dev PR touches plugin-dashboard tests.


    Generated by Claude Code

  7. yinlianghui commented on Aug 15, 2026

    @yinlianghui
    ContributorAuthor

    <!-- os-dev-report -->

    {
      "issue": 4487,
      "status": "done",
      "branch": "claude/issue-4487-dotted-dimension-race",
      "pr": "https://github.com/objectstack-ai/objectui/pull/4704",
      "premise_still_valid": true,
      "summary": "Fixed the race at both measured sites (DatasetWidget.dottedDimensionTable.test.tsx:207, DatasetWidget.dottedDimension.test.tsx:269) plus one more found sweeping the file family (DatasetWidget.localSelectI18n.test.tsx:304) -- all three wait on rendered content that renders BY IDENTITY (independent of whether the metadata fetch resolved or was even issued), then bare-assert on installMetaRouter's requested array. Wrapped each requested assertion in its own waitFor, mirroring the repo's existing waitFor(() => expect(fetchMock)...) idiom. Checked the other 10 requested-assertion sites in the same file family and left them unchanged -- each of those waits on content that can only appear AFTER the metadata read resolves (dotted-path label, locale-bundle translation, multi-hop walk), so they are causally safe, not racy; the METRIC case is gated by enabled: !isMetric so it never fetches at all.",
      "tests": "Premise reproduced locally: looped 25 isolated runs of the 3 files against the PRE-FIX content (restored temporarily from origin/main, fix stayed committed on the branch) -- DatasetWidget.dottedDimension.test.tsx:269 failed on run 14/25 with 'AssertionError: expected [] to deeply equal [ crm_opportunity ]', byte-identical to CI's reported failure. Same loop against the fixed code: 0/40 failures. Deterministic reverse verification at the issue's named site: added a temporary 20ms delay to installMetaRouter's mock (test double only, never committed) to widen the window, then ran 5x with the OLD bare-assertion form (5/5 failed, same assertion text) and 5x with the NEW waitFor form under the identical delay (5/5 passed); delay and form-swap fully reverted, working tree matches the committed fix exactly (empty git diff against HEAD). Gate union at HEAD d321dd08c: `pnpm --filter '@object-ui/plugin-dashboard^...' build` green; `pnpm --filter @object-ui/plugin-dashboard run type-check` green; `pnpm exec vitest run packages/plugin-dashboard/` -- Test Files 58 passed (58), Tests 462 passed (462); `pnpm exec eslint --quiet` on the 3 touched files clean; `node scripts/check-changeset-presence.mjs` green (empty-frontmatter changeset declared); `pnpm run check:control-bytes` green.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  8. yinlianghui commented on Aug 15, 2026

    @yinlianghui
    ContributorAuthor

    os-dev-report (correction — the previous comment's marker was malformed as posted; this comment supersedes it as the report of record)

    {
      "issue": 4487,
      "status": "done",
      "branch": "claude/issue-4487-dotted-dimension-race",
      "pr": "https://github.com/objectstack-ai/objectui/pull/4704",
      "premise_still_valid": true,
      "summary": "Fixed the race at both measured sites (DatasetWidget.dottedDimensionTable.test.tsx:207, DatasetWidget.dottedDimension.test.tsx:269) plus one more found sweeping the file family (DatasetWidget.localSelectI18n.test.tsx:304) -- all three wait on rendered content that renders BY IDENTITY (independent of whether the metadata fetch resolved or was even issued), then bare-assert on installMetaRouter's requested array. Wrapped each requested assertion in its own waitFor, mirroring the repo's existing waitFor(() => expect(fetchMock)...) idiom. Checked the other 10 requested-assertion sites in the same file family and left them unchanged -- each of those waits on content that can only appear AFTER the metadata read resolves (dotted-path label, locale-bundle translation, multi-hop walk), so they are causally safe, not racy; the METRIC case is gated by enabled: !isMetric so it never fetches at all.",
      "tests": "Premise reproduced locally: looped 25 isolated runs of the 3 files against the PRE-FIX content (restored temporarily from origin/main, fix stayed committed on the branch) -- DatasetWidget.dottedDimension.test.tsx:269 failed on run 14/25 with 'AssertionError: expected [] to deeply equal [ crm_opportunity ]', byte-identical to CI's reported failure. Same loop against the fixed code: 0/40 failures. Deterministic reverse verification at the issue's named site: added a temporary 20ms delay to installMetaRouter's mock (test double only, never committed) to widen the window, then ran 5x with the OLD bare-assertion form (5/5 failed, same assertion text) and 5x with the NEW waitFor form under the identical delay (5/5 passed); delay and form-swap fully reverted, working tree matches the committed fix exactly (empty git diff against HEAD). Gate union at HEAD d321dd08c: pnpm --filter '@object-ui/plugin-dashboard^...' build green; pnpm --filter @object-ui/plugin-dashboard run type-check green; pnpm exec vitest run packages/plugin-dashboard/ -- Test Files 58 passed (58), Tests 462 passed (462); pnpm exec eslint --quiet on the 3 touched files clean; node scripts/check-changeset-presence.mjs green (empty-frontmatter changeset declared); pnpm run check:control-bytes green.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions