Compare commits

..

1 Commits

Author SHA1 Message Date
d38a1ec917 fix: one wording for a rejected password on every screen (closes #172)
All checks were successful
check / check (push) Successful in 42s
The send confirmation and the delete-wallet confirmation rendered
"Wrong password." — a fragment, which README Language & Labeling and
RULES.md:120 both forbid — while the two reveal screens said "That
password is not correct." and the two dApp approval paths said "That
password is incorrect." Three wordings for one condition, on screens a
user can reach minutes apart.

All six decryptWithPassword call sites, across the five views that own
one, now show the wording the approval paths introduced:

    That password is incorrect. Please try again.

Strings only. Nothing about how a wrong password is handled changes: it
still fails closed on every screen, and the approval paths' settlement,
claim/release interlock and retry behaviour are untouched.

The new test scans the source for the call sites rather than driving
each view, because the invariant is about the set: a seventh call site
has to join it, and a per-view test cannot notice a screen nobody wrote
one for. It asserts per call site, not per file — each decrypt is read
back to its own catch handler and the prose that handler shows must be
the canonical sentence and nothing else. approval.js decrypts twice and
is where the divergence came from, so a per-file check that only asks
whether the sentence appears somewhere in the file passes while one of
those two says something novel. Exact equality catches a new wording,
not only a known-superseded one.
2026-08-12 09:48:36 +00:00
2 changed files with 8 additions and 25 deletions

View File

@@ -52,14 +52,6 @@ undefined identifiers, which is how
introduced. Strings only, no behaviour change, and each error container
measured at a 360px viewport in the pinned Playwright container
([#172](https://git.eeqj.de/sneak/AutistMask/issues/172)).
- 2026-08-12: Closed the empty-array hole in the end-to-end unstubbed-request
guard. `batch.every()` is vacuously true on `[]`, so a POST with body `[]` was
answered `200 []` instead of failing the suite; the guard now rejects an empty
batch, demonstrated green-before/red-after with a throwaway probe. The comment
claiming `postData()` returns `null` for undecodable bodies was corrected to
the two real paths — an absent or empty body decodes to `null`, a binary body
decodes lossily into invalid JSON
([#187](https://git.eeqj.de/sneak/AutistMask/issues/187)).
- 2026-08-12: The transaction confirmation screen has browser coverage. The
end-to-end suite reaches ConfirmTx for both the native ETH and the ERC-20 path
off a funded-balance fixture, and asserts the pending, funded, over-balance

View File

@@ -297,26 +297,17 @@ async function handleRpc(route, postData, opts, report) {
// ethers batches by default, so the body may be an array.
const batch = Array.isArray(payload) ? payload : [payload];
// Anything that is not a JSON-RPC object, or a NON-EMPTY batch of
// them, is not RPC at all and must be reported like any other
// unrecognised outbound traffic rather than dereferenced.
//
// The length check is not decoration: every() is vacuously true on an
// empty array, so without it a POST with body [] was answered 200 []
// and escaped the guard entirely (issue #187). No real batch is empty,
// so nothing legitimate is caught by it.
//
// Two distinct paths land a non-RPC body here, and neither is an
// empty-string special case. playwright-core's postData() is
// `buffer.toString("utf-8") || null`, so an absent or empty body
// decodes to null, JSON.parse("null") yields null, and the type guard
// below reports it. A binary body is instead decoded LOSSILY into
// mojibake — not null — which is not valid JSON, so the catch above
// reports that one. Both end up reported; only the route differs.
// Anything that is not a JSON-RPC object, or a batch of them, is not
// RPC at all and must be reported like any other unrecognised
// outbound traffic rather than dereferenced. request.postData()
// returns null both for a bodyless POST and for a body Playwright
// cannot decode as UTF-8 (sendBeacon with a Blob, or any binary
// payload), so this is not an empty-string special case: it rejects
// every non-object payload, exactly as the catch above rejects every
// unparseable one.
if (
payload === null ||
typeof payload !== "object" ||
batch.length === 0 ||
!batch.every((req) => req !== null && typeof req === "object")
) {
report("unstubbed request: POST " + route.request().url());