test: the popup boot in the jest suite sends no request to the internet #597
@@ -9,6 +9,7 @@ const {
|
||||
bootPopup,
|
||||
cleanupPopup,
|
||||
unversionedValidProfile,
|
||||
ADDRESS,
|
||||
} = require("./support/popupBoot");
|
||||
|
||||
const FLASH_MS = 10;
|
||||
@@ -40,3 +41,47 @@ test("a flash message's timer does not fire after cleanupPopup()", async () => {
|
||||
|
||||
await wait(FLASH_MS * 5);
|
||||
});
|
||||
|
||||
// A boot onto a screen that sends a request no mocked module answers: that
|
||||
// request reaches the boot's fetch() stub, never the internet
|
||||
// (https://git.eeqj.de/sneak/AutistMask/issues/559).
|
||||
function restoringOnto(view, viewData) {
|
||||
return unversionedValidProfile({
|
||||
currentView: view,
|
||||
selectedWallet: 0,
|
||||
selectedAddress: 0,
|
||||
viewStack: ["main"],
|
||||
viewData,
|
||||
});
|
||||
}
|
||||
|
||||
test("the transaction screen's Blockscout request reaches the stub", async () => {
|
||||
const page = await bootPopup(
|
||||
restoringOnto("transaction", {
|
||||
tx: { hash: "0x1", from: ADDRESS, to: ADDRESS },
|
||||
}),
|
||||
);
|
||||
|
||||
expect(page.visibleViews()).toEqual(["transaction"]);
|
||||
expect(globalThis.fetch.mock.calls.map((call) => call[0])).toEqual([
|
||||
"https://eth.blockscout.com/api/v2/transactions/0x1",
|
||||
]);
|
||||
});
|
||||
|
||||
test("the confirmation screen's Etherscan lookup reaches the stub", async () => {
|
||||
const page = await bootPopup(
|
||||
restoringOnto("confirm-tx", {
|
||||
pendingTx: {
|
||||
token: "ETH",
|
||||
from: ADDRESS,
|
||||
to: ADDRESS,
|
||||
amount: "1",
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
expect(page.visibleViews()).toEqual(["confirm-tx"]);
|
||||
expect(globalThis.fetch.mock.calls.map((call) => call[0])).toEqual([
|
||||
"https://etherscan.io/address/" + ADDRESS,
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -45,6 +45,7 @@ const realSetInterval = globalThis.setInterval;
|
||||
const realClearInterval = globalThis.clearInterval;
|
||||
const realSetTimeout = globalThis.setTimeout;
|
||||
const realClearTimeout = globalThis.clearTimeout;
|
||||
const realFetch = globalThis.fetch;
|
||||
|
||||
// Every timeout set since the last cleanupPopup() that has neither fired nor
|
||||
// been cleared. cleanupPopup() clears them all.
|
||||
@@ -260,8 +261,14 @@ async function settle() {
|
||||
async function bootPopup(stored, options) {
|
||||
jest.resetModules();
|
||||
|
||||
// The three modules that reach the network. None is on the path under
|
||||
// test; all would make the suite hit the internet.
|
||||
// The RPC requests made through src/shared/balances.js go through Node's
|
||||
// own http and https modules, not fetch(), so the fetch() stub below would
|
||||
// not stop them, which is why that module stays mocked.
|
||||
// src/shared/prices.js and src/shared/transactions.js send their requests
|
||||
// through fetch(), and their mocks answer with no prices and no
|
||||
// transactions. Every request the page still sends, such as the
|
||||
// transaction screen's Blockscout lookup and the Etherscan lookup in
|
||||
// src/shared/etherscanLabels.js, meets the fetch() stub.
|
||||
jest.doMock("../../src/shared/prices", () => ({
|
||||
prices: {},
|
||||
refreshPrices: jest.fn(async () => {}),
|
||||
@@ -334,6 +341,12 @@ async function bootPopup(stored, options) {
|
||||
windowListeners[name].push(fn);
|
||||
},
|
||||
};
|
||||
// Every fetch() the page makes fails, as it does elsewhere in the suite,
|
||||
// instead of reaching the internet. A new stub per boot, so the calls it
|
||||
// records start with that boot. Put back by cleanupPopup().
|
||||
globalThis.fetch = jest.fn(() => {
|
||||
throw new Error("tests must not perform network requests");
|
||||
});
|
||||
// The ten-second refresh init() starts, and a transaction wait's timers,
|
||||
// would outlive the test. So every interval is recorded rather than
|
||||
// started, clearInterval() removes it as a browser would, and tick() below
|
||||
@@ -435,6 +448,7 @@ function cleanupPopup() {
|
||||
pendingTimeouts.clear();
|
||||
globalThis.setTimeout = realSetTimeout;
|
||||
globalThis.clearTimeout = realClearTimeout;
|
||||
globalThis.fetch = realFetch;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
Reference in New Issue
Block a user