import { describe, expect, it } from "vitest";
import { ROBOT_STATUS_TONES } from "@/lib/config";
import { THEME_TOKENS } from "@/lib/theme";
import { statusColor } from "@/lib/theme-status";
describe("statusColor", () => {
it("設定値にあるキーは対応する色を返す", () => {
expect(statusColor("dark", "待機中")).toBe(THEME_TOKENS.dark.ok);
expect(statusColor("dark", "充電中")).toBe(THEME_TOKENS.dark.pr);
expect(statusColor("dark", "ハンドルアップ")).toBe(THEME_TOKENS.dark.ng);
expect(statusColor("dark", "セキュリティ有効")).toBe(THEME_TOKENS.dark.ac);
});
it("★設定値に無いキーはグレー(c.txD)を返す★(実データで起きること。D-077と同じ思想)", () => {
expect(statusColor("dark", "UnknownStatus")).toBe(THEME_TOKENS.dark.txD);
expect(statusColor("light", "EmergencyStop")).toBe(THEME_TOKENS.light.txD);
expect(statusColor("dark", "Handrail Lifted")).toBe(THEME_TOKENS.dark.txD);
// `Standby.` は ROBOT_STATUS_TONES にあえて登録していない(lib/config/index.ts のコメント参照)
expect(statusColor("dark", "Standby.")).toBe(THEME_TOKENS.dark.txD);
});
it("空文字もグレーを返す", () => {
expect(statusColor("dark", "")).toBe(THEME_TOKENS.dark.txD);
});
it("前後に空白のある値はグレーを返す(trim しない。値を加工しないのが D-077 の方針)", () => {
expect(statusColor("dark", " 待機中 ")).toBe(THEME_TOKENS.dark.txD);
expect(statusColor("dark", "待機中 ")).toBe(THEME_TOKENS.dark.txD);
expect(statusColor("light", " 待機中")).toBe(THEME_TOKENS.light.txD);
});
// ★`ROBOT_STATUS_TONES` はプレーンなオブジェクトリテラルなので、
// ガードなしの添字アクセスだと `Object.prototype` のメンバーを拾ってしまい、
// 後段で `undefined` に落ちて `Pill` が `background:undefined22` を出していた。
// D-077 の生値方針では未知の値が来ることが仕様上の前提なので、
// ★プロトタイプ由来のキーでも必ずグレーにフォールバックする★ことを固定する。
const PROTOTYPE_KEYS = [
"constructor",
"toString",
"__proto__",
"hasOwnProperty",
"valueOf",
"isPrototypeOf",
"propertyIsEnumerable",
"toLocaleString",
];
it.each(PROTOTYPE_KEYS)(
"★Object.prototype 由来のキー %s はグレーを返す(undefined ではない)★",
(key) => {
expect(statusColor("dark", key)).toBe(THEME_TOKENS.dark.txD);
expect(statusColor("light", key)).toBe(THEME_TOKENS.light.txD);
},
);
it("★どのキーでも戻り値は必ず文字列で undefined を含まない★(Pill の style が壊れないこと)", () => {
const keys = [
...Object.keys(ROBOT_STATUS_TONES),
...PROTOTYPE_KEYS,
"",
" 待機中 ",
"EmergencyStop",
"Handrail Lifted",
"Standby.",
"-200",
];
for (const theme of ["dark", "light"] as const) {
for (const key of keys) {
const color = statusColor(theme, key);
expect(typeof color).toBe("string");
expect(color).not.toContain("undefined");
}
}
});
it("ライト/ダーク両方のテーマでそれぞれのトークンが返る", () => {
expect(statusColor("light", "待機中")).toBe(THEME_TOKENS.light.ok);
expect(statusColor("dark", "待機中")).toBe(THEME_TOKENS.dark.ok);
expect(statusColor("light", "待機中")).not.toBe(statusColor("dark", "待機中"));
});
it("ROBOT_STATUS_TONES の全キーが両テーマで色を返す(網羅の裏取り)", () => {
for (const status of Object.keys(ROBOT_STATUS_TONES)) {
expect(statusColor("dark", status)).not.toBe(THEME_TOKENS.dark.txD);
expect(statusColor("light", status)).not.toBe(THEME_TOKENS.light.txD);
}
});
});