// balanceLine() is the row that issue #307 was reported against: every // screen that lists a holding renders through it, and the symbol it renders // is whatever an ERC-20's symbol() returned. This asserts against the // string it emits, which is what gets assigned to innerHTML. // // The browser half of the same claim — that a real Chrome renders that // string as text and puts no iframe in the popup DOM — is in // tests/e2e/run.js. This half runs inside the 20-second make test cap. "use strict"; // helpers.js reaches for both at module scope through the modules it pulls // in. Neither is exercised by anything asserted here. global.chrome = { storage: { local: { get: () => Promise.resolve({}), set: () => Promise.resolve(), }, }, runtime: { sendMessage: () => {} }, }; global.document = { getElementById: () => null, createElement: () => ({ style: {}, classList: { toggle() {} } }), body: { prepend: () => {} }, addEventListener: () => {}, }; const { balanceLine } = require("../src/popup/views/helpers"); const { MAX_SYMBOL_LENGTH } = require("../src/shared/symbolDisplay"); // The payload from the issue's reproduction, verbatim. const HOSTILE_SYMBOL = ''; describe("balanceLine", () => { test("emits a hostile symbol as text, not as an element", () => { // Deliberately asserted on the escaping alone. The cap truncates // this payload before its id attribute, so an assertion about the // rest of the payload would pass on the cap and say nothing about // the escape. const html = balanceLine(HOSTILE_SYMBOL, 1, null, null); expect(html).not.toContain(" { const html = balanceLine("A".repeat(4096), 1, null, null); expect(html).toContain("A".repeat(MAX_SYMBOL_LENGTH - 1) + "…"); expect(html).not.toContain("A".repeat(MAX_SYMBOL_LENGTH + 1)); }); // The token id lands inside data-token="...", so a quote in it is a // way out of the attribute and into a new one. test("keeps a quote-bearing token id inside its attribute", () => { const html = balanceLine("TKN", 1, null, '" onclick="alert(1)'); expect(html).not.toContain('onclick="'); expect(html).toContain('data-token="" onclick="alert(1)"'); }); test("renders an ordinary holding unchanged", () => { const html = balanceLine("USDC", 1.5, null, "0xabc"); expect(html).toContain("USDC"); expect(html).toContain("1.5000"); expect(html).toContain('data-token="0xabc"'); }); });