test: drive the Settings screen in a browser and guard every popup element id (closes #229)
Nothing exercised the Settings view in a browser, and jest runs in the
node environment with no DOM, so the densest run of $("...") lookups in
the codebase was unverified at runtime. A wrong id is valid JavaScript
naming a defined function: $() returns null and the next property access
throws, which inside a view's init() aborts the rest of the popup's
init() and leaves every screen blank.
Two halves, because they catch different things.
The e2e suite (tests/e2e/run.js) gains seven cases between the address
removal and dust threshold sections. They assert the About well and the
wallet list were actually written — show() populates those near its end,
only the debug well and the debug-mode checkbox follow, so reading them
back proves show() ran through to there rather than just far enough to
unhide the section — that the four Token Spam Protection controls are
real input[type=checkbox] elements defaulted on, and that the theme and
network selectors offer exactly the choices src/shared/networks.js and
index.html define.
What the selectors persist is asserted by a round trip through
NON-DEFAULT values: they are driven to dark and sepolia, the popup is
closed and reopened, both are read back, and both are then restored the
same way and reasserted after a second reopen. Neither value is the
first <option> of its <select>, which is the point — the first option is
what the DOM reports with no JavaScript having run at all, so asserting
it would pass just as happily against a Settings screen that assigned
nothing. One spam filter is likewise toggled off and back on across a
reopen each way. Those round trips run the change handler, saveState(),
loadState() and the assignments show() and init() make, rather than only
looking at the screen. Each group records a coverage key and a final
case demands the exact set, so a section that silently stopped running
reddens the suite instead of shrinking it.
show() no longer wraps its settings-network lookup in if (networkSelect),
and neither does init(): a null there was silently skipped, which is
exactly the failure this change exists to make loud.
tests/popupElementIds.test.js is the general half and needs no browser,
so jest picks it up and it runs in make check: every literal id reached
through $(), document.getElementById(), showError()/hideError() and
showView() must exist in src/popup/index.html, no id in index.html may
be defined twice, and the scan asserts it found the code and the markup
so it cannot pass by covering nothing. Only literal arguments are
resolvable statically; $(containerId) and a lookup naming the wrong
existing element are the browser suites' job, and README says so.
Demonstrated against four deliberate breaks. A typo'd id in settings.js
reddens both halves, the e2e run reporting "pageerror: Cannot set
properties of null (setting 'checked')" against its first test. A
handler bound to the wrong but existing element passes the static guard
and reddens only the new functional case. A typo in a view no browser
suite opens reddens only the static guard. Deleting either persisted
value assignment in settings.js — the theme one in init(), the network
one in show() — reddens the selector round trip and nothing else, each
one on its own.
This commit is contained in:
28
TODO.md
28
TODO.md
@@ -46,6 +46,34 @@ undefined identifiers, which is how
|
||||
|
||||
# Completed Steps
|
||||
|
||||
- 2026-08-17: The Settings screen is driven in a browser, and every element id
|
||||
the popup looks up is checked statically. Nothing exercised Settings in the
|
||||
e2e suite, and jest runs with no DOM, so the densest run of `$("...")` lookups
|
||||
in the codebase was unverified at runtime. Seven new cases in
|
||||
`tests/e2e/run.js` reach Settings, assert the About well and the wallet list
|
||||
were actually written, assert the four Token Spam Protection checkboxes are
|
||||
real checkboxes defaulted on, and assert the theme and network selectors offer
|
||||
the choices `src/shared/networks.js` and `index.html` define. The selectors
|
||||
are then driven to `dark` and `sepolia` — neither is the first `<option>`, so
|
||||
neither can be read back from the markup with no JavaScript involved — and
|
||||
reasserted after a popup reopen before being restored the same way, and one
|
||||
spam filter is toggled off and back on across a reopen each way. Those round
|
||||
trips run the change handler, `saveState()`, `loadState()` and the
|
||||
`init()`/`show()` assignments rather than just looking at the screen. `show()`
|
||||
no longer guards its `settings-network` lookup with `if (networkSelect)`: a
|
||||
missing element must fail loudly, which is the whole failure mode this unit
|
||||
exists to catch. Each group records a coverage key and a final case demands
|
||||
the exact set, so a shortened or skipped section reddens the run instead of
|
||||
shrinking it. `tests/popupElementIds.test.js` is the general half and runs in
|
||||
`make check` with no browser: every literal id reached through `$()`,
|
||||
`document.getElementById()`, `showError()`/`hideError()` and `showView()` must
|
||||
exist in `src/popup/index.html`, which no id in `index.html` may define twice.
|
||||
Demonstrated on four deliberate breaks — a typo'd id (both halves red), a
|
||||
handler bound to the wrong but existing element (only the functional e2e case
|
||||
red), a typo in a view no browser suite opens (only the static guard red), and
|
||||
the deletion of both persisted-value assignments in `settings.js` (only the
|
||||
selector round-trip case red)
|
||||
([#229](https://git.eeqj.de/sneak/AutistMask/issues/229)).
|
||||
- 2026-08-17: One wording for an empty password field on every screen that asks
|
||||
for one. The private key export screen said "Password is required." where the
|
||||
other five say "Please enter your password.", the same one-condition-two-
|
||||
|
||||
Reference in New Issue
Block a user