test: drive ConfirmTx in the e2e suite, gate assertion included (closes #238) #258
Reference in New Issue
Block a user
Delete Branch "test/issue-238-confirmtx-coverage"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #238.
src/popup/views/confirmTx.jshad no unit tests andmake test-e2eneverreached the confirmation screen, so the screen that decides what gets signed
had no automated coverage of its own behaviour. The arithmetic underneath is
well covered in
src/shared/txValidation.js; the gap was the wiring.The load-bearing assertion
The confirmation screen quotes the fee estimate (
gasLimit * gasPrice) andgates on the fee reserve (
gasLimit * maxFeePerGas). Reading the quotednumber instead is
#154 in full, and until now
that was correct by reading only. The fixture stubs the two far apart
(estimate
0.002121 ETH, reserve0.004221 ETH) and sizes the refused sendsinto the gap between them, so an estimate-reading gate accepts what a
reserve-reading gate refuses.
Demonstrated, not asserted by inspection. With
feeWei = gasCostWeichanged tofeeWei = estimateWeiinestimateGas()— the mutant the review of#197 described — the suite
goes red:
Both paths die, through different balances and different messages. The mutation
was reverted;
git diff origin/nexttouches no file undersrc/.What the harness gained
tests/e2e/network.js, in the established read-at-request-time style:ethBalanceWei— hex wei answered toeth_getBalance, default zero, whichis what every pre-existing test expects.
seedTokenBalance— the ERC-20 holding that puts a token in the sendscreen's dropdown, the only route to the ERC-20 confirmation path.
eth_getBlockByNumberwith abaseFeePerGas. Without it ethers has nomaxFeePerGas, the reserve and the estimate collapse into one number, andthe gate tests would pass while asserting nothing. That trap is written down
next to the constants.
decimals()for the stub token oneth_call(every other call still answersa zero word, so the ENS reverse lookup is untouched). A zero there makes
parseUnits()reject a fractional amount and the ERC-20 estimate fails forthe wrong reason.
failGasEstimate— a node-side refusal foreth_estimateGas.holdGasEstimate— holds the estimate open so the pending state is observedrather than raced. A hold that outlives its bound is reported like any other
harness fault.
ErrorCollector.expect()intests/e2e/harness.js: a test that drives afailure path provokes the
console.errorthe code is supposed to emit, whichthe harness fails a run on. A declaration consumes exactly one matching record,
and a declaration nothing matched fails its test just as an undeclared error
does — so it cannot be used as a mute. Both halves were verified by running
against a deliberately wrong pattern (
console.error: [AutistMask] gas estimation failed: ...reported as an unexpected error) and by declaring anexpectation nothing emits (
expected browser error(s) that never arrived: ...).Coverage added
Nine tests, over both transaction types:
~0.002121 ETHandup to 0.004221 ETH reservedseparately.and the over-budget message NOT shown.
path:
1022.5625pxfor the ETH view and1070.5625pxfor the ERC-20 view,printed on every run.
TODO.mdand the End-to-End Tests section ofREADME.mdupdated in the samecommit.
Verification
make check: green. 19 suites, 416 tests,prettier --checkclean.make test-e2e: green, 23/23 (was 14/14 onnext).nextatbd4bdca; the only conflict wasTODO.md, resolved keeping both entries.Note for the reviewer:
script/lintin this repo isprettier --checkrun onthe host, not in a container — there is no containerised lint target to invoke
yet. That is #152, untouched
here.
Not touched, per the issue: the empty-array POST guard
(#187),
TRAILING_WATCH_MS,and the service-worker interception canary.
FAIL —
needs-rebase. One blocking finding; the change itself is sound and should not be touched.Not fast-forwardable onto current
origin/next. Branch head7e5d7cdforks atbd4bdca;nextis nowafe6dda, two commits ahead (#221 at23712b5, #155 atafe6dda).git merge-tree --write-tree origin/next 7e5d7cdexits 1 withCONFLICT (content): Merge conflict in TODO.md— both sides insert a bullet at the top of# Completed Steps. The PR body's rebase ontobd4bdcapredates both. Acceptable: rebase onto currentorigin/next, resolveTODO.mdkeeping all three bullets (this one plus the #221 and #155 entries — the #221 entry does not exist at this branch's merge-base and must not be dropped), re-run both suites, force-push. No other change wanted.Everything else verified and passing, independently reproduced on a clean clone:
make check19 suites / 416 tests, prettier clean;make test-e2e23/23 executed; every DoD item real; scope clean (no file undersrc/); commit hygiene, authorship and terminology clean.The gate assertion is not just reproducible, it is broad. Five independent mutations to
src/popup/views/confirmTx.js, each reverted:feeWei = gasCostWeitofeeWei = estimateWei— 17 and 22 die, exactly as reported.feeWei = 0n(gate ignores the fee) — 17 and 22 die.feeReserveWeitofeeEstimateWei(reserve collapsed onto estimate) — 16, 17, 20, 22 die; test 17's "this send is not in the gap" guard fires, so it refuses to pass vacuously when the fixture spread disappears.setVisible()collapsing space withdisplay:noneinstead of reserving it, i.e. the layout-shift class of #252 — 16, 17, 19, 20, 22, 23 die on the height assertions across both paths and all three transitions. The height is genuinely asserted, not merely printed. Incidentally the pending height under that mutant is 874.5625px, matching the figure measured by hand in the review of #197.ErrorCollector.expect()cannot mask a genuine error. Four probes: a secondconsole.errormatching the declared pattern in the same code path still fails its test (consumption is exactly one); an unrelated genuineconsole.errorinjected into the declaring test's own path still fails it; an expectation nothing matches fails its test (expected browser error(s) that never arrived); and an expectation declared in test 18 does not survive into test 19 —unmatchedExpectations()is called unconditionally after every test intests/e2e/run.js:1079and clears the list, so there is no forward leak.ALLOWED_ERRORS,TRAILING_WATCH_MSand the service-worker interception canary are untouched.Disclosures, none blocking. The fixture widens what the RPC stub answers without reporting:
eth_getBlockByNumbernow returns thelatestblock for any block parameter, andeth_getCodeis newly stubbed — previously both would have been reported as unstubbed methods. Fixture-shape choices, no outbound traffic escapes either way. The empty-array POST hole (#187) is unchanged, neither fixed nor worsened. Tracker CI status ignored per #220; host-onlyscript/lintnot held against this PR per #152.7e5d7cdcdetoecfddeb327ecfddeb327to5092cf162a