fix: the address and token screens and the address scan no longer log requests a popup reload cancels (closes #475)
The transaction lists on the address and token screens, the address scan after a wallet is created, and the endpoint checks in Settings now check the signal the popup aborts on pagehide before reporting a failed request, as the home screen and the balance refresh already do. scanForAddresses() takes the signal ahead of its gap limit. End-to-end tests reload the popup on the address screen with Blockscout held, and during the address scan with its requests held. Jest tests show the transaction lists, the scan and the Settings checks report a real failure and stay silent once the popup has closed. The transaction detail and confirmation screens are left out: they do not keep the popup context. Model: opus-5-5
This commit is contained in:
@@ -1,13 +1,19 @@
|
||||
// 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).
|
||||
// The balance refresh, and the address scan after a wallet is created, do not
|
||||
// report a request the popup's own closing cancelled, and still report one
|
||||
// that failed while the popup was open
|
||||
// (https://git.eeqj.de/sneak/AutistMask/issues/218,
|
||||
// https://git.eeqj.de/sneak/AutistMask/issues/475).
|
||||
//
|
||||
// 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 { refreshBalances, scanForAddresses } = require("../src/shared/balances");
|
||||
const {
|
||||
generateMnemonic,
|
||||
hdWalletFromMnemonic,
|
||||
} = require("../src/shared/wallet");
|
||||
|
||||
const RPC_URL = "https://rpc.example.invalid";
|
||||
const EXPLORER_URL = "https://explorer.example.invalid/api/v2";
|
||||
@@ -24,8 +30,9 @@ beforeEach(() => {
|
||||
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.
|
||||
// The RPC calls (ETH balance, ENS name, and the scan's balance and
|
||||
// transaction count) and the explorer request (token balances) all fail
|
||||
// the same way.
|
||||
FetchRequest.registerGetUrl(failedToFetch);
|
||||
globalThis.fetch = jest.fn(failedToFetch);
|
||||
});
|
||||
@@ -65,3 +72,24 @@ test("a failure once the popup has closed is not", async () => {
|
||||
await refresh(pageClosed.signal);
|
||||
expect(logged).toEqual([]);
|
||||
});
|
||||
|
||||
function scan(signal) {
|
||||
// What the scan found is logged at info level, which is not under test.
|
||||
jest.spyOn(console, "log").mockImplementation(() => {});
|
||||
const { xpub } = hdWalletFromMnemonic(generateMnemonic());
|
||||
return scanForAddresses(xpub, RPC_URL, "mainnet", signal);
|
||||
}
|
||||
|
||||
test("a scan failure while the popup is open is reported", async () => {
|
||||
await scan(new AbortController().signal);
|
||||
expect(
|
||||
logged.some((line) => line.includes("scanForAddresses check failed")),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test("a scan failure once the popup has closed is not", async () => {
|
||||
const pageClosed = new AbortController();
|
||||
pageClosed.abort();
|
||||
await scan(pageClosed.signal);
|
||||
expect(logged).toEqual([]);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user