[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
142
application/state/settingsStateDefaults.test.ts
Normal file
142
application/state/settingsStateDefaults.test.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import {
|
||||
DEFAULT_THEME,
|
||||
getContrastRatio,
|
||||
buildAppThemeCssVars,
|
||||
getHslTokenRelativeLuminance,
|
||||
resolveReadableForegroundForHsl,
|
||||
resolveThemeAccentForeground,
|
||||
migrateIncomingTerminalFontId,
|
||||
} from "./settingsStateDefaults.ts";
|
||||
import { TERMINAL_FONT_AUTO } from "../../infrastructure/config/fonts.ts";
|
||||
import { STORAGE_KEY_TERM_FONT_FAMILY } from "../../infrastructure/config/storageKeys.ts";
|
||||
import type { UiThemeTokens } from "../../infrastructure/config/uiThemes.ts";
|
||||
|
||||
function installMemoryLocalStorage(): Map<string, string> {
|
||||
const store = new Map<string, string>();
|
||||
(globalThis as { localStorage?: unknown }).localStorage = {
|
||||
getItem: (k: string) => (store.has(k) ? store.get(k)! : null),
|
||||
setItem: (k: string, v: string) => void store.set(k, v),
|
||||
removeItem: (k: string) => void store.delete(k),
|
||||
clear: () => store.clear(),
|
||||
};
|
||||
return store;
|
||||
}
|
||||
|
||||
test("fresh installs follow the operating system color scheme by default", () => {
|
||||
assert.equal(DEFAULT_THEME, "system");
|
||||
});
|
||||
|
||||
test("migrateIncomingTerminalFontId rewrites deprecated ids to the auto sentinel, not menlo", () => {
|
||||
// menlo would put Windows/Linux upgrade users back into the #1647 path,
|
||||
// and a concrete id would leak across OSes via sync; auto resolves per device.
|
||||
const store = installMemoryLocalStorage();
|
||||
try {
|
||||
assert.equal(migrateIncomingTerminalFontId("pingfang-sc"), TERMINAL_FONT_AUTO);
|
||||
// The rewrite is persisted as the platform-neutral sentinel, never a concrete id.
|
||||
assert.equal(store.get(STORAGE_KEY_TERM_FONT_FAMILY), TERMINAL_FONT_AUTO);
|
||||
assert.equal(migrateIncomingTerminalFontId("microsoft-yahei"), TERMINAL_FONT_AUTO);
|
||||
} finally {
|
||||
delete (globalThis as { localStorage?: unknown }).localStorage;
|
||||
}
|
||||
});
|
||||
|
||||
test("migrateIncomingTerminalFontId leaves valid ids and empty values untouched", () => {
|
||||
assert.equal(migrateIncomingTerminalFontId("jetbrains-mono"), "jetbrains-mono");
|
||||
assert.equal(migrateIncomingTerminalFontId(TERMINAL_FONT_AUTO), TERMINAL_FONT_AUTO);
|
||||
assert.equal(migrateIncomingTerminalFontId(""), null);
|
||||
assert.equal(migrateIncomingTerminalFontId(null), null);
|
||||
});
|
||||
|
||||
test("readable foreground picks white text for dark accent colors", () => {
|
||||
assert.equal(resolveReadableForegroundForHsl("270 70% 45%"), "0 0% 100%");
|
||||
});
|
||||
|
||||
test("readable foreground picks black text for light accent colors", () => {
|
||||
assert.equal(resolveReadableForegroundForHsl("48 95% 72%"), "0 0% 0%");
|
||||
});
|
||||
|
||||
test("computed contrast chooses the stronger black or white foreground", () => {
|
||||
const purpleLuminance = getHslTokenRelativeLuminance("270 70% 45%");
|
||||
assert.equal(typeof purpleLuminance, "number");
|
||||
assert.ok(getContrastRatio(1, purpleLuminance as number) > getContrastRatio(0, purpleLuminance as number));
|
||||
|
||||
const yellowLuminance = getHslTokenRelativeLuminance("48 95% 72%");
|
||||
assert.equal(typeof yellowLuminance, "number");
|
||||
assert.ok(getContrastRatio(0, yellowLuminance as number) > getContrastRatio(1, yellowLuminance as number));
|
||||
});
|
||||
|
||||
test("theme accent foreground uses the computed color for preset accent buttons", () => {
|
||||
const tokens: UiThemeTokens = {
|
||||
background: "0 0% 100%",
|
||||
foreground: "222 47% 12%",
|
||||
card: "0 0% 100%",
|
||||
cardForeground: "222 47% 12%",
|
||||
popover: "0 0% 100%",
|
||||
popoverForeground: "222 47% 12%",
|
||||
primary: "270 70% 45%",
|
||||
primaryForeground: "0 0% 0%",
|
||||
secondary: "220 12% 95%",
|
||||
secondaryForeground: "222 47% 12%",
|
||||
muted: "220 12% 95%",
|
||||
mutedForeground: "220 10% 45%",
|
||||
accent: "270 70% 45%",
|
||||
accentForeground: "0 0% 0%",
|
||||
destructive: "0 70% 50%",
|
||||
destructiveForeground: "0 0% 100%",
|
||||
border: "220 12% 88%",
|
||||
input: "220 12% 88%",
|
||||
ring: "270 70% 45%",
|
||||
};
|
||||
|
||||
assert.equal(resolveThemeAccentForeground(tokens, "theme", "48 95% 72%"), "0 0% 100%");
|
||||
assert.equal(resolveThemeAccentForeground(tokens, "custom", "48 95% 72%"), "0 0% 0%");
|
||||
});
|
||||
|
||||
test("app surface theme vars isolate non-terminal pages from active terminal chrome", () => {
|
||||
const tokens: UiThemeTokens = {
|
||||
background: "0 0% 100%",
|
||||
foreground: "222 47% 12%",
|
||||
card: "0 0% 100%",
|
||||
cardForeground: "222 47% 12%",
|
||||
popover: "0 0% 100%",
|
||||
popoverForeground: "222 47% 12%",
|
||||
primary: "270 70% 45%",
|
||||
primaryForeground: "0 0% 0%",
|
||||
secondary: "220 12% 95%",
|
||||
secondaryForeground: "222 47% 12%",
|
||||
muted: "220 12% 95%",
|
||||
mutedForeground: "220 10% 45%",
|
||||
accent: "270 70% 45%",
|
||||
accentForeground: "0 0% 0%",
|
||||
destructive: "0 70% 50%",
|
||||
destructiveForeground: "0 0% 100%",
|
||||
border: "220 12% 88%",
|
||||
input: "220 12% 88%",
|
||||
ring: "270 70% 45%",
|
||||
};
|
||||
|
||||
assert.deepEqual(buildAppThemeCssVars(tokens, "theme", "48 95% 72%"), {
|
||||
"--background": "0 0% 100%",
|
||||
"--foreground": "222 47% 12%",
|
||||
"--card": "0 0% 100%",
|
||||
"--card-foreground": "222 47% 12%",
|
||||
"--popover": "0 0% 100%",
|
||||
"--popover-foreground": "222 47% 12%",
|
||||
"--primary": "270 70% 45%",
|
||||
"--primary-foreground": "0 0% 100%",
|
||||
"--secondary": "220 12% 95%",
|
||||
"--secondary-foreground": "222 47% 12%",
|
||||
"--muted": "220 12% 95%",
|
||||
"--muted-foreground": "220 10% 45%",
|
||||
"--accent": "270 70% 45%",
|
||||
"--accent-foreground": "0 0% 100%",
|
||||
"--destructive": "0 70% 50%",
|
||||
"--destructive-foreground": "0 0% 100%",
|
||||
"--border": "220 12% 88%",
|
||||
"--input": "220 12% 88%",
|
||||
"--ring": "270 70% 45%",
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user