Files
NetMesh/application/state/useStoredString.test.ts
zhaolei 3c72efcb7f
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
[Init] Initial commit - NetMesh terminal manager
2026-09-13 18:24:01 +08:00

120 lines
3.8 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import {
createStoredStringSyncHandlers,
readOptionalStoredStringValue,
readStoredStringValue,
resolveStoredStringUpdate,
} from "./useStoredString.ts";
type TestMode = "edit" | "preview";
const isTestMode = (value: string | null): value is TestMode =>
value === "edit" || value === "preview";
function installLocalStorage() {
const previousLocalStorage = Object.getOwnPropertyDescriptor(globalThis, "localStorage");
const backing = new Map<string, string>();
const storage: Storage = {
get length() {
return backing.size;
},
clear() {
backing.clear();
},
getItem(key: string) {
return backing.get(key) ?? null;
},
key(index: number) {
return Array.from(backing.keys())[index] ?? null;
},
removeItem(key: string) {
backing.delete(key);
},
setItem(key: string, value: string) {
backing.set(key, value);
},
};
Object.defineProperty(globalThis, "localStorage", {
value: storage,
configurable: true,
});
return {
storage,
restore() {
if (previousLocalStorage) {
Object.defineProperty(globalThis, "localStorage", previousLocalStorage);
return;
}
Reflect.deleteProperty(globalThis, "localStorage");
},
};
}
test("stored string sync handlers refresh from same-window and browser storage events", (t) => {
const env = installLocalStorage();
t.after(() => env.restore());
const storageKey = "netcatty:test-mode";
const syncedValues: TestMode[] = [];
const handlers = createStoredStringSyncHandlers<TestMode>({
storageKey,
fallback: "edit",
isAllowedValue: isTestMode,
onValue: (value) => syncedValues.push(value),
});
env.storage.setItem(storageKey, "preview");
handlers.handleAdapterChange({ detail: { key: storageKey } } as CustomEvent<{ key: string }>);
assert.deepEqual(syncedValues, ["preview"]);
env.storage.setItem(storageKey, "invalid");
handlers.handleBrowserStorage({ type: "storage", key: storageKey } as StorageEvent);
assert.deepEqual(syncedValues, ["preview", "edit"]);
env.storage.setItem(storageKey, "preview");
handlers.handleAdapterChange({ detail: { key: "other-key" } } as CustomEvent<{ key: string }>);
assert.deepEqual(syncedValues, ["preview", "edit"]);
});
test("stored string helpers read fallback and resolve updater-style toggles", (t) => {
const env = installLocalStorage();
t.after(() => env.restore());
const storageKey = "netcatty:test-mode";
assert.equal(readStoredStringValue(storageKey, "edit", isTestMode), "edit");
assert.equal(readOptionalStoredStringValue(storageKey, isTestMode), null);
env.storage.setItem(storageKey, "preview");
assert.equal(readStoredStringValue(storageKey, "edit", isTestMode), "preview");
assert.equal(readOptionalStoredStringValue(storageKey, isTestMode), "preview");
env.storage.setItem(storageKey, "invalid");
assert.equal(readStoredStringValue(storageKey, "edit", isTestMode), "edit");
assert.equal(readOptionalStoredStringValue(storageKey, isTestMode), null);
assert.equal(resolveStoredStringUpdate<TestMode>("edit", "preview"), "preview");
assert.equal(
resolveStoredStringUpdate<TestMode>("preview", (currentValue) => (
currentValue === "edit" ? "preview" : "edit"
)),
"edit",
);
});
test("stored string helpers work with default validator when isAllowedValue is omitted", (t) => {
const env = installLocalStorage();
t.after(() => env.restore());
const storageKey = "netcatty:test-font";
assert.equal(readStoredStringValue(storageKey, "default-font"), "default-font");
assert.equal(readOptionalStoredStringValue(storageKey), null);
env.storage.setItem(storageKey, "Inter");
assert.equal(readStoredStringValue(storageKey, "default-font"), "Inter");
assert.equal(readOptionalStoredStringValue(storageKey), "Inter");
});