test(dashboard): name the skeleton in board-mobile-view-switch instead of the shared class (#2848)

Closes the last item I left open on #2834 — the two cases that were
passing against a skeleton.

## The weakness

They asserted `.list-view` to mean *"we are in list view"*. The workflow
**skeleton** carries that same class, so they matched it and passed
**without the list ever drawing**. I found this while adding the
`list-view-body` marker in #2834, tried to fix it, hit a dead end, and
reverted rather than leave two green tests red.

## Fixed by making the assertion honest, not by forcing the real body

This harness renders `<ListView>` with a deliberately small `../../api`
mock and no workflows, so the skeleton **is** what appears — and that is
fine, because the subject of these cases is the **board's** structure
after switching, not the list's contents. Naming the skeleton says what
the test actually observes.

## Why not the real body — measured, and it explains the earlier dead
end

Supplying the shared `DEFAULT_BOARD_WORKFLOWS` fixture makes ListView
render its full body, which **throws** under this file's api mock. The
harness has no `ErrorBoundary`, so React unmounts the entire root: the
DOM goes completely empty and every later query fails with a misleading
`Unable to find switch-to-board`.

That is precisely the failure I could not explain on #2834. A probe
placed after the await settled it:

```
PROBE after-await testids: [] | boundary: none
```

Empty DOM, no boundary — an uncaught render error taking the root down,
presenting as a missing button three lines later. Upgrading this to the
real body means expanding an api mock inside a file about board CSS
structure, which is a bigger change than the assertion is worth. The
reasoning is recorded at the site so the next person does not rediscover
it the way I did.

## The assertion is load-bearing, not just renamed

Mutating the skeleton's own `data-testid` in `ListView.tsx`:

```
TestingLibraryElementError: Unable to find an element by: [data-testid="list-workflows-skeleton"]   (x2)
```

Restoring it: `Tests 3 passed`.

## Verification

3/3 · `tsc` 0 · lint 0.

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

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-07-30 15:01:54 -07:00
committed by GitHub
parent bebbdf9083
commit c0e647f320

View File

@@ -130,7 +130,21 @@ describe("Board mobile view switch (FN-001)", () => {
render(<ViewSwitchHarness />);
// Start in list view
expect(document.querySelector(".list-view")).not.toBeNull();
/*
FNXC:ListView 2026-07-30-12:40:
Asserts the SKELETON by name, not `.list-view`, which the skeleton and the real body share.
This harness renders `<ListView>` with a deliberately small `../../api` mock and no workflows, so
what appears here is the workflow skeleton — and that is fine, because the subject of these cases
is the BOARD's structure after switching, not the list's contents. Naming it keeps the assertion
honest about what it observes.
Do not "upgrade" this to the real body without also expanding the api mock: supplying workflows
makes ListView render its full body, which throws under this mock, and with no ErrorBoundary in
the harness React unmounts the entire root — the DOM goes empty and every later query fails with
a misleading "switch-to-board not found". Measured; that is what happens.
*/
expect(screen.getByTestId("list-workflows-skeleton")).not.toBeNull();
expect(document.querySelector(".board")).toBeNull();
// Switch to board view
@@ -154,7 +168,21 @@ describe("Board mobile view switch (FN-001)", () => {
expect(document.querySelector(".list-view")).toBeNull();
fireEvent.click(screen.getByTestId("switch-to-list"));
expect(document.querySelector(".list-view")).not.toBeNull();
/*
FNXC:ListView 2026-07-30-12:40:
Asserts the SKELETON by name, not `.list-view`, which the skeleton and the real body share.
This harness renders `<ListView>` with a deliberately small `../../api` mock and no workflows, so
what appears here is the workflow skeleton — and that is fine, because the subject of these cases
is the BOARD's structure after switching, not the list's contents. Naming it keeps the assertion
honest about what it observes.
Do not "upgrade" this to the real body without also expanding the api mock: supplying workflows
makes ListView render its full body, which throws under this mock, and with no ErrorBoundary in
the harness React unmounts the entire root — the DOM goes empty and every later query fails with
a misleading "switch-to-board not found". Measured; that is what happens.
*/
expect(screen.getByTestId("list-workflows-skeleton")).not.toBeNull();
expect(document.querySelector(".board")).toBeNull();
fireEvent.click(screen.getByTestId("switch-to-board"));