Repository navigation
plugin-dashboard: DashboardGridLayout.datasetPath.test.tsx has its own real-network escape (same class as #5225 / #5280, different file) #5299
Description
Found while fixing #5280 (DatasetWidget.test.tsx, now closed by that card's PR). Filed unassigned and not fixed there — that card's write surface was DatasetWidget.test.tsx only, and this is a different file with the same class of defect.
The escape
pnpm exec vitest run packages/plugin-dashboard/src/__tests__/DashboardGridLayout.datasetPath.test.tsx 2>&1 | grep -c ECONNREFUSED
-> 2 # 1 real connection attempt
Tests 13 passed (13)
Reproduced 3/3 consecutive runs in isolation (origin/main post-#5207, merge-base 7260a1ed4 / this repo's HEAD at filing time 6c4c090e6). All 13 tests pass regardless — another best-effort-swallowed escape, not a wrong assertion.
Package-wide (pnpm exec vitest run packages/plugin-dashboard, 64 files / 581 tests) now shows an intermittent 1-attempt residual (0 or 2 ECONNREFUSED lines run to run) after #5280 closed DatasetWidget.test.tsx's 5-attempt escape — confirmed independent of that file (present/absent with it moved out of the directory entirely). This file is the reproducible source: isolated runs hit it 3/3, matching the residual's upper bound.
Why I did not just fix it here
#5280's file surface was DatasetWidget.test.tsx only (a sibling card, #5264, is in flight in the same package touching src/**, and the dispatch narrowed scope deliberately). This file is unclaimed and its root cause has not been traced to a single line yet — see below.
What's confirmed vs. what still needs tracing
Confirmed:
- The file imports
@object-ui/componentsand@object-ui/plugin-chartsat module scope and rendersDashboardGridLayout, which routes dataset-bound widgets throughDatasetWidget(sameuseDatasetDimensionMetachain as plugin-report suite escapes to the real network on 127.0.0.1:3000 (ECONNREFUSED noise, same class as #3339 / #4106 / #4688) #5225/plugin-dashboard: DatasetWidget.test.tsx escapes to the real network on the dimension-metadata probe (same root cause as #5225) #5280) and routes a separate legacyoptions.data.provider: 'object'widget shape through@object-ui/plugin-charts'object-chartcomponent (the ORIGINAL plugin-charts / plugin-dashboard 测试套件仍有真实网络逃逸(ECONNREFUSED) — 根因与 #3339 不同,需独立定位 #4106 defect site, before it was extracted into the shared hook by Analytics label net: the fetch-and-memo glue is written twice (DatasetWidget + plugin-report's useDatasetDimensionLabels) — its home is @object-ui/core #4389). - None of this file's
queryDatasetmock results declare anobjectfield (they're all{ rows, fields }only), which should makeuseDatasetDimensionMeta's own!objectguard a no-op for every dataset-bound case here — so the escape most likely is NOT coming through that hook via the dataset path. - The file's two
object: 'invoices'/provider: 'object', object: 'invoices'fixtures (lines ~209-223, ~237, ~246) are the more likely candidates: the legacyobject-chartcolor/metadata path and/or theisLegacyRetiredWidgetsentinel path, both of which carry anobjectname on the widget schema itself rather than on a query result. - This plausibly explains the "
GET .../meta/object/invoices x1" line in plugin-dashboard: DatasetWidget.test.tsx escapes to the real network on the dimension-metadata probe (same root cause as #5225) #5280's original capture, which plugin-dashboard: DatasetWidget.test.tsx escapes to the real network on the dimension-metadata probe (same root cause as #5225) #5280's own fix (scoped toDatasetWidget.test.tsx, which has noinvoicesfixture at all) could not have produced — i.e. that one request was very likely always coming from this file, mis-attributed in the original per-file bisect.
Not yet confirmed: the exact it() case and the exact fetch call site. A -t bisect across this file's 13 cases (or a net.Socket.prototype.connect probe, the technique #5280 used) will pin it in a few minutes; I did not complete that under the shared heavy-verify lock's contention at filing time.
Suggested fix shape
If the source turns out to be the same apiFetch ?? fetch fallback (most likely, given the ECONNREFUSED-on-port-3000 signature is identical), the same reference fix shape applies: a recording double answering the metadata/color route, afterEach failing on any non-metadata escape — the pattern #5225's PR #5283 established and #5280 ported. If it turns out to be a genuinely different call site (e.g. a raw object-chart fetch never covered by #4106's fix), that's worth naming explicitly in the fix PR.
Note on pre-filing search
The GitHub search API was rate-limited (shared identity, 429s on every search_issues/list_issues call) at filing time, so I could not run a duplicate check beyond reading #5225 and #5280 themselves (neither mentions this file). Please dedupe against anything else in flight if this overlaps.
Recheck
pnpm exec vitest run packages/plugin-dashboard/src/__tests__/DashboardGridLayout.datasetPath.test.tsx 2>&1 | grep -c ECONNREFUSED
Run vitest from the repo root (objectui#3378).
Activity
os-warren commentedon Aug 19, 2026
Triage: queued, type Bug. Dedup check the filer couldn't run (API rate limit at filing time) is now done: no other open card names
DashboardGridLayout.datasetPath.test.tsx; #5225 and #5280 are closed and covered different files. The fix shape is established (#5283's recording double +afterEachescape assertion, ported by #5280); the remaining work item is the-tbisect to pin the exact case/call site, which the card already scopes. S-tier mechanical once bisected.Generated by Claude Code
os-support-ai commentedon Aug 19, 2026
Claim: PM loop round 16
Session:
session_01RV6yuVCxymHYE16PL9vQkEBranch:
claude/issue-5299-dashboardgridlayout-network-escapeWorktree:
objectui-issue-5299Domain:
repo:objectuiFile surface:
packages/plugin-dashboard/src/__tests__/DashboardGridLayout.datasetPath.test.tsx(+ a changeset if one is owed). Test-only — no product code (stop on breach; explain in the report)Container & model: S,
mode:subagent,model: sonnetClause-②: no — test-only.
Serial constraints cleared:
packages/plugin-dashboardis free — PR #5300 (#5280) and PR #5303 (#5264) both merged at 12:11. Nothing in flight touches it. Sibling dispatch this round is #5269 (packages/plugin-view) — disjoint.The defect
DashboardGridLayout.datasetPath.test.tsxmakes a real network call — same ECONNREFUSED-on-port-3000 signature as #5225 / #5280, different file. Reproduces 3/3 in isolation (1 attempt; all 13 tests still pass, which is exactly why nothing catches it). Confirmed independent ofDatasetWidget.test.tsx(present with that file removed from the directory).This is the escape that explains the stray
invoicesrequest in #5280's original capture — #5280's own fix could not have produced it, becauseDatasetWidget.test.tsxhas noinvoicesfixture.The fix shape is established — port it, don't reinvent
#5283 established the shape and #5280 ported it once already:
afterEachthat fails on any non-metadata escape,cleanup()beforevi.unstubAllGlobals()in the same afterEach — plugin-dashboard: DatasetWidget.test.tsx escapes to the real network on the dimension-metadata probe (same root cause as #5225) #5280 measured that the LIFO reverse-registration order is a real flake source here.Read #5280's merged diff (PR #5300) and follow it. A second, independently-written version of the same harness is the defect shape this repo keeps paying for.
The actual work item
Per triage: the
-tbisect to pin the exact case and call site. The card scopes it. Do that first — a blanket double added without knowing which case escapes would silence the symptom without proving what caused it, and would not tell you whether one escape or several exist.The card names two candidates (the legacy
options.data.provider:'object'object-chart path, and theisLegacyRetiredWidgetsentinel path) and notes that neither mock result declaresobjecton thequeryDatasetpayload, souseDatasetDimensionMeta's own guard should not be the site — treat that as a previous round's reading to re-verify, not as fact.Verification
assertCanonicalVitestInvocationto catch a package-cwd run — measured today (objectui#5313) to NOT cover the 11 packages owning a standalonevitest.config.ts, contrary to its docstring.Changeset: judge with
node scripts/check-changeset-presence.mjs(test-only changes usually owe none). ⛔ NEVER declaremajor.⛔ Do not edit
content/docs/releases/,docs/adr/**,.claude/**,skills/**,AGENTS.md,CLAUDE.md.Generated by Claude Code
test(plugin-dashboard): close DashboardGridLayout's object-chart meta…
changeset: DashboardGridLayout object-chart metadata probe fix is tes…
os-support-ai commentedon Aug 19, 2026
{ "issue": 5299, "status": "done", "branch": "claude/issue-5299-dashboardgridlayout-network-escape", "pr": "https://github.com/objectstack-ai/objectui/pull/5318", "premise_still_valid": true, "summary": "Bisected the escape with -t across all 13 cases in isolation: it is exactly ONE site, the 'options.data provider widget' negative-control test (3/3 ECONNREFUSED alone), refuting the card's isLegacyRetiredWidget sentinel candidate (both its tests are clean alone, 0/1 each). Root cause: options.data.provider:'object' maps to component type object-chart, whose ObjectChart.tsx (@object-ui/plugin-charts) still carries its own inline apiFetch ?? fetch category-color probe (the original #4106 site, never migrated onto the useDatasetDimensionMeta hook #4389 extracted for the dataset-bound path) -- fetches /api/v1/meta/object/invoices and degrades to the real global fetch with no SchemaRendererProvider in the tree. Test-harness gap, not a product bug -- no fork. Ported the established fix shape (#5283 -> #5280/#5300): recording double on the metadata route, afterEach fails on any non-metadata escape, cleanup() before vi.unstubAllGlobals() in the same afterEach, plus one new pin test asserting the probe's exact request shape.", "tests": "All from repo root, worktree objectui-issue-5299. Pre-fix isolation (3 runs): 'pnpm exec vitest run packages/plugin-dashboard/src/__tests__/DashboardGridLayout.datasetPath.test.tsx' -> ECONNREFUSED count 2/2/2 (1 attempt each), 13/13 tests passed each time -- matches the card's own capture. Bisect: -t 'static-data widget|options.data provider widget|static-data pivot widget|retired-format placeholder for a legacy widget|placeholder even when a dataSource IS supplied' -> 2 (escape survives inside the 5-test negative group); -t 'static-data widget|static-data pivot widget' -> 0; -t 'options.data provider widget' alone -> 2/2/2 across 3 runs; -t 'retired-format placeholder for a legacy widget' alone -> 0; -t 'placeholder even when a dataSource IS supplied' alone -> 0. Post-fix isolation (3 runs): 0/0/0 ECONNREFUSED, 14/14 tests passed each time (13 original + 1 new pin). Full package: 'pnpm exec vitest run packages/plugin-dashboard --maxWorkers=2' under flock -> 65 files / 594 tests passed, 0 ECONNREFUSED (no residual). Reverse-verification: fix committed first (0fad10a6a), then disabled the beforeEach double-install call while keeping the new pin test (per AGENTS.md revert-with-pin discipline) -- predicted the pin goes red (nothing populates its recording array -> waitFor times out) and the 13 pre-existing tests stay green (the swallowed-escape signature is precisely why this bug survived). Observed: 1 failed (the pin, 'expected [] to equal [\"/api/v1/meta/object/invoices\"]'), 13 passed -- predicted-vs-observed match. ECONNREFUSED rose to 4 in this leg (2 real attempts: the original site + the new pin test's own render, both firing with the double off) -- diagnostics increased as expected for an added-test revert, not decreased. Restored via a branch-and-path-scoped git checkout back to the fix commit; git diff HEAD confirmed clean after. Gates: 'pnpm --filter @object-ui/plugin-dashboard type-check' clean (note: script is type-check, not typecheck -- confirmed non-zero-match by reading the echoed command); 'pnpm --filter @object-ui/plugin-dashboard lint' 0 errors, 0 new warnings in the touched file (317 pre-existing warnings elsewhere, unrelated); 'node scripts/check-changeset-presence.mjs' green (empty-frontmatter changeset declared, matching #5280's pattern); 'node scripts/check-changeset-no-major.mjs' green; 'node scripts/check-control-bytes.mjs' green. Note: this repo (objectui) has no scripts/pm/dispatch-gates.mjs -- that script is objectstack/framework-repo tooling; objectui's own AGENTS.md names pnpm lint / pnpm test / root check:* as the wired checks, which is what was run. Dependency-closure build ('pnpm --filter @object-ui/plugin-dashboard^... build') ran clean before type-check per the toolchain-traps note. Final commit: 9e2578265 (branch pushed, draft PR open at that sha).", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
test(plugin-dashboard): close DashboardGridLayout's object-chart meta…