// Tests for the dust threshold field in Settings (issue #233). // // Two halves: what the parse accepts, and what the settings view does with a // rejection. The view half runs against the real change handler with the DOM // helpers stubbed out, because the bug was not in the parse — it was that a // rejection said nothing. const { DUST_THRESHOLD_MESSAGE, parseDustThresholdGwei, } = require("../src/popup/dustThreshold"); describe("parsing the dust threshold", () => { test("accepts a whole number of gwei", () => { expect(parseDustThresholdGwei("100000")).toBe(100000); expect(parseDustThresholdGwei("1")).toBe(1); }); // Zero is a real setting, not an empty field: it hides nothing. test("accepts zero", () => { expect(parseDustThresholdGwei("0")).toBe(0); }); test("accepts surrounding whitespace", () => { expect(parseDustThresholdGwei(" 250 ")).toBe(250); }); test("rejects an empty field", () => { expect(parseDustThresholdGwei("")).toBe(null); expect(parseDustThresholdGwei(" ")).toBe(null); }); test("rejects a negative threshold", () => { expect(parseDustThresholdGwei("-1")).toBe(null); }); // parseInt used to read this as 1, which is not what was typed. test("rejects a fractional value", () => { expect(parseDustThresholdGwei("1.5")).toBe(null); expect(parseDustThresholdGwei("1.0")).toBe(null); }); // parseInt used to read this as 100. The unit is printed beside the // field already. test("rejects a value carrying its unit", () => { expect(parseDustThresholdGwei("100 gwei")).toBe(null); }); // Number() reads this as 16. Storing 16 for a field that was told to // want a whole number of gwei would be the same silent substitution the // message exists to end. test("rejects hex notation", () => { expect(parseDustThresholdGwei("0x10")).toBe(null); }); // Number() reads this as 1000. test("rejects exponent notation", () => { expect(parseDustThresholdGwei("1e3")).toBe(null); }); test("rejects other non-numeric input", () => { expect(parseDustThresholdGwei("lots")).toBe(null); expect(parseDustThresholdGwei("+5")).toBe(null); expect(parseDustThresholdGwei("Infinity")).toBe(null); expect(parseDustThresholdGwei(undefined)).toBe(null); expect(parseDustThresholdGwei(5)).toBe(null); }); // Beyond 2^53 the digits would round on the way in, so the stored // threshold would not be the one typed. test("rejects a value too large to hold exactly", () => { expect(parseDustThresholdGwei("9007199254740993")).toBe(null); }); }); describe("the rejection message", () => { // README, Language & Labeling: error messages are full sentences. test("is a full sentence naming the constraint", () => { expect(DUST_THRESHOLD_MESSAGE).toMatch(/^[A-Z].*\.$/); expect(DUST_THRESHOLD_MESSAGE).toContain("whole number of gwei"); expect(DUST_THRESHOLD_MESSAGE).toContain("zero or greater"); }); }); describe("showing the message shifts no layout", () => { const fs = require("fs"); const path = require("path"); const POPUP_HTML = fs.readFileSync( path.join(__dirname, "..", "src", "popup", "index.html"), "utf8", ); // README, No Layout Shift: the message goes to the always-present flash // line, whose height is reserved whether or not it holds text. Nothing // is inserted next to the field itself. test("the flash line is always present with its height reserved", () => { const flashLine = POPUP_HTML.match( /