fix: move the UTC Timestamps checkbox into the Display well (closes #212)
Some checks failed
check / check (push) Has been cancelled
Some checks failed
check / check (push) Has been cancelled
The `settings-utc-timestamps` checkbox sat inside the Token Spam Protection
well, immediately after the dust-threshold input. It is a display preference
and has nothing to do with spam filtering, so it now renders in the Display
well next to the theme selector.
Markup move only. The checkbox is wired by id — `$("settings-utc-timestamps")`
in `src/popup/views/settings.js`, where `$` is `document.getElementById` — for
both the initial `checked` assignment and the `change` handler, so nothing in
the wiring depends on the element's parent or siblings. `state.utcTimestamps`,
`saveState`/`loadState` and the `helpers.js` formatting path are untouched.
`tests/settingsUtcTimestamps.test.js` pins both halves down: the checkbox
appears exactly once and inside the Display well rather than the spam well,
and the setting still round-trips through storage.
This commit is contained in:
@@ -680,8 +680,8 @@ screen, including ExportPrivKey, falls back to Home.
|
|||||||
`[x]` delete button, plus a "+ Add wallet" button
|
`[x]` delete button, plus a "+ Add wallet" button
|
||||||
- Tracked Tokens: one row per tracked token with an `[x]` remove button,
|
- Tracked Tokens: one row per tracked token with an `[x]` remove button,
|
||||||
plus a "+ Add token" button
|
plus a "+ Add token" button
|
||||||
- Display: "Show tracked tokens with zero balance" checkbox and a Theme
|
- Display: "Show tracked tokens with zero balance" checkbox, "UTC
|
||||||
selector (System / Light / Dark)
|
Timestamps" checkbox, and a Theme selector (System / Light / Dark)
|
||||||
- Network: network selector (Ethereum Mainnet / Sepolia Testnet); switching
|
- Network: network selector (Ethereum Mainnet / Sepolia Testnet); switching
|
||||||
resets the RPC and Blockscout endpoints to that network's defaults
|
resets the RPC and Blockscout endpoints to that network's defaults
|
||||||
- Ethereum RPC: endpoint URL input + "Save" button (validated against
|
- Ethereum RPC: endpoint URL input + "Save" button (validated against
|
||||||
@@ -692,7 +692,6 @@ screen, including ExportPrivKey, falls back to Home.
|
|||||||
- "Hide tokens with fewer than 1,000 holders" checkbox
|
- "Hide tokens with fewer than 1,000 holders" checkbox
|
||||||
- "Hide transactions from detected fraud contracts" checkbox
|
- "Hide transactions from detected fraud contracts" checkbox
|
||||||
- "Hide dust transactions below N gwei" checkbox + threshold input
|
- "Hide dust transactions below N gwei" checkbox + threshold input
|
||||||
- "UTC Timestamps" checkbox
|
|
||||||
- Allowed Sites: list with remove buttons
|
- Allowed Sites: list with remove buttons
|
||||||
- Denied Sites: list with remove buttons
|
- Denied Sites: list with remove buttons
|
||||||
- About: project link, license, author, version, release date, and the
|
- About: project link, license, author, version, release date, and the
|
||||||
|
|||||||
3
TODO.md
3
TODO.md
@@ -44,6 +44,9 @@ undefined identifiers, which is how
|
|||||||
|
|
||||||
# Completed Steps
|
# Completed Steps
|
||||||
|
|
||||||
|
- 2026-08-11: UTC Timestamps checkbox moved from the Token Spam Protection well
|
||||||
|
into Display, next to the theme selector
|
||||||
|
([#212](https://git.eeqj.de/sneak/AutistMask/issues/212)).
|
||||||
- 2026-08-11: README Screen Map rebuilt from the code — every screen, element
|
- 2026-08-11: README Screen Map rebuilt from the code — every screen, element
|
||||||
and transition re-verified against `src/popup/`
|
and transition re-verified against `src/popup/`
|
||||||
([#164](https://git.eeqj.de/sneak/AutistMask/issues/164)).
|
([#164](https://git.eeqj.de/sneak/AutistMask/issues/164)).
|
||||||
|
|||||||
@@ -869,6 +869,12 @@
|
|||||||
/>
|
/>
|
||||||
Show tracked tokens with zero balance
|
Show tracked tokens with zero balance
|
||||||
</label>
|
</label>
|
||||||
|
<label
|
||||||
|
class="text-xs flex items-center gap-1 cursor-pointer mb-2"
|
||||||
|
>
|
||||||
|
<input type="checkbox" id="settings-utc-timestamps" />
|
||||||
|
UTC Timestamps
|
||||||
|
</label>
|
||||||
<div class="text-xs flex items-center gap-1">
|
<div class="text-xs flex items-center gap-1">
|
||||||
<label for="settings-theme">Theme:</label>
|
<label for="settings-theme">Theme:</label>
|
||||||
<select
|
<select
|
||||||
@@ -979,12 +985,6 @@
|
|||||||
/>
|
/>
|
||||||
<span class="text-xs text-muted">gwei</span>
|
<span class="text-xs text-muted">gwei</span>
|
||||||
</div>
|
</div>
|
||||||
<label
|
|
||||||
class="text-xs flex items-center gap-1 cursor-pointer mb-1"
|
|
||||||
>
|
|
||||||
<input type="checkbox" id="settings-utc-timestamps" />
|
|
||||||
UTC Timestamps
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg-well p-3 mx-1 mb-3">
|
<div class="bg-well p-3 mx-1 mb-3">
|
||||||
|
|||||||
111
tests/settingsUtcTimestamps.test.js
Normal file
111
tests/settingsUtcTimestamps.test.js
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
// Tests for the UTC Timestamps setting.
|
||||||
|
//
|
||||||
|
// The checkbox was moved out of the Token Spam Protection well and into the
|
||||||
|
// Display well next to the theme selector. It is wired by id through the $()
|
||||||
|
// helper, so the move cannot break the handler — but nothing in the suite said
|
||||||
|
// so. These tests pin both halves down: the markup lives in Display and
|
||||||
|
// nowhere else, and the value still round-trips through storage.
|
||||||
|
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
const POPUP_HTML = fs.readFileSync(
|
||||||
|
path.join(__dirname, "..", "src", "popup", "index.html"),
|
||||||
|
"utf8",
|
||||||
|
);
|
||||||
|
|
||||||
|
// The body of one `<div class="bg-well ...">` well, selected by its heading.
|
||||||
|
function wellWithHeading(html, heading) {
|
||||||
|
const headingIndex = html.indexOf(
|
||||||
|
'<h3 class="font-bold mb-1">' + heading + "</h3>",
|
||||||
|
);
|
||||||
|
expect(headingIndex).toBeGreaterThan(-1);
|
||||||
|
const start = html.lastIndexOf('<div class="bg-well', headingIndex);
|
||||||
|
const end = html.indexOf('<div class="bg-well', headingIndex);
|
||||||
|
return html.slice(start, end === -1 ? html.length : end);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("the UTC Timestamps checkbox placement", () => {
|
||||||
|
test("the checkbox appears exactly once in the popup markup", () => {
|
||||||
|
const matches = POPUP_HTML.match(/id="settings-utc-timestamps"/g);
|
||||||
|
expect(matches).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("it renders in the Display well, alongside the theme selector", () => {
|
||||||
|
const display = wellWithHeading(POPUP_HTML, "Display");
|
||||||
|
|
||||||
|
expect(display).toContain('id="settings-utc-timestamps"');
|
||||||
|
expect(display).toContain('id="settings-theme"');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("it does not render in the Token Spam Protection well", () => {
|
||||||
|
const spam = wellWithHeading(POPUP_HTML, "Token Spam Protection");
|
||||||
|
|
||||||
|
expect(spam).not.toContain('id="settings-utc-timestamps"');
|
||||||
|
// The filters that do belong there are untouched.
|
||||||
|
expect(spam).toContain('id="settings-hide-low-holders"');
|
||||||
|
expect(spam).toContain('id="settings-hide-fraud-contracts"');
|
||||||
|
expect(spam).toContain('id="settings-hide-dust"');
|
||||||
|
expect(spam).toContain('id="settings-dust-threshold"');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("the UTC Timestamps setting round-trips through storage", () => {
|
||||||
|
let store;
|
||||||
|
|
||||||
|
function loadStateModule() {
|
||||||
|
store = {};
|
||||||
|
global.chrome = {
|
||||||
|
storage: {
|
||||||
|
local: {
|
||||||
|
get: async (key) =>
|
||||||
|
key in store ? { [key]: store[key] } : {},
|
||||||
|
set: async (obj) => Object.assign(store, obj),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
jest.resetModules();
|
||||||
|
return require("../src/shared/state");
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
delete global.chrome;
|
||||||
|
});
|
||||||
|
|
||||||
|
test("defaults to off with nothing persisted", async () => {
|
||||||
|
const { state, loadState } = loadStateModule();
|
||||||
|
|
||||||
|
await loadState();
|
||||||
|
|
||||||
|
expect(state.utcTimestamps).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("an enabled checkbox is persisted and read back", async () => {
|
||||||
|
const first = loadStateModule();
|
||||||
|
|
||||||
|
// What the change handler in views/settings.js does.
|
||||||
|
first.state.utcTimestamps = true;
|
||||||
|
await first.saveState();
|
||||||
|
expect(store.autistmask.utcTimestamps).toBe(true);
|
||||||
|
|
||||||
|
// A fresh popup load sees it.
|
||||||
|
jest.resetModules();
|
||||||
|
const second = require("../src/shared/state");
|
||||||
|
expect(second.state.utcTimestamps).toBe(false);
|
||||||
|
await second.loadState();
|
||||||
|
expect(second.state.utcTimestamps).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("turning it back off is persisted too", async () => {
|
||||||
|
const { state, saveState, loadState } = loadStateModule();
|
||||||
|
|
||||||
|
state.utcTimestamps = true;
|
||||||
|
await saveState();
|
||||||
|
state.utcTimestamps = false;
|
||||||
|
await saveState();
|
||||||
|
|
||||||
|
state.utcTimestamps = true;
|
||||||
|
await loadState();
|
||||||
|
expect(state.utcTimestamps).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user