[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

This commit is contained in:
2026-09-13 18:24:01 +08:00
commit 3c72efcb7f
3255 changed files with 907009 additions and 0 deletions

View File

@@ -0,0 +1,132 @@
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
const readAppLockSectionSource = () => (
readFileSync(new URL("./AppLockSettingsSection.tsx", import.meta.url), "utf8")
);
test("disabling app lock does not trigger a second renderer-side unlock request", () => {
const source = readAppLockSectionSource();
assert.doesNotMatch(source, /unlockApp\?\.\(/);
assert.doesNotMatch(source, /unlockApp\?:/);
});
test("app lock setup starts with password setup instead of a misleading enable toggle", () => {
const source = readAppLockSectionSource();
assert.match(source, /!hasPassword \? \(/);
assert.match(source, /settings\.appLock\.setupTitle/);
assert.match(source, /settings\.appLock\.setupDescription/);
assert.match(source, /settings\.appLock\.manageTitle/);
assert.doesNotMatch(
source,
/hasAppLockPassword \? t\("settings\.appLock\.enableDesc"\) : t\("settings\.appLock\.enableAfterPassword"\)/,
);
});
test("app lock section exposes settings-search anchors", () => {
const source = readAppLockSectionSource();
assert.match(source, /anchorId="system-app-lock"/);
});
test("app lock disable handler uses its modal current password field", () => {
const source = readAppLockSectionSource();
const handlerStart = source.indexOf("const handleDisable = useCallback");
const handlerEnd = source.indexOf("const handleSavePassword", handlerStart);
const handlerSource = source.slice(handlerStart, handlerEnd);
assert.match(handlerSource, /requestAppLockDisable\(disablePassword\)/);
assert.match(handlerSource, /disablePassword,/);
assert.doesNotMatch(source, /handleAppLockEnabledChange/);
});
test("app lock page uses settings rows and moves password forms into a dialog", () => {
const source = readAppLockSectionSource();
const dialogStart = source.indexOf('<Dialog');
const firstPasswordInput = source.indexOf('<Input');
assert.match(source, /<SettingCard divided>/);
assert.match(source, /<SettingRow/);
assert.match(source, /<DialogContent/);
assert.ok(firstPasswordInput > dialogStart, "password inputs should only render inside the dialog");
assert.doesNotMatch(source.slice(0, dialogStart), /<Input/);
assert.doesNotMatch(source, /settings\.appLock\.enableDesc/);
assert.match(source, /settings\.appLock\.disableTitle/);
assert.match(source, /settings\.appLock\.disableDescription/);
assert.match(source, /settings\.appLock\.disable/);
assert.match(source, /settings\.appLock\.changePasswordTitle/);
assert.match(source, /settings\.appLock\.currentPasswordForDisablePlaceholder/);
assert.match(source, /settings\.appLock\.currentPasswordForChangePlaceholder/);
});
test("app lock password setup keeps whitespace as password content", () => {
const source = readAppLockSectionSource();
assert.ok(source.includes("newPassword.length === 0"));
assert.ok(source.includes("confirmPassword.length === 0"));
assert.ok(!source.includes("newPassword.trim()"));
assert.ok(!source.includes("confirmPassword.trim()"));
});
test("app lock system unlock setting uses bridge-provided platform label", () => {
const source = readAppLockSectionSource();
assert.match(source, /showSystemUnlock/);
assert.match(source, /appLockSystemUnlockStatus\.label/);
assert.match(source, /settings\.appLock\.systemUnlock\.label/);
assert.doesNotMatch(source, /navigator\.platform/);
});
test("app lock system unlock enablement does not require current password in settings", () => {
const source = readAppLockSectionSource();
const handlerStart = source.indexOf("const handleSystemUnlockChange = useCallback");
const handlerEnd = source.indexOf("const handleAutoPromptChange", handlerStart);
const handlerSource = source.slice(handlerStart, handlerEnd);
assert.match(handlerSource, /setAppLockSystemUnlockEnabled\(\{/);
assert.doesNotMatch(handlerSource, /appLockSystemUnlockPassword/);
assert.doesNotMatch(handlerSource, /currentPassword:/);
const systemUnlockStart = source.indexOf("{showSystemUnlock");
const systemUnlockEnd = source.indexOf("settings.appLock.changePasswordTitle", systemUnlockStart);
const systemUnlockSection = source.slice(systemUnlockStart, systemUnlockEnd);
assert.doesNotMatch(systemUnlockSection, /settings\.appLock\.currentPassword/);
});
test("app lock system unlock setting hides when unavailable unless already enabled", () => {
const source = readAppLockSectionSource();
assert.match(source, /appLockSystemUnlockStatus\.available \|\| appLockSettings\.systemUnlockEnabled/);
// Already-enabled toggle stays clickable when unavailable so the user can disable.
assert.match(
source,
/disabled=\{\s*isSavingSystemUnlock\s*\|\|\s*\(!appLockSystemUnlockStatus\.available && !appLockSettings\.systemUnlockEnabled\)\s*\}/,
);
});
test("app lock system unlock exposes auto prompt as a child option", () => {
const source = readAppLockSectionSource();
assert.match(source, /settings\.appLock\.systemUnlock\.autoPrompt\.label/);
assert.match(source, /settings\.appLock\.systemUnlock\.autoPrompt\.desc/);
assert.match(source, /appLockSettings\.systemUnlockAutoPromptEnabled/);
assert.match(source, /appLockSettings\.systemUnlockEnabled/);
});
test("app lock system unlock handles native verification failures", () => {
const source = readAppLockSectionSource();
assert.match(source, /'cancelled' \| 'failed'/);
assert.match(source, /result\.error === 'cancelled'/);
assert.match(source, /case 'failed':\s*return t\('settings\.appLock\.systemUnlock\.unavailable'\)/);
});
test("app lock disable explains that turning it off removes the saved password", () => {
const englishLocale = readFileSync(new URL("../../../application/i18n/locales/en/core.ts", import.meta.url), "utf8");
assert.match(englishLocale, /saved password will be removed/);
assert.match(englishLocale, /requires creating a new one/);
});