Files
NetMesh/components/HostIconPicker.test.tsx
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

133 lines
4.7 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import React from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { I18nProvider } from "../application/i18n/I18nProvider.tsx";
import { HostIconPicker } from "./HostIconPicker.tsx";
import { TooltipProvider } from "./ui/tooltip.tsx";
const distroOptions = [
{
value: "linux",
label: "Generic Linux",
icon: "/distro/linux.svg",
bgClass: "bg-[#333333]",
},
{
value: "ubuntu",
label: "Ubuntu",
icon: "/distro/ubuntu.svg",
bgClass: "bg-[#E95420]",
},
];
const hostIconPickerSource = readFileSync(new URL("./HostIconPicker.tsx", import.meta.url), "utf8");
const renderPicker = (props: Partial<React.ComponentProps<typeof HostIconPicker>> = {}) =>
renderToStaticMarkup(
<I18nProvider locale="en">
<TooltipProvider>
<HostIconPicker
distroMode={props.distroMode}
manualDistro={props.manualDistro}
effectiveDistro={props.effectiveDistro}
distroOptions={props.distroOptions || distroOptions}
getDistroOptionLabel={props.getDistroOptionLabel || ((value) => distroOptions.find((option) => option.value === value)?.label || "Unknown")}
iconMode={props.iconMode}
iconId={props.iconId}
iconColorMode={props.iconColorMode}
iconColor={props.iconColor}
iconColorCustom={props.iconColorCustom}
manualIconMenuOpen={props.manualIconMenuOpen}
onChange={() => {}}
/>
</TooltipProvider>
</I18nProvider>,
);
test("HostIconPicker renders automatic source and automatic color by default", () => {
const markup = renderPicker({ effectiveDistro: "ubuntu" });
assert.match(markup, /Source/);
assert.match(markup, /Auto-detect/);
assert.match(markup, /Current/);
assert.match(markup, /Ubuntu/);
assert.match(markup, /Icon color/);
assert.match(markup, /Automatic/);
assert.match(markup, /Current color/);
assert.doesNotMatch(markup, /Brand/);
assert.doesNotMatch(markup, /Custom color/);
});
test("HostIconPicker renders a single manual icon dropdown in manual source mode", () => {
const markup = renderPicker({ distroMode: "manual", manualDistro: "linux", manualIconMenuOpen: true });
assert.match(markup, /Manual icon/);
assert.match(markup, /Generic Linux/);
assert.match(markup, /aria-label="Manual icon"/);
});
test("HostIconPicker renders built-in type icons when a custom type is selected", () => {
const markup = renderPicker({ distroMode: "manual", iconMode: "custom", iconId: "database", manualIconMenuOpen: true });
assert.match(markup, /Database/);
assert.match(markup, /Current color/);
assert.match(markup, /background-color:#0891B2/);
});
test("HostIconPicker shows the automatic brand color preview", () => {
const markup = renderPicker({ distroMode: "manual", manualDistro: "ubuntu" });
assert.match(markup, /Current color/);
assert.match(markup, /bg-\[#E95420\]/);
assert.match(markup, /Ubuntu/);
});
test("HostIconPicker ignores stale colors when color mode is automatic", () => {
const markup = renderPicker({
distroMode: "manual",
iconMode: "custom",
iconId: "database",
iconColorMode: "auto",
iconColor: "violet",
iconColorCustom: "#12ABEF",
});
assert.match(markup, /Automatic/);
assert.match(markup, /Current color/);
assert.match(markup, /Database/);
assert.match(markup, /background-color:#0891B2/);
assert.doesNotMatch(markup, /#12ABEF/);
assert.doesNotMatch(markup, /Violet/);
});
test("HostIconPicker keeps brand/type tabs inside the manual icon dropdown menu", () => {
assert.match(hostIconPickerSource, /<SelectContent className="min-w-\[16rem\]" hideScrollButtons>[\s\S]*role="tab"[\s\S]*hostDetails\.icon\.tab\.brand/);
assert.match(hostIconPickerSource, /<SelectContent className="min-w-\[16rem\]" hideScrollButtons>[\s\S]*hostDetails\.icon\.tab\.type/);
assert.doesNotMatch(hostIconPickerSource, /<TabsList/);
});
test("HostIconPicker renders preset and custom color choices in manual color mode", () => {
const markup = renderPicker({ iconColorMode: "manual", iconColor: "violet" });
assert.match(markup, /Manual/);
assert.match(markup, /Violet/);
});
test("HostIconPicker renders a custom hex color input", () => {
const markup = renderPicker({ iconColorMode: "manual", iconColorCustom: "#12ABEF" });
assert.match(markup, /Custom color/);
assert.match(markup, /#12ABEF/);
assert.match(markup, /type="color"/);
});
test("HostIconPicker does not expose image upload", () => {
const markup = renderPicker({ distroMode: "manual", iconMode: "custom", iconId: "database" });
assert.doesNotMatch(markup, /upload/i);
assert.doesNotMatch(markup, /choose file/i);
});