Copies .dockerignore, .gitignore, .prettierignore, check.yml and REPO_POLICIES.md from sneak/prompts at dd4027b, keeping the repo's own entries (dist/, release/, yarn files) after the canonical content. The Dockerfile gets separate lint and test phases; its last stage depends on both, checks the git describe version and runs make build. script/lint, test, check, cibuild and docker are the canonical models. check-censored moves into the lint phase and test-verify-build into the test phase. fmt and fmt-check fall back to the nvm-installed node. The e2e image builds are uncached. Comments citing the old test caps or what runs a script are updated. Model: opus-5-5
77 lines
3.1 KiB
JavaScript
77 lines
3.1 KiB
JavaScript
// 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 60-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 =
|
|
'<iframe id="pwn" src="https://dapp.e2e.test/" ' +
|
|
'style="position:fixed;left:0;top:0;width:360px;height:600px;z-index:99999"></iframe>';
|
|
|
|
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("<iframe");
|
|
expect(html).toContain("<iframe");
|
|
});
|
|
|
|
test("caps the symbol before rendering it", () => {
|
|
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("<span>USDC</span>");
|
|
expect(html).toContain("<span>1.5000</span>");
|
|
expect(html).toContain('data-token="0xabc"');
|
|
});
|
|
|
|
// formatUsd() writes a value under a cent as "< $0.01".
|
|
test("escapes the USD value along with the symbol", () => {
|
|
const html = balanceLine("USDC", 0.001, 1, null);
|
|
expect(html).toContain("< $0.01");
|
|
expect(html).not.toContain("< $0.01");
|
|
});
|
|
});
|