test: drive the StateRecovery screen in both browser suites (closes #361)
A stored record a newer build wrote opens the popup on the recovery screen. Export Saved Data puts that record, exactly as stored, in the text box; a near-miss confirmation phrase erases nothing; the exact phrase erases it and reloads into Welcome. Chrome and Firefox run the same four cases, each under its shipped CSP. They run before any wallet exists: with no wallet nothing saves on a timer, so no save can write a good record over the unreadable one, and the erase leaves the popup on Welcome for wallet creation. If any of them fails, the last one removes the record so later tests still start from Welcome. Model: opus-5-5
This commit was merged in pull request #463.
This commit is contained in:
+123
-2
@@ -9,6 +9,8 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { isDeepStrictEqual } = require("util");
|
||||
|
||||
const {
|
||||
Transaction,
|
||||
formatEther,
|
||||
@@ -47,6 +49,10 @@ const {
|
||||
} = require("./network");
|
||||
const { DUST_THRESHOLD_MESSAGE } = require("../../src/popup/dustThreshold");
|
||||
const { NETWORKS } = require("../../src/shared/networks");
|
||||
const {
|
||||
STATE_SCHEMA_VERSION,
|
||||
stateProblem,
|
||||
} = require("../../src/shared/stateSchema");
|
||||
|
||||
const TEST_TIMEOUT_MS = 120000;
|
||||
|
||||
@@ -115,8 +121,8 @@ test("the popup is drawn in the monospace font it declares (#418)", async (env)
|
||||
// so a recurrence fails whichever test it lands in rather than being
|
||||
// tolerated. Since libsodium's WASM module is embedded in the bundle and
|
||||
// needs no fetch, a realm that compiles WASM is a realm where libsodium
|
||||
// takes the WASM path, and the next test drives a real vault encryption
|
||||
// through it.
|
||||
// takes the WASM path, and wallet creation below drives a real vault
|
||||
// encryption through it.
|
||||
test("the popup compiles WebAssembly under the shipped CSP (#182)", async (env) => {
|
||||
const ok = await pageCompilesWasm(env.page);
|
||||
assert(
|
||||
@@ -128,6 +134,121 @@ test("the popup compiles WebAssembly under the shipped CSP (#182)", async (env)
|
||||
);
|
||||
});
|
||||
|
||||
// The screen the popup shows when it cannot read the stored profile
|
||||
// (src/popup/views/stateRecovery.js), driven under the shipped CSP (#361).
|
||||
//
|
||||
// These run before any wallet exists, on purpose. With no wallet neither the
|
||||
// popup nor the background refreshes balances, so nothing saves while they run
|
||||
// and no save can write a good record over the unreadable one. The last of
|
||||
// them erases it, which leaves the popup on Welcome for wallet creation.
|
||||
|
||||
// A profile a newer build wrote: a wallet with its encrypted secret, under a
|
||||
// schema version this build refuses to read.
|
||||
const UNREADABLE_RECORD = {
|
||||
schemaVersion: STATE_SCHEMA_VERSION + 1,
|
||||
wallets: [
|
||||
{
|
||||
type: "hd",
|
||||
name: "Main",
|
||||
xpub: "xpub-written-by-a-newer-build",
|
||||
encryptedSecret: "ciphertext-written-by-a-newer-build",
|
||||
nextIndex: 1,
|
||||
addresses: [{ address: STUB_COUNTERPARTY }],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// The whole stored record, read out of extension storage.
|
||||
function storedRecord(page) {
|
||||
return page.evaluate(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
chrome.storage.local.get("autistmask", (r) =>
|
||||
resolve(r.autistmask),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
test("an unreadable stored record opens the popup on the recovery screen (#361)", async (env) => {
|
||||
// The popup the first test opened saves once, as it shows Welcome. Stored
|
||||
// before that save lands, the record would be written over.
|
||||
await waitForPersisted(
|
||||
env.page,
|
||||
"currentView",
|
||||
"welcome",
|
||||
"before the unreadable record is stored",
|
||||
);
|
||||
await env.page.evaluate(
|
||||
(record) =>
|
||||
new Promise((resolve) => {
|
||||
chrome.storage.local.set({ autistmask: record }, resolve);
|
||||
}),
|
||||
UNREADABLE_RECORD,
|
||||
);
|
||||
await env.page.close();
|
||||
|
||||
env.errors.expect(
|
||||
"the recovery screen logging the problem as it goes up",
|
||||
/state is unusable, showing the recovery screen/,
|
||||
);
|
||||
env.page = await openPopup(env.ctx, env.popupUrl);
|
||||
await visible(env.page, "#view-state-recovery");
|
||||
const problem = await env.page.textContent("#state-recovery-problem");
|
||||
assert(
|
||||
problem === stateProblem(UNREADABLE_RECORD),
|
||||
"the recovery screen names the problem as " + JSON.stringify(problem),
|
||||
);
|
||||
});
|
||||
|
||||
test("Export Saved Data shows the stored record verbatim (#361)", async (env) => {
|
||||
await env.page.click("#btn-state-recovery-export");
|
||||
await visible(env.page, "#state-recovery-blob");
|
||||
const exported = await env.page.inputValue("#state-recovery-blob");
|
||||
assert(exported !== "", "Export Saved Data left the text box empty");
|
||||
assert(
|
||||
isDeepStrictEqual(JSON.parse(exported), UNREADABLE_RECORD),
|
||||
"the text box does not hold the stored record: " + exported,
|
||||
);
|
||||
});
|
||||
|
||||
test("a near-miss confirmation phrase erases nothing (#361)", async (env) => {
|
||||
await env.page.fill("#state-recovery-reset-input", "ERASE MY WALLETS");
|
||||
await env.page.click("#btn-state-recovery-reset");
|
||||
await env.page.waitForFunction(
|
||||
() =>
|
||||
document.getElementById("state-recovery-flash").textContent ===
|
||||
"Type ERASE MY WALLET to confirm. Nothing was erased.",
|
||||
);
|
||||
const stored = await storedRecord(env.page);
|
||||
assert(
|
||||
isDeepStrictEqual(stored, UNREADABLE_RECORD),
|
||||
"the stored record changed: " + JSON.stringify(stored),
|
||||
);
|
||||
});
|
||||
|
||||
test("the exact confirmation phrase erases the record and reloads into Welcome (#361)", async (env) => {
|
||||
try {
|
||||
await env.page.fill("#state-recovery-reset-input", "ERASE MY WALLET");
|
||||
await env.page.click("#btn-state-recovery-reset");
|
||||
// Welcome is the proof of the erase: the record still stored would
|
||||
// put the recovery screen up again, and its wallet would open Home.
|
||||
await visible(env.page, "#view-welcome");
|
||||
} finally {
|
||||
// Whatever failed in these four tests, wallet creation starts from
|
||||
// Welcome. The record left stored would fail every test after this.
|
||||
if (!(await env.page.isVisible("#view-welcome"))) {
|
||||
await env.page.evaluate(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
chrome.storage.local.remove("autistmask", resolve);
|
||||
}),
|
||||
);
|
||||
await env.page.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test("wallet creation through the UI reaches the main view", async (env) => {
|
||||
env.phrase = await createWallet(env.page);
|
||||
assert(
|
||||
|
||||
Reference in New Issue
Block a user