Files
fusion/packages/dashboard/app/components
gsxdsm de677b231a fix(tests): settings-mobile queries container; SettingsModal renders through a portal (#2890)
## What this clears

All **17 failures** in `settings-mobile.test.tsx` — the second-largest
block in the dashboard `app:backfill 3/4` shard after the
TaskDetailModal file (#2885), and the **same root cause**.

## Probed, not assumed

Every failure read `expected null to be truthy`, which looks like the
modal never rendered:

```
PROBE container.settings-layout=false  document.settings-layout=true
      document.modal=true  bodyLen=36637
```

`SettingsModal` mounts through `createPortal`, so its subtree hangs off
`document.body`, not the container `render()` returns. The markup is
there; the container-rooted lookup cannot see it.

## Nine of these assertions could never have failed

They are **absence** checks:

```ts
expect(container.querySelector(".settings-scope-banner")).toBeNull();
expect(container.querySelector("#settings-mobile-section")).toBeNull();
```

`container` is empty for this component no matter what, so these passed
on an **empty root** rather than on absence — they would have kept
passing if the element appeared. Converting them makes them mean what
they say. All nine still pass, so they were correct, just unproven.

## Two rounds of my own errors, both caught by measuring

1. A blanket `container` → `document` replace also rewrote
`renderResult.container.querySelector` into `renderResult.document...` —
**not a thing**. That broke the two *"embedded Settings surface"* star
tests. Because the embedded surface is genuinely not portalled, this
first read as *"embedded needs container"*. It doesn't; the JS was
simply invalid.
2. Fixed by restoring those seven, then converting them to **bare
`document`** once I confirmed each test unmounts its surface before
rendering the next (`modalRender.unmount()` precedes the embedded
render), so a document-rooted query cannot match a stale instance.

**Verified no regressions rather than assuming** — diffed the
failing-test list before and after: 13 fixed / 0 new, then the remaining
4 fixed. Every failure in the final state was already failing at the
start.

## Evidence

| | result |
|---|---|
| the file | **41/41** (was 17 failed) |
| shard `3/4` | **55 → 38** with this change alone |
| mutation: rename `.settings-layout` in `SettingsModal` | **1 failed**
|

`pnpm lint` clean. Test-only; `SettingsModal.tsx` restored clean.

## Together with #2885

#2885 clears the TaskDetailModal file (30). Both are the same
portal/query-root defect in different files, and both were sitting
behind `app:app` in the runner's fail-fast — which is why they went
unnoticed. Shard `3/4` should land at **~8** with both applied.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 17:59:18 -07:00
..
2026-06-27 23:37:24 -07:00