Files
kandev/apps/web/components/settings/system/feature-toggle-card.test.tsx
T
2026-06-15 13:33:45 +01:00

149 lines
4.2 KiB
TypeScript

import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import type { RuntimeFlagState } from "@/lib/types/runtime-flags";
import { FeatureToggleCard } from "./feature-toggle-card";
vi.mock("@kandev/ui/switch", () => ({
Switch: ({
checked,
disabled,
"aria-label": ariaLabel,
onCheckedChange,
}: {
checked: boolean;
disabled: boolean;
"aria-label": string;
onCheckedChange: (checked: boolean) => void;
}) => (
<button
aria-label={ariaLabel}
aria-pressed={checked}
disabled={disabled}
type="button"
onClick={() => onCheckedChange(!checked)}
/>
),
}));
afterEach(cleanup);
describe("FeatureToggleCard", () => {
it("shows risk copy as supporting text instead of a warning alert", () => {
render(
<FeatureToggleCard
flag={flagState({
risk_description:
"Office mode is still evolving and should be reviewed before relying on it.",
})}
saving={false}
onChange={() => undefined}
onReset={() => undefined}
/>,
);
expect(screen.getByText(/Office mode is still evolving/)).not.toBeNull();
expect(screen.queryByRole("alert")).toBeNull();
});
it("calls onChange with the next switch value", () => {
const onChange = vi.fn();
render(
<FeatureToggleCard
flag={flagState({ effective_value: false })}
saving={false}
onChange={onChange}
onReset={() => undefined}
/>,
);
fireEvent.click(screen.getByLabelText("Toggle Office mode"));
expect(onChange).toHaveBeenCalledWith(true);
});
it("calls onReset from the use default action when an override exists", () => {
const onReset = vi.fn();
render(
<FeatureToggleCard
flag={flagState({ override_value: false })}
saving={false}
onChange={() => undefined}
onReset={onReset}
/>,
);
fireEvent.click(screen.getByRole("button", { name: /use default/i }));
expect(onReset).toHaveBeenCalledTimes(1);
});
it("disables changes and reset when the launch environment controls the flag", () => {
const onChange = vi.fn();
const onReset = vi.fn();
render(
<FeatureToggleCard
flag={flagState({ env_locked: true, source: "env" })}
saving={false}
onChange={onChange}
onReset={onReset}
/>,
);
expect(screen.getByLabelText("Toggle Office mode")).toHaveProperty("disabled", true);
expect(screen.getByRole("button", { name: /use default/i })).toHaveProperty("disabled", true);
expect(screen.getByText("Controlled by launch environment")).not.toBeNull();
});
it("disables changes and reset for immutable flags", () => {
const onChange = vi.fn();
const onReset = vi.fn();
render(
<FeatureToggleCard
flag={flagState({ mutable: false, override_value: false })}
saving={false}
onChange={onChange}
onReset={onReset}
/>,
);
expect(screen.getByLabelText("Toggle Office mode")).toHaveProperty("disabled", true);
expect(screen.getByRole("button", { name: /use default/i })).toHaveProperty("disabled", true);
});
it("shows restart metadata when a saved change is pending", () => {
render(
<FeatureToggleCard
flag={flagState({ restart_required: true, requires_restart_to_apply: true })}
saving={false}
onChange={() => undefined}
onReset={() => undefined}
/>,
);
expect(screen.getByText("Requires restart")).not.toBeNull();
expect(screen.getByText("Pending restart")).not.toBeNull();
});
});
function flagState(overrides: Partial<RuntimeFlagState> = {}): RuntimeFlagState {
return {
key: "features.office",
env_var: "KANDEV_FEATURES_OFFICE",
label: "Office mode",
description: "Enables autonomous agent office workflows and related settings.",
kind: "feature",
stability: "experimental",
risk_level: "medium",
risk_description: "",
default_value: false,
override_value: true,
effective_value: true,
source: "override",
env_locked: false,
restart_required: true,
requires_restart_to_apply: true,
mutable: true,
...overrides,
};
}