fix: a popup reload mid-refresh no longer logs the requests it cancels (closes #218)
Chrome cancels a closing popup's open requests just after pagehide, and in the page a cancelled fetch() fails with the same "Failed to fetch" as a server that cannot be reached. The home screen's transaction list and the balance refresh logged an error for each, and the e2e suite failed on them. The popup now aborts an AbortController on pagehide, and those failure reports check its signal first. End-to-end tests reload the popup with Blockscout held and require nothing logged, and fail the transaction list for real and require the failure reported; a unit test covers the balance refresh. The address and token screens and the new-wallet address scan are #475. Model: opus-5-5
This commit was merged in pull request #476.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
// The balance refresh does not report a request the popup's own closing
|
||||
// cancelled, and still reports one that failed while the popup was open
|
||||
// (https://git.eeqj.de/sneak/AutistMask/issues/218).
|
||||
//
|
||||
// In the popup a cancelled fetch() fails with the same "Failed to fetch" as a
|
||||
// server that cannot be reached, so every request here fails that way, and
|
||||
// only the signal the popup aborts on pagehide tells the two cases apart.
|
||||
|
||||
const { FetchRequest } = require("ethers");
|
||||
const { refreshBalances } = require("../src/shared/balances");
|
||||
|
||||
const RPC_URL = "https://rpc.example.invalid";
|
||||
const EXPLORER_URL = "https://explorer.example.invalid/api/v2";
|
||||
const ADDRESS = "0x1111111111111111111111111111111111111111";
|
||||
|
||||
const realFetch = globalThis.fetch;
|
||||
let logged;
|
||||
|
||||
beforeEach(() => {
|
||||
logged = [];
|
||||
jest.spyOn(console, "error").mockImplementation((...args) => {
|
||||
logged.push(args.map(String).join(" "));
|
||||
});
|
||||
const failedToFetch = async () => {
|
||||
throw new TypeError("Failed to fetch");
|
||||
};
|
||||
// The RPC calls (ETH balance, ENS name) and the explorer request (token
|
||||
// balances) all fail the same way.
|
||||
FetchRequest.registerGetUrl(failedToFetch);
|
||||
globalThis.fetch = jest.fn(failedToFetch);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
FetchRequest.registerGetUrl(FetchRequest.createGetUrlFunc());
|
||||
globalThis.fetch = realFetch;
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
function refresh(signal) {
|
||||
const wallets = [{ addresses: [{ address: ADDRESS }] }];
|
||||
return refreshBalances(
|
||||
wallets,
|
||||
RPC_URL,
|
||||
EXPLORER_URL,
|
||||
[],
|
||||
"mainnet",
|
||||
signal,
|
||||
);
|
||||
}
|
||||
|
||||
test("a failure while the popup is open is reported", async () => {
|
||||
await refresh(new AbortController().signal);
|
||||
for (const label of [
|
||||
"ETH balance failed",
|
||||
"ENS reverse failed",
|
||||
"fetchTokenBalances failed: Failed to fetch",
|
||||
]) {
|
||||
expect(logged.some((line) => line.includes(label))).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
test("a failure once the popup has closed is not", async () => {
|
||||
const pageClosed = new AbortController();
|
||||
pageClosed.abort();
|
||||
await refresh(pageClosed.signal);
|
||||
expect(logged).toEqual([]);
|
||||
});
|
||||
Reference in New Issue
Block a user