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
133 lines
4.7 KiB
TypeScript
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);
|
|
});
|