// A contract lookup on AddToken can answer after the user has left AddToken. // The token is still added, and the screen the user is on does not change // (https://git.eeqj.de/sneak/AutistMask/issues/603). An answer while AddToken // still shows goes to AddressDetail. Driven through the real popup over a // stored profile. const { bootPopup, cleanupPopup, unversionedValidProfile, TOKEN_ADDRESS, } = require("./support/popupBoot"); const TOKEN = { address: TOKEN_ADDRESS, symbol: "TST", decimals: 18, name: "Test Token", }; // A second contract address, typed after AddToken was opened again. const OTHER_TOKEN_ADDRESS = "0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"; afterEach(() => { cleanupPopup(); }); // The popup reopened onto AddressDetail, then AddToken opened from it with // TOKEN's contract address typed in. async function openAddToken() { const boot = await bootPopup( unversionedValidProfile({ currentView: "address", selectedWallet: 0, selectedAddress: 0, }), ); expect(boot.pageErrors).toEqual([]); await boot.click("btn-add-token"); expect(boot.visibleViews()).toEqual(["add-token"]); boot.node("add-token-address").value = TOKEN.address; return boot; } // Presses Add with a contract lookup that answers only when the function // returned here is called. That function waits for Add to finish. function addWithPendingLookup(boot) { const { lookupTokenInfo } = require("../src/shared/balances"); let answer; lookupTokenInfo.mockImplementationOnce( () => new Promise((resolve) => { answer = resolve; }), ); const adding = boot.click("btn-add-token-confirm"); return async () => { answer({ symbol: TOKEN.symbol, decimals: TOKEN.decimals, name: TOKEN.name, }); await adding; }; } test("an answer after the user opened Settings adds the token and Settings stays", async () => { const boot = await openAddToken(); const answerLookup = addWithPendingLookup(boot); await boot.click("btn-settings"); expect(boot.visibleViews()).toEqual(["settings"]); await answerLookup(); expect(boot.visibleViews()).toEqual(["settings"]); expect(boot.storage.read("autistmask").trackedTokens).toEqual([TOKEN]); }); test("Back onto AddToken after that answer shows no lookup status", async () => { const boot = await openAddToken(); const answerLookup = addWithPendingLookup(boot); expect(boot.text("add-token-info")).toBe("Looking up token..."); await boot.click("btn-settings"); await answerLookup(); await boot.click("btn-settings-back"); expect(boot.visibleViews()).toEqual(["add-token"]); expect(boot.text("add-token-info")).toBe(""); expect(boot.node("add-token-info").style.visibility).toBe("hidden"); }); test("an answer after AddToken was opened again adds the token and leaves AddToken and its status line as they are", async () => { const boot = await openAddToken(); const answerFirstLookup = addWithPendingLookup(boot); await boot.click("btn-add-token-back"); await boot.click("btn-add-token"); expect(boot.visibleViews()).toEqual(["add-token"]); boot.node("add-token-address").value = OTHER_TOKEN_ADDRESS; // The second lookup is never answered. addWithPendingLookup(boot); await answerFirstLookup(); expect(boot.visibleViews()).toEqual(["add-token"]); expect(boot.text("add-token-info")).toBe("Looking up token..."); expect(boot.storage.read("autistmask").trackedTokens).toEqual([TOKEN]); }); test("an answer while AddToken still shows goes to AddressDetail with the token listed", async () => { const boot = await openAddToken(); const answerLookup = addWithPendingLookup(boot); await answerLookup(); expect(boot.visibleViews()).toEqual(["address"]); expect(boot.node("address-balances").innerHTML).toContain("TST"); expect(boot.storage.read("autistmask").trackedTokens).toEqual([TOKEN]); });