Skip to content

test(console): render the panes - #184

Merged
stormer78 merged 1 commit into
mainfrom
feat/console-renderer
Sep 7, 2026
Merged

test(console): render the panes#184
stormer78 merged 1 commit into
mainfrom
feat/console-renderer

Conversation

@stormer78

Copy link
Copy Markdown
Contributor

Eleven persona PRs today, and every bug that reached the live console lived in the one layer nothing could test:

what shipped what saw it
a ref callback that looped the renderer to a blank page (#179) you, within a minute
a form that opened empty because a selection was never passed to it (#182) you
a screen that never came back because its mode was decided once (#178) reading, just in time
a field asking for an identifier the context did not have (#181) you

The models under all of them — identity-graph, profile-entries, persona-flow, persona-candidates — passed throughout, because each was correct. Rendering is the only thing that sees the rest.

What this adds

tests/harness/ — module hooks and a DOM so node --test can mount a pane. Nothing changes about how tests elsewhere are run or written.

The hooks do two things that are not obvious:

  • resolve a ./thing.js import to thing.tsx. The sources use TypeScript's Bundler resolution, which the bundler honours and Node does not; existing tests sidestepped it by importing ../src/.../thing.ts with the real extension, which a component cannot do because its own imports are written the other way.
  • transform JSX with esbuild, not typescript. This repo is on TypeScript 7, whose JS API is the native port's small surface — transpileModule and JsxEmit are simply not on it, and a hook written against the 5.x compiler API fails with an undefined enum that names nothing.

The fake agent answers by task URI, returns the relay's real envelope ({ok, result: {kind: "accepted", …}}) so a pane that mishandles a real response cannot pass, and throws on a task the test did not name — a pane asking something unexpected is exactly what a test should notice, so that is a failure rather than an empty answer.

The tests

Nine, each written against the symptom a person saw rather than the fix, so they keep meaning something if the fix is rewritten. Every negative is paired: "a context with no identifier offers to create one" sits beside "a context with identifiers lists them", because the first alone passes against a form that always offers to create.

Mutation-checked against three of the real bugs:

  • restoring the scrape-from-a-ref3 tests fail (the loop takes the whole pane down, which is what it did)
  • dropping the create offer → a context that publishes no identifier offers to make one fails
  • ignoring the selection → selecting a persona aims the context's button at it fails

Two harness details that quietly made a test lie

Both cost me a false pass before they were fixed, and both are written down:

  • Click a checkbox; do not assign checked. React reads the click. A hand-set value plus a synthetic change looks like a tick to the test and like nothing to the component — the test passed while proving nothing about the handler.
  • Text matching takes the innermost element. Document order returns an ancestor, so clicking a card where the test meant a row inside it selects the wrong thing and then asserts against the wrong screen.

Cost

One devDependency (happy-dom), scoped to the extension package. The extension's test script gains tsc -b, matching packages/core's, because the render tests import through the real package and need its dist.

Verification

npm run lint, npm run build, npm test865 across four workspaces (extension 260 → 269). All six ci.yml assertions against the real build.

Eleven persona PRs today, and every bug that reached the live console
lived in the one layer nothing could test: a `ref` callback that looped
the renderer to a blank page, a form that opened empty because a
selection was never passed to it, a screen that never came back because
its mode was decided once, a field asking for an identifier the context
did not have. The models under all of them — `identity-graph`,
`profile-entries`, `persona-flow`, `persona-candidates` — passed
throughout, because each was correct. Rendering is the only thing that
sees the rest.

`tests/harness/` adds module hooks and a DOM so `node --test` can mount
a pane, with no change to how tests are run or written elsewhere.

**The hooks** resolve a `./thing.js` import to `thing.tsx` — the sources
use TypeScript's `Bundler` resolution, which the bundler honours and
Node does not — and transform JSX with esbuild. Not `typescript`: this
repo is on TypeScript 7, whose JS API is the native port's small
surface, with no `transpileModule` and no `JsxEmit` on it. A hook
written against the 5.x compiler API fails with an undefined enum and
names nothing.

**The fake agent** answers by task URI, returns the relay's real
envelope so a pane that mishandles a real response cannot pass, and
**throws** on a task the test did not name — a pane asking something
unexpected is exactly what a test should notice, so that is a failure
rather than an empty answer.

Nine tests, each written against the symptom a person saw rather than
the fix, so they keep meaning something if the fix is rewritten.
Mutation-checked against three of the real bugs: restoring the
scrape-from-a-ref fails three of them, dropping the create offer fails
one, ignoring the selection fails one.

Two harness details worth knowing, both of which quietly made a test
lie before they were fixed: a checkbox must be clicked rather than have
`checked` assigned, because React reads the click; and text matching
takes the *innermost* element, because document order returns an
ancestor and clicking a card where a test meant a row inside it selects
the wrong thing and then asserts against the wrong screen.

Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
@stormer78
stormer78 merged commit 64bbcd7 into main Sep 7, 2026
3 checks passed
@stormer78
stormer78 deleted the feat/console-renderer branch September 7, 2026 14:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant