Nothing exercises the Settings view in a browser. The e2e suite never navigates there, and jest runs in the node environment with no DOM, so every $("settings-...") lookup in src/popup/views/settings.js is unverified at runtime.
Consequence: a single wrong element id makes init() throw and takes the entire Settings screen down — network selector, theme, spam filters, wallet management, the lot. make check passes, review passes on a static grep, and the user finds it.
This is precisely the undefined-identifier class that shipped as #150 and #151. Settings is the densest concentration of id lookups in the codebase and has the least coverage of any screen.
Raised while adding a new checkbox in #176, where the author correctly flagged that their static verification was weaker than a run.
Partly overlapping but NOT a substitute: #152 adds ESLint, which would catch a genuinely undefined identifier. It would not catch a string id that is valid JavaScript but does not match any element in index.html — which is the actual failure mode here.
Implementation requirements
Add e2e coverage that creates a wallet, navigates to Settings, and asserts the screen renders with no page error.
Assert the controls are present and functional, not merely that the view is visible: the four Token Spam Protection checkboxes render with their expected default states, toggling one persists across a popup reopen, and the network and theme selectors render.
Make a wrong id FAIL the suite loudly. Any uncaught page error while on Settings must fail the run — the harness already treats console.error as a failure, so confirm a thrown init() actually surfaces that way rather than being swallowed.
Consider a cheap general guard alongside the specific test: assert every $("...") id referenced by the view modules exists in src/popup/index.html. That catches the whole class rather than the ids one test happens to touch, and is a static check that could run in make check.
Definition of done
An e2e test reaches Settings, asserts the spam-protection checkboxes and the network and theme selectors render, and toggles one setting across a reopen.
Deliberately breaking one element id in settings.js fails the suite — demonstrated, with captured output.
A green run cannot mean the Settings assertions were skipped.
TODO.md updated in the same commit.
make check passes.
Nothing exercises the Settings view in a browser. The e2e suite never navigates there, and jest runs in the node environment with no DOM, so every `$("settings-...")` lookup in `src/popup/views/settings.js` is unverified at runtime.
Consequence: a single wrong element id makes `init()` throw and takes the **entire Settings screen** down — network selector, theme, spam filters, wallet management, the lot. `make check` passes, review passes on a static grep, and the user finds it.
This is precisely the undefined-identifier class that shipped as https://git.eeqj.de/sneak/AutistMask/issues/150 and https://git.eeqj.de/sneak/AutistMask/issues/151. Settings is the densest concentration of id lookups in the codebase and has the least coverage of any screen.
Raised while adding a new checkbox in https://git.eeqj.de/sneak/AutistMask/issues/176, where the author correctly flagged that their static verification was weaker than a run.
Partly overlapping but NOT a substitute: https://git.eeqj.de/sneak/AutistMask/issues/152 adds ESLint, which would catch a genuinely undefined identifier. It would not catch a string id that is valid JavaScript but does not match any element in `index.html` — which is the actual failure mode here.
## Implementation requirements
- Add e2e coverage that creates a wallet, navigates to Settings, and asserts the screen renders with no page error.
- Assert the controls are present and functional, not merely that the view is visible: the four Token Spam Protection checkboxes render with their expected default states, toggling one persists across a popup reopen, and the network and theme selectors render.
- Make a wrong id FAIL the suite loudly. Any uncaught page error while on Settings must fail the run — the harness already treats `console.error` as a failure, so confirm a thrown `init()` actually surfaces that way rather than being swallowed.
- Consider a cheap general guard alongside the specific test: assert every `$("...")` id referenced by the view modules exists in `src/popup/index.html`. That catches the whole class rather than the ids one test happens to touch, and is a static check that could run in `make check`.
## Definition of done
- [ ] An e2e test reaches Settings, asserts the spam-protection checkboxes and the network and theme selectors render, and toggles one setting across a reopen.
- [ ] Deliberately breaking one element id in `settings.js` fails the suite — demonstrated, with captured output.
- [ ] A green run cannot mean the Settings assertions were skipped.
- [ ] `TODO.md` updated in the same commit.
- [ ] `make check` passes.
clawbot
added this to the 1.0.0 milestone 2026-08-11 15:09:37 +02:00
e2e (Chrome suite, tests/e2e/run.js) — a new Settings section, additive, following the existing shape and reusing the openSettings() helper already there:
reach Settings from the created wallet, assert #view-settings renders;
assert the four Token Spam Protection checkboxes are present, are real input[type=checkbox], and default to checked (hideSpoofedSymbols, hideLowHolderTokens, hideFraudContracts, hideDustTransactions all default true in src/shared/state.js);
toggle one by clicking it, close the page, reopen the popup, and assert it comes back off — that exercises the change handler, saveState(), loadState() and the init() assignment, not just visibility;
assert #settings-network and #settings-theme are select elements whose options match NETWORKS / the three theme values and whose current value equals persisted state.
Placed after the address-removal section so it runs before the sections that own the fixture state, and it leaves the popup back on #view-main.
Skip-detection. Each Settings test records a coverage key in env; a final guard test asserts the recorded set equals the expected set exactly. An early return, a deleted test or a silently-swallowed body then fails the run rather than shrinking it quietly.
Thrown init().settings.init(ctx) runs from the DOMContentLoaded handler in src/popup/index.js, so a wrong id throws inside an async function, i.e. as a promise rejection rather than a synchronous throw. I will verify empirically that that reaches the harness collector as a pageerror/console.error and fails the run, rather than assuming it — and if it is swallowed, the fix goes in the harness.
Demonstration. Break one id in src/popup/views/settings.js on the show() path and one on the init() path, capture both failing runs into the PR body, then revert.
Static guard. A jest test asserting every literal $("id") under src/popup/ has a matching id="..." in src/popup/index.html, so it runs in make check. Measured on next: 221 distinct referenced ids, 274 ids in the markup, 0 missing — no false positives today. Scoped to $("...") deliberately: literal document.getElementById("...") would drag in debug-banner, which is created at runtime and legitimately absent from the markup.
TODO.md in the same commit.
Plan.
**e2e (Chrome suite, `tests/e2e/run.js`)** — a new Settings section, additive, following the existing shape and reusing the `openSettings()` helper already there:
- reach Settings from the created wallet, assert `#view-settings` renders;
- assert the four Token Spam Protection checkboxes are present, are real `input[type=checkbox]`, and default to checked (`hideSpoofedSymbols`, `hideLowHolderTokens`, `hideFraudContracts`, `hideDustTransactions` all default `true` in `src/shared/state.js`);
- toggle one by clicking it, close the page, reopen the popup, and assert it comes back off — that exercises the `change` handler, `saveState()`, `loadState()` and the `init()` assignment, not just visibility;
- assert `#settings-network` and `#settings-theme` are `select` elements whose options match `NETWORKS` / the three theme values and whose current value equals persisted state.
Placed after the address-removal section so it runs before the sections that own the fixture state, and it leaves the popup back on `#view-main`.
**Skip-detection.** Each Settings test records a coverage key in `env`; a final guard test asserts the recorded set equals the expected set exactly. An early return, a deleted test or a silently-swallowed body then fails the run rather than shrinking it quietly.
**Thrown `init()`.** `settings.init(ctx)` runs from the `DOMContentLoaded` handler in `src/popup/index.js`, so a wrong id throws inside an async function, i.e. as a promise rejection rather than a synchronous throw. I will verify empirically that that reaches the harness collector as a `pageerror`/`console.error` and fails the run, rather than assuming it — and if it is swallowed, the fix goes in the harness.
**Demonstration.** Break one id in `src/popup/views/settings.js` on the `show()` path and one on the `init()` path, capture both failing runs into the PR body, then revert.
**Static guard.** A jest test asserting every literal `$("id")` under `src/popup/` has a matching `id="..."` in `src/popup/index.html`, so it runs in `make check`. Measured on `next`: 221 distinct referenced ids, 274 ids in the markup, 0 missing — no false positives today. Scoped to `$("...")` deliberately: literal `document.getElementById("...")` would drag in `debug-banner`, which is created at runtime and legitimately absent from the markup.
`TODO.md` in the same commit.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Nothing exercises the Settings view in a browser. The e2e suite never navigates there, and jest runs in the node environment with no DOM, so every
$("settings-...")lookup insrc/popup/views/settings.jsis unverified at runtime.Consequence: a single wrong element id makes
init()throw and takes the entire Settings screen down — network selector, theme, spam filters, wallet management, the lot.make checkpasses, review passes on a static grep, and the user finds it.This is precisely the undefined-identifier class that shipped as #150 and #151. Settings is the densest concentration of id lookups in the codebase and has the least coverage of any screen.
Raised while adding a new checkbox in #176, where the author correctly flagged that their static verification was weaker than a run.
Partly overlapping but NOT a substitute: #152 adds ESLint, which would catch a genuinely undefined identifier. It would not catch a string id that is valid JavaScript but does not match any element in
index.html— which is the actual failure mode here.Implementation requirements
console.erroras a failure, so confirm a throwninit()actually surfaces that way rather than being swallowed.$("...")id referenced by the view modules exists insrc/popup/index.html. That catches the whole class rather than the ids one test happens to touch, and is a static check that could run inmake check.Definition of done
settings.jsfails the suite — demonstrated, with captured output.TODO.mdupdated in the same commit.make checkpasses.Plan.
e2e (Chrome suite,
tests/e2e/run.js) — a new Settings section, additive, following the existing shape and reusing theopenSettings()helper already there:#view-settingsrenders;input[type=checkbox], and default to checked (hideSpoofedSymbols,hideLowHolderTokens,hideFraudContracts,hideDustTransactionsall defaulttrueinsrc/shared/state.js);changehandler,saveState(),loadState()and theinit()assignment, not just visibility;#settings-networkand#settings-themeareselectelements whose options matchNETWORKS/ the three theme values and whose current value equals persisted state.Placed after the address-removal section so it runs before the sections that own the fixture state, and it leaves the popup back on
#view-main.Skip-detection. Each Settings test records a coverage key in
env; a final guard test asserts the recorded set equals the expected set exactly. An early return, a deleted test or a silently-swallowed body then fails the run rather than shrinking it quietly.Thrown
init().settings.init(ctx)runs from theDOMContentLoadedhandler insrc/popup/index.js, so a wrong id throws inside an async function, i.e. as a promise rejection rather than a synchronous throw. I will verify empirically that that reaches the harness collector as apageerror/console.errorand fails the run, rather than assuming it — and if it is swallowed, the fix goes in the harness.Demonstration. Break one id in
src/popup/views/settings.json theshow()path and one on theinit()path, capture both failing runs into the PR body, then revert.Static guard. A jest test asserting every literal
$("id")undersrc/popup/has a matchingid="..."insrc/popup/index.html, so it runs inmake check. Measured onnext: 221 distinct referenced ids, 274 ids in the markup, 0 missing — no false positives today. Scoped to$("...")deliberately: literaldocument.getElementById("...")would drag indebug-banner, which is created at runtime and legitimately absent from the markup.TODO.mdin the same commit.