Files
AutistMask/tests/tokenLookupCancelled.test.js
T
clawbot f8f2461354
check / check (push) Successful in 1m57s
e2e / e2e-chrome (push) Successful in 4m53s
e2e / e2e-firefox (push) Successful in 2m31s
fix: a popup reload no longer logs the requests it cancels, except on the transaction detail and confirmation screens (closes #475)
The transaction lists and ENS name lookups on the address and token
screens, the address scan after a wallet is created, the endpoint checks
in Settings, the wait screen's receipt check, the Send screen's Max fee
estimate and the token lookup on both add-token screens now check the
signal the popup aborts on pagehide before reporting a failed request.
scanForAddresses(), resolveEnsNames() and lookupTokenInfo() take the
signal.

End-to-end tests reload the popup on the address screen and during the
address scan with their requests held. Jest tests show each of these
reports a real failure and stays silent once the popup has closed. The
transaction detail and confirmation screens are left out: they discard
the popup context that carries the signal.

Model: opus-5-5
2026-10-06 12:34:54 +00:00

104 lines
3.1 KiB
JavaScript

// The two add-token screens do not report a token lookup the popup's own
// closing cancelled, and still report one that failed while the popup was open
// (https://git.eeqj.de/sneak/AutistMask/issues/475).
//
// In the popup a cancelled request fails with the same "Failed to fetch" as a
// server that cannot be reached, so every RPC request here fails that way, and
// only the signal the popup aborts on pagehide tells the two cases apart. The
// real lookupTokenInfo() runs, which logs a failed lookup itself before the
// screen does. Driven against the fake elements tests/flashLine.test.js uses.
const { FetchRequest } = require("ethers");
const ADDRESS = "0x1111111111111111111111111111111111111111";
let elements;
function fakeElement() {
return {
value: "",
textContent: "",
style: {},
listeners: {},
addEventListener(event, handler) {
this.listeners[event] = handler;
},
};
}
// Stands in for document.getElementById(): one fake element per id.
function element(id) {
return (elements[id] ||= fakeElement());
}
jest.doMock("../src/popup/views/helpers", () => ({
$: element,
showView: () => {},
showFlash: () => {},
escapeHtml: (s) => s,
goBack: () => {},
}));
// state.js reads chrome.storage.local at load.
globalThis.chrome = {
storage: { local: { get: async () => ({}), set: async () => {} } },
};
const { state } = require("../src/shared/state");
let logged;
beforeEach(() => {
elements = {};
logged = [];
state.trackedTokens = [];
jest.spyOn(console, "error").mockImplementation((...args) => {
logged.push(args.map(String).join(" "));
});
FetchRequest.registerGetUrl(async () => {
throw new TypeError("Failed to fetch");
});
});
afterEach(() => {
FetchRequest.registerGetUrl(FetchRequest.createGetUrlFunc());
jest.restoreAllMocks();
});
describe.each([
["addToken", "add-token-address", "btn-add-token-confirm"],
[
"settingsAddToken",
"settings-addtoken-address",
"btn-settings-addtoken-manual",
],
])("looking up a token on %s", (view, field, button) => {
// Clicks the screen's add button for ADDRESS and waits for the lookup.
async function add(pageClosed) {
require("../src/popup/views/" + view).init({
doRefreshAndRender: () => {},
pageClosed,
});
element(field).value = ADDRESS;
await element(button).listeners.click();
}
test("a failure while the popup is open is reported", async () => {
await add(new AbortController().signal);
expect(logged).toHaveLength(2);
expect(logged[0]).toContain("symbol() failed:");
expect(logged[1]).toBe(
"[AutistMask] Adding token failed for " +
ADDRESS +
" Not a valid ERC-20 token (symbol() failed).",
);
});
test("a failure once the popup has closed is not", async () => {
const pageClosed = new AbortController();
pageClosed.abort();
await add(pageClosed.signal);
expect(logged).toEqual([]);
});
});