Skip to content

test(sandbox-panel): wait for the loaded panel, not for the load to start - #6064

Merged
senamakel merged 1 commit into
tinyhumansai:mainfrom
ntdatt812:fix/sandbox-panel-test-readiness
Sep 12, 2026
Merged

senamakel merged 1 commit into
tinyhumansai:mainfrom
ntdatt812:fix/sandbox-panel-test-readiness

Conversation

@ntdatt812

@ntdatt812 ntdatt812 commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

SandboxSettingsPanel.validation.test.tsx fails intermittently on CI:

FAIL  src/components/settings/panels/__tests__/SandboxSettingsPanel.validation.test.tsx
      > SandboxSettingsPanel — memory limit validation > persists a positive integer
TestingLibraryElementError: Unable to find an element with the display value: 512.

…and the DOM dump printed with it still shows the loading paragraph:

<p class="text-sm text-content-muted">Loading…</p>

Why

renderLoaded takes its readiness signal from the wrong event:

renderWithProviders(<SandboxSettingsPanel />);
await waitFor(() => expect(mockGet).toHaveBeenCalled());

SandboxSettingsPanel calls openhumanGetSandboxSettings() synchronously inside its mount effect (SandboxSettingsPanel.tsx:55), so that assertion is already true when waitFor first checks it. isLoading only flips in the finally (:69) — one microtask and a re-render later. renderLoaded therefore returns while the panel is still on its loading branch, and the synchronous getBy* accessors below it (memoryInput, cpuInput, imageInput) query a DOM that has no fields in it yet.

Usually the tick waitFor costs is enough to cover the microtask. On a loaded runner with coverage instrumentation it is not.

Two things worth noting:

  • The file already documents this exact trap, in flushPersist's docstring: "await waitFor(() => expect(mockGet).toHaveBeenCalled()) is NOT a readiness signal here: mockGet fires on mount, so the condition is already true and waitFor resolves on its first tick." It was applied to the negative assertions but the same non-signal was left as the readiness gate.
  • The sibling SandboxSettingsPanel.test.tsx does not trip on it — it reaches for the loaded DOM with findByRole / findByText, which retry. Only this file uses synchronous accessors.

The change

Await the backend combobox. It is rendered only by the loaded branch, and by every override these tests pass — including the docker_memory_limit_mb: null, docker_cpu_limit: null case, where waiting on a specific field value would not work.

Verification

The failure is timing-dependent, so I made it deterministic instead of running it until it flaked: have the mock resolve on a macrotask rather than a microtask, which is what a contended runner does to it.

on origin/main with this change
load resolves on a macrotask ✗ fails, Unable to find… + Loading… in the DOM ✓ 14/14
unchanged (fast load) ✓ 14/14 ✓ 14/14

Also clean in app/: npx tsc --noEmit, npx prettier --check.

No production code is touched, and no assertion is weakened — the tests still query the same elements and make the same claims; they just wait for the panel to exist first.

Summary by CodeRabbit

  • Tests
    • Improved settings panel test synchronization by waiting for backend options to load before querying subsequent fields.
    • Increased test reliability when validating settings after the loading state completes.

…tart

`SandboxSettingsPanel.validation.test.tsx` fails intermittently on CI with
"Unable to find an element with the display value: 512" and a DOM dump
still showing the loading paragraph.

renderLoaded's readiness signal is `waitFor(() => expect(mockGet)
.toHaveBeenCalled())`. The panel calls openhumanGetSandboxSettings
synchronously inside its mount effect, so that assertion already holds on
waitFor's first tick; isLoading only flips in the promise's finally
block, one microtask and a re-render later. The synchronous getBy*
accessors that follow can therefore query a DOM with no fields in it.

The file already documents this exact trap in flushPersist's docstring --
"mockGet fires on mount, so the condition is already true and waitFor
resolves on its first tick" -- but the same non-signal was left in place
as the readiness gate. The sibling SandboxSettingsPanel.test.tsx does not
trip on it because it reaches for the loaded DOM with findBy*, which
retries.

Awaiting the backend combobox instead: it is rendered only by the loaded
branch, and by every override these tests pass, including the
null-limits case.

Verified by making the load land on a macrotask instead of a microtask,
which is what a loaded runner does. Against origin/main that fails with
the CI error and the same loading paragraph; with this change the file
passes 14/14. It also passes 14/14 unmodified, and tsc --noEmit and
prettier --check are clean.
@coderabbitai

coderabbitai Bot commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 8f4af9c7-787e-44bd-8119-2c074a730c2e

📥 Commits

Reviewing files that changed from the base of the PR and between 64dd757 and 9ec0f98.

📒 Files selected for processing (1)
  • app/src/components/settings/panels/__tests__/SandboxSettingsPanel.validation.test.tsx

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The validation test now waits for the backend combobox to render before it queries fields, replacing an earlier wait that could complete while the panel remained in its loading state.

Changes

Sandbox settings validation

Layer / File(s) Summary
Wait for the loaded settings panel
app/src/components/settings/panels/__tests__/SandboxSettingsPanel.validation.test.tsx
renderLoaded now waits for the loaded-state backend combobox before subsequent field queries.

Estimated code review effort: 2 (Simple) | ~5 minutes

Merge Risk: ⚪ Minimal · up to 9ec0f

Sandbox settings validation tests now wait for the loaded panel before querying fields, removing an intermittent loading-state race without changing product behavior. No current merge-blocking risk remains.

Suggested reviewers: m3ga-mind

Poem

A rabbit waits beside the pane
The combobox appears again
The loading state hops away
Tests find their fields without delay
Green checks thump in gentle rain

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: updating the test to wait for the loaded panel instead of the request start.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI

Comment @coderabbitai help to get the list of available commands.

@tinysweeper tinysweeper Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

tinysweeper found nothing blocking. Approving.

$0.0000 · 0 in / 0 out · 128 embedded · openrouter/openai/text-embedding-3-small

@tinysweeper tinysweeper Bot added the priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect. label Sep 7, 2026
@senamakel senamakel self-assigned this Sep 12, 2026
@senamakel
senamakel merged commit 2ac3514 into tinyhumansai:main Sep 12, 2026
34 of 38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants