1 Commits
Author SHA1 Message Date
sneak f123d45ec1 docs: README end-to-end limits match what the browser suites do (closes #293)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
The window.close override the issue named was removed with #275, so it
needs no entry. Every other place either suite changes or works around
the shipped extension is now listed: the popup loaded in a tab, Chrome's
wait before each site-connection request, its recording wrapper and click
listener, its clipboard grant, two layout tests that write into the page,
the forced leave during a decrypt, and Firefox's setting that forces the
site-connection prompt into a window. Firefox's tolerated error is
described as the leftover it is, with #487 to remove it; the phishing
blocklist is no longer listed as a failing fetch, and two stale figures
are corrected.

Model: opus-5-5
2026-10-07 02:36:29 +00:00
6 changed files with 20 additions and 80 deletions
+10 -14
View File
@@ -634,12 +634,11 @@ Three limits are worth knowing, all real differences from the Chrome suite:
and silently evicts the oldest, so more than 250 console messages between two
drains destroys the excess unread. 400 throws inside one step are reported as
exactly the newest 250, three runs running. That buffer is shared with
Firefox's own console noise; a clean run, measured when the suite had three
steps (popup load, wallet creation and Add Token), peaked at 4 of 250 at the
install drain and 0 at every later drain, but a step that logs heavily could
evict unread errors. What poll-based costs is location, not coverage: an error
cannot be placed within a step the way the Chrome suite's `pageerror` events
place it.
Firefox's own console noise; a clean run of the suite's first three steps,
measured before the rest were added, peaked at 4 of 250 at the install drain
and 0 at every later drain, but a step that logs heavily could evict unread
errors. What poll-based costs is location, not coverage: an error cannot be
placed within a step the way the Chrome suite's `pageerror` events place it.
- **Almost nothing is stubbed, which inverts the coverage of network-dependent
code.** The container still runs with `--network none`, so the run is offline
and no request can escape. The one thing it can reach is the loopback fixture
@@ -1314,14 +1313,11 @@ behind a "···" menu.
Navigation uses a stack model (like iOS): each forward action pushes the current
screen onto `state.viewStack`, and "Back" pops it (`pushCurrentView()` and
`goBack()` in `src/popup/views/helpers.js`). "Back" skips an entry for the
screen already showing: ShowRecoveryPhrase and the two delete screens take
themselves off the stack when left, so the Settings gear on one of them leaves
Settings under Settings, and "Back" from there goes to the screen before
Settings. The root screen is either Welcome (no wallets) or Home (has wallets).
Each screen below gives its view id in parentheses; the registry of view ids is
the `VIEWS` array in `src/popup/views/helpers.js`, and the markup for a screen
is the element with id `view-` plus that view id in `src/popup/index.html`.
`goBack()` in `src/popup/views/helpers.js`). The root screen is either Welcome
(no wallets) or Home (has wallets). Each screen below gives its view id in
parentheses; the registry of view ids is the `VIEWS` array in
`src/popup/views/helpers.js`, and the markup for a screen is the element with id
`view-` plus that view id in `src/popup/index.html`.
Three elements sit outside the screens and are present on all of them: the title
bar ("AutistMask by @sneak" plus the Settings gear), the flash message line
-9
View File
@@ -59,15 +59,6 @@ but the review is broader than any of them.
[#487](https://git.eeqj.de/sneak/AutistMask/issues/487)), the phishing
blocklist the extension no longer fetches, and two stale figures.
- 2026-10-07: Back from Settings no longer shows Settings again after the
settings gear was pressed on the recovery phrase or a delete wallet screen
opened from Settings, with or without a reopen in between
([#481](https://git.eeqj.de/sneak/AutistMask/issues/481)). Those screens take
themselves off the Back stack when left, which leaves Settings under Settings;
`goBack()` now skips an entry for the screen already showing.
`tests/showPhrase.test.js`, `tests/deleteWalletLostPassword.test.js` and
`tests/backNavigation.test.js` drive each path.
- 2026-10-07: `script/discard-dist-on-failure` returns the failed step's own
exit status even when it cannot write its message, to a closed stderr or to a
pipe nobody reads any more
+2 -13
View File
@@ -216,21 +216,10 @@ function pushCurrentView() {
// Pop the navigation stack and show the previous view. If the stack
// is empty, fall back to the main (home) view.
//
// An entry for the view already showing is skipped: landing on it would
// make Back seem to do nothing. Settings, the recovery phrase or delete
// wallet screen, then the gear leaves Settings under Settings, because that
// screen takes itself off the stack when left, and a reopened popup cuts it
// off the restored stack the same way
// (https://git.eeqj.de/sneak/AutistMask/issues/481).
function goBack() {
const stack = state.viewStack;
while (stack.length > 0 && stack[stack.length - 1] === state.currentView) {
stack.pop();
}
let target;
if (stack.length > 0) {
target = stack.pop();
if (state.viewStack.length > 0) {
target = state.viewStack.pop();
} else {
target = "main";
}
-18
View File
@@ -52,7 +52,6 @@ const {
resetRenderedViews,
} = require("../src/popup/viewRouter");
const { state } = require("../src/shared/state");
const { restorableStack } = require("../src/shared/persistedState");
const ADDRESS = "0x1111111111111111111111111111111111111111";
const TOKEN = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48";
@@ -210,23 +209,6 @@ describe("Back onto a view the reopened popup never rendered", () => {
});
});
// https://git.eeqj.de/sneak/AutistMask/issues/481. Settings, the recovery
// phrase or delete wallet screen, the gear, then a reopen: the restored stack
// is cut at the screen the gear left, which leaves Settings under the Settings
// the popup reopens onto.
describe("Back from Settings reopened over its own entry", () => {
test.each(["show-phrase", "delete-wallet-confirm"])(
"goes to the screen under it after leaving %s",
(left) => {
const stored = ["main", "settings", left];
reopenedOn("settings", restorableStack(stored, "settings"));
goBack();
expect(calls).toEqual(["main"]);
expect(state.currentView).toBe("main");
},
);
});
// The guards are restoreView()'s, so a popped view whose backing data is
// gone lands on Home rather than on an empty template.
describe("Back onto a view whose backing data is gone", () => {
+5 -7
View File
@@ -618,11 +618,9 @@ describe("the password route's confirm button", () => {
// https://git.eeqj.de/sneak/AutistMask/issues/480: leaving either delete
// screen drops its wallet selection, so Back onto one showed a screen whose
// button could only answer "No wallet selected for deletion." Taking the
// screen off the stack leaves Settings under Settings, and Back must not land
// there either (https://git.eeqj.de/sneak/AutistMask/issues/481).
// button could only answer "No wallet selected for deletion."
describe("Back from Settings after leaving by the settings gear", () => {
test("goes past the delete screen to the screen under Settings", () => {
test("does not land on the delete screen", () => {
const { helpers, deleteWallet, state } = load();
deleteWallet.show(1);
// The settings gear: push the current view, then show Settings.
@@ -631,10 +629,10 @@ describe("Back from Settings after leaving by the settings gear", () => {
expect(state.viewStack).toEqual(["main", "settings"]);
helpers.goBack();
expect(state.currentView).toBe("main");
expect(state.currentView).not.toBe("delete-wallet-confirm");
});
test("goes past the lost-password screen to the screen under Settings", async () => {
test("does not land on the lost-password screen", async () => {
const { helpers, deleteWallet, state } = load();
await openLostPassword(deleteWallet, 1);
// The settings gear: push the current view, then show Settings.
@@ -643,7 +641,7 @@ describe("Back from Settings after leaving by the settings gear", () => {
expect(state.viewStack).toEqual(["main", "settings"]);
helpers.goBack();
expect(state.currentView).toBe("main");
expect(state.currentView).not.toBe(VIEW);
});
// The lost-password screen's own Back is "Back returns to the delete
+3 -19
View File
@@ -131,10 +131,8 @@ describe("Back from Settings after leaving by the settings gear", () => {
// https://git.eeqj.de/sneak/AutistMask/issues/461: leaving drops the
// wallet selection, so Back onto this screen showed a password prompt
// that could only answer "No wallet is selected." Taking the screen off
// the stack leaves Settings under Settings, and Back must not land there
// either (https://git.eeqj.de/sneak/AutistMask/issues/481).
test("goes to the screen under Settings", () => {
// that could only answer "No wallet is selected."
test("does not land on the recovery phrase screen", () => {
const { helpers, state, showPhrase } = load();
// Opened from the wallet list in Settings, then left by the gear:
@@ -145,21 +143,7 @@ describe("Back from Settings after leaving by the settings gear", () => {
expect(state.viewStack).toEqual(["main", "settings"]);
helpers.goBack();
expect(state.currentView).toBe("main");
});
// Each round trip leaves one more Settings under Settings.
test("goes to the screen under Settings after two round trips", () => {
const { helpers, state, showPhrase } = load();
for (let i = 0; i < 2; i++) {
showPhrase.show(0);
helpers.pushCurrentView();
helpers.showView("settings");
}
expect(state.viewStack).toEqual(["main", "settings", "settings"]);
helpers.goBack();
expect(state.currentView).toBe("main");
expect(state.currentView).not.toBe(SHOW_PHRASE_VIEW);
});
// This Back takes Settings off the stack before the screen is left, so