[Test] Add unit tests for router_settings components

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
yuneng-jiang 2026-02-24 15:26:06 -08:00 • committed by Sameer Kankute
parent f778afc14b
commit 0e8b5616d6
6 changed files with 650 additions and 0 deletions

View file

@ -0,0 +1,55 @@
import { describe, it, expect } from "vitest";
import { render, screen } from "@testing-library/react";
import LatencyBasedConfiguration from "./LatencyBasedConfiguration";
describe("LatencyBasedConfiguration", () => {
it("should render the section heading", () => {
render(<LatencyBasedConfiguration routingStrategyArgs={{}} />);
expect(screen.getByText("Latency-Based Configuration")).toBeInTheDocument();
});
it("should render default params when no args are provided", () => {
render(<LatencyBasedConfiguration routingStrategyArgs={null as any} />);
// Default: ttl=3600, lowest_latency_buffer=0
expect(screen.getByDisplayValue("3600")).toBeInTheDocument();
expect(screen.getByDisplayValue("0")).toBeInTheDocument();
});
it("should render the provided routing strategy args as inputs", () => {
const args = { ttl: 7200, lowest_latency_buffer: 0.1 };
render(<LatencyBasedConfiguration routingStrategyArgs={args} />);
expect(screen.getByDisplayValue("7200")).toBeInTheDocument();
expect(screen.getByDisplayValue("0.1")).toBeInTheDocument();
});
it("should render an input with the correct name attribute for each param", () => {
const args = { ttl: 3600, lowest_latency_buffer: 0 };
render(<LatencyBasedConfiguration routingStrategyArgs={args} />);
expect(screen.getByRole("textbox", { name: /ttl/i })).toBeInTheDocument();
expect(screen.getByRole("textbox", { name: /lowest latency buffer/i })).toBeInTheDocument();
});
it("should display the TTL parameter explanation", () => {
render(<LatencyBasedConfiguration routingStrategyArgs={null as any} />);
expect(
screen.getByText(/sliding window to look back over/i)
).toBeInTheDocument();
});
it("should display the lowest_latency_buffer parameter explanation", () => {
render(<LatencyBasedConfiguration routingStrategyArgs={null as any} />);
expect(
screen.getByText(/shuffle between deployments within this %/i)
).toBeInTheDocument();
});
it("should render object values stringified into the input", () => {
const args = { ttl: { nested: true } };
render(<LatencyBasedConfiguration routingStrategyArgs={args} />);
// HTML input type=text strips newlines, so check that the key/value appears
const input = document.querySelector('input[name="ttl"]') as HTMLInputElement;
expect(input).not.toBeNull();
expect(input.value).toContain('"nested"');
expect(input.value).toContain('true');
});
});

View file

@ -0,0 +1,80 @@
import { describe, it, expect } from "vitest";
import { render, screen } from "@testing-library/react";
import ReliabilityRetriesSection from "./ReliabilityRetriesSection";
const baseSettings = {
num_retries: 3,
timeout: 30,
allowed_fails: 2,
fallbacks: ["gpt-3.5"],
context_window_fallbacks: [],
routing_strategy_args: { ttl: 3600 },
routing_strategy: "simple-shuffle",
enable_tag_filtering: false,
};
describe("ReliabilityRetriesSection", () => {
it("should render the section heading", () => {
render(<ReliabilityRetriesSection routerSettings={{}} routerFieldsMetadata={{}} />);
expect(screen.getByText("Reliability & Retries")).toBeInTheDocument();
});
it("should render input fields for non-excluded settings", () => {
render(<ReliabilityRetriesSection routerSettings={baseSettings} routerFieldsMetadata={{}} />);
expect(screen.getByDisplayValue("3")).toBeInTheDocument(); // num_retries
expect(screen.getByDisplayValue("30")).toBeInTheDocument(); // timeout
expect(screen.getByDisplayValue("2")).toBeInTheDocument(); // allowed_fails
});
it("should not render inputs for excluded keys", () => {
render(<ReliabilityRetriesSection routerSettings={baseSettings} routerFieldsMetadata={{}} />);
// Each excluded key must not produce a visible input value
const inputs = screen.queryAllByRole("textbox");
const inputNames = inputs.map((el) => el.getAttribute("name"));
expect(inputNames).not.toContain("fallbacks");
expect(inputNames).not.toContain("context_window_fallbacks");
expect(inputNames).not.toContain("routing_strategy_args");
expect(inputNames).not.toContain("routing_strategy");
expect(inputNames).not.toContain("enable_tag_filtering");
});
it("should use ui_field_name from metadata as the label", () => {
const metadata = {
num_retries: { ui_field_name: "Number of Retries", field_description: "How many times to retry" },
};
render(
<ReliabilityRetriesSection routerSettings={{ num_retries: 3 }} routerFieldsMetadata={metadata} />
);
expect(screen.getByText("Number of Retries")).toBeInTheDocument();
});
it("should fall back to the raw param name when no metadata label is available", () => {
render(
<ReliabilityRetriesSection routerSettings={{ num_retries: 3 }} routerFieldsMetadata={{}} />
);
expect(screen.getByText("num_retries")).toBeInTheDocument();
});
it("should render null values as an empty input", () => {
render(
<ReliabilityRetriesSection routerSettings={{ timeout: null }} routerFieldsMetadata={{}} />
);
const input = screen.getByRole("textbox", { name: /timeout/i }) as HTMLInputElement;
expect(input.value).toBe("");
});
it("should render object values stringified into the input", () => {
const settings = { retry_policy: { "rate-limited": 2 } };
render(<ReliabilityRetriesSection routerSettings={settings} routerFieldsMetadata={{}} />);
// HTML input type=text strips newlines, so check that the key/value appears
const input = document.querySelector('input[name="retry_policy"]') as HTMLInputElement;
expect(input).not.toBeNull();
expect(input.value).toContain('"rate-limited"');
expect(input.value).toContain('2');
});
it("should render no inputs when routerSettings is empty", () => {
render(<ReliabilityRetriesSection routerSettings={{}} routerFieldsMetadata={{}} />);
expect(screen.queryAllByRole("textbox")).toHaveLength(0);
});
});

View file

@ -0,0 +1,134 @@
import { describe, it, expect, vi } from "vitest";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import RouterSettingsForm from "./RouterSettingsForm";
import type { RouterSettingsFormValue } from "./RouterSettingsForm";
// Use the same antd mock as RoutingStrategySelector to keep things consistent
vi.mock("antd", () => ({
Select: Object.assign(
({ value, onChange, children }: any) => (
<select
data-testid="strategy-select"
value={value ?? ""}
onChange={(e) => onChange(e.target.value)}
>
{children}
</select>
),
{
Option: ({ value, children }: any) => (
<option value={value}>{children}</option>
),
}
),
}));
vi.mock("@tremor/react", async (importOriginal) => {
const actual = await importOriginal<typeof import("@tremor/react")>();
return {
...actual,
Switch: ({ checked, onChange }: any) => (
<input
type="checkbox"
role="switch"
checked={checked}
onChange={(e) => onChange(e.target.checked)}
/>
),
};
});
const defaultValue: RouterSettingsFormValue = {
routerSettings: {},
selectedStrategy: null,
enableTagFiltering: false,
};
const baseProps = {
value: defaultValue,
onChange: vi.fn(),
routerFieldsMetadata: {},
availableRoutingStrategies: [],
routingStrategyDescriptions: {},
};
describe("RouterSettingsForm", () => {
it("should render", () => {
render(<RouterSettingsForm {...baseProps} />);
expect(screen.getByText("Routing Settings")).toBeInTheDocument();
});
it("should not show the strategy selector when no strategies are provided", () => {
render(<RouterSettingsForm {...baseProps} />);
expect(screen.queryByTestId("strategy-select")).not.toBeInTheDocument();
});
it("should show the strategy selector when strategies are available", () => {
const props = {
...baseProps,
availableRoutingStrategies: ["simple-shuffle", "latency-based-routing"],
};
render(<RouterSettingsForm {...props} />);
expect(screen.getByTestId("strategy-select")).toBeInTheDocument();
});
it("should not render LatencyBasedConfiguration for non-latency strategies", () => {
const props = {
...baseProps,
value: { ...defaultValue, selectedStrategy: "simple-shuffle" },
availableRoutingStrategies: ["simple-shuffle"],
};
render(<RouterSettingsForm {...props} />);
expect(screen.queryByText("Latency-Based Configuration")).not.toBeInTheDocument();
});
it("should render LatencyBasedConfiguration when strategy is latency-based-routing", () => {
const props = {
...baseProps,
value: {
...defaultValue,
selectedStrategy: "latency-based-routing",
routerSettings: { routing_strategy_args: { ttl: 3600, lowest_latency_buffer: 0 } },
},
availableRoutingStrategies: ["latency-based-routing"],
};
render(<RouterSettingsForm {...props} />);
expect(screen.getByText("Latency-Based Configuration")).toBeInTheDocument();
});
it("should call onChange with the updated strategy when the selector changes", () => {
const onChange = vi.fn();
const props = {
...baseProps,
onChange,
availableRoutingStrategies: ["simple-shuffle", "latency-based-routing"],
};
render(<RouterSettingsForm {...props} />);
const select = screen.getByTestId("strategy-select") as HTMLSelectElement;
select.value = "latency-based-routing";
select.dispatchEvent(new Event("change", { bubbles: true }));
expect(onChange).toHaveBeenCalledWith(
expect.objectContaining({ selectedStrategy: "latency-based-routing" })
);
});
it("should call onChange with the updated enableTagFiltering when the toggle changes", async () => {
const onChange = vi.fn();
const user = userEvent.setup();
render(<RouterSettingsForm {...baseProps} onChange={onChange} />);
await user.click(screen.getByRole("switch"));
expect(onChange).toHaveBeenCalledWith(
expect.objectContaining({ enableTagFiltering: true })
);
});
it("should show the Reliability & Retries section", () => {
render(<RouterSettingsForm {...baseProps} />);
expect(screen.getByText("Reliability & Retries")).toBeInTheDocument();
});
});

View file

@ -0,0 +1,98 @@
import { describe, it, expect, vi } from "vitest";
import { render, screen } from "@testing-library/react";
import RoutingStrategySelector from "./RoutingStrategySelector";
// Ant Design's Select is complex to drive in JSDOM; swap it for a plain
// <select> so we can assert options and fire change events normally.
vi.mock("antd", () => ({
Select: Object.assign(
({ value, onChange, children }: any) => (
<div data-testid="ant-select">
<select
data-testid="strategy-select"
value={value ?? ""}
onChange={(e) => onChange(e.target.value)}
>
{children}
</select>
</div>
),
{
Option: ({ value, children }: any) => (
<option value={value}>{children}</option>
),
}
),
}));
const baseProps = {
selectedStrategy: null,
availableStrategies: ["simple-shuffle", "latency-based-routing", "least-busy"],
routingStrategyDescriptions: {
"simple-shuffle": "Randomly pick a deployment",
"latency-based-routing": "Pick the lowest-latency deployment",
},
routerFieldsMetadata: {},
onStrategyChange: vi.fn(),
};
describe("RoutingStrategySelector", () => {
it("should render", () => {
render(<RoutingStrategySelector {...baseProps} />);
expect(screen.getByTestId("ant-select")).toBeInTheDocument();
});
it("should display default label when no metadata is provided", () => {
render(<RoutingStrategySelector {...baseProps} />);
expect(screen.getByText("Routing Strategy")).toBeInTheDocument();
});
it("should display ui_field_name from metadata when provided", () => {
const props = {
...baseProps,
routerFieldsMetadata: {
routing_strategy: {
ui_field_name: "Strategy",
field_description: "How to pick a deployment",
},
},
};
render(<RoutingStrategySelector {...props} />);
expect(screen.getByText("Strategy")).toBeInTheDocument();
expect(screen.getByText("How to pick a deployment")).toBeInTheDocument();
});
it("should render all available strategies as options", () => {
render(<RoutingStrategySelector {...baseProps} />);
expect(screen.getByText("simple-shuffle")).toBeInTheDocument();
expect(screen.getByText("latency-based-routing")).toBeInTheDocument();
expect(screen.getByText("least-busy")).toBeInTheDocument();
});
it("should display strategy descriptions alongside option labels", () => {
render(<RoutingStrategySelector {...baseProps} />);
expect(screen.getByText("Randomly pick a deployment")).toBeInTheDocument();
expect(screen.getByText("Pick the lowest-latency deployment")).toBeInTheDocument();
});
it("should not render a description for a strategy that has none", () => {
render(<RoutingStrategySelector {...baseProps} />);
// "least-busy" has no entry in routingStrategyDescriptions
const select = screen.getByTestId("strategy-select");
const leastBusyOption = Array.from(select.querySelectorAll("option")).find(
(o) => o.value === "least-busy"
);
expect(leastBusyOption).toBeInTheDocument();
});
it("should call onStrategyChange with the selected strategy value", () => {
const onStrategyChange = vi.fn();
render(<RoutingStrategySelector {...baseProps} onStrategyChange={onStrategyChange} />);
const select = screen.getByTestId("strategy-select") as HTMLSelectElement;
select.value = "latency-based-routing";
select.dispatchEvent(new Event("change", { bubbles: true }));
expect(onStrategyChange).toHaveBeenCalledWith("latency-based-routing");
});
});

View file

@ -0,0 +1,113 @@
import { describe, it, expect, vi } from "vitest";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import TagFilteringToggle from "./TagFilteringToggle";
// setupTests.ts mocks @tremor/react but leaves Switch as the real implementation.
// Re-mock Switch as a plain checkbox so toggle interactions are trivially testable.
vi.mock("@tremor/react", async (importOriginal) => {
const actual = await importOriginal<typeof import("@tremor/react")>();
return {
...actual,
Switch: ({ checked, onChange, className }: any) => (
<input
type="checkbox"
role="switch"
checked={checked}
onChange={(e) => onChange(e.target.checked)}
className={className}
/>
),
};
});
const baseMetadata = {
enable_tag_filtering: {
ui_field_name: "Tag Filtering",
field_description: "Route requests based on tags",
link: null,
},
};
describe("TagFilteringToggle", () => {
it("should render", () => {
render(
<TagFilteringToggle enabled={false} routerFieldsMetadata={{}} onToggle={vi.fn()} />
);
expect(screen.getByRole("switch")).toBeInTheDocument();
});
it("should display default label when no metadata is provided", () => {
render(
<TagFilteringToggle enabled={false} routerFieldsMetadata={{}} onToggle={vi.fn()} />
);
expect(screen.getByText("Enable Tag Filtering")).toBeInTheDocument();
});
it("should display the label from metadata when provided", () => {
render(
<TagFilteringToggle
enabled={false}
routerFieldsMetadata={baseMetadata}
onToggle={vi.fn()}
/>
);
expect(screen.getByText("Tag Filtering")).toBeInTheDocument();
});
it("should display the description from metadata", () => {
render(
<TagFilteringToggle
enabled={false}
routerFieldsMetadata={baseMetadata}
onToggle={vi.fn()}
/>
);
expect(screen.getByText("Route requests based on tags")).toBeInTheDocument();
});
it("should render a Learn more link when metadata provides one", () => {
const metadata = {
enable_tag_filtering: {
...baseMetadata.enable_tag_filtering,
link: "https://docs.example.com/tag-filtering",
},
};
render(
<TagFilteringToggle enabled={false} routerFieldsMetadata={metadata} onToggle={vi.fn()} />
);
const link = screen.getByRole("link", { name: /learn more/i });
expect(link).toBeInTheDocument();
expect(link).toHaveAttribute("href", "https://docs.example.com/tag-filtering");
});
it("should not render a Learn more link when metadata has no link", () => {
render(
<TagFilteringToggle
enabled={false}
routerFieldsMetadata={baseMetadata}
onToggle={vi.fn()}
/>
);
expect(screen.queryByRole("link", { name: /learn more/i })).not.toBeInTheDocument();
});
it("should reflect the enabled=true state on the switch", () => {
render(
<TagFilteringToggle enabled={true} routerFieldsMetadata={{}} onToggle={vi.fn()} />
);
expect(screen.getByRole("switch")).toBeChecked();
});
it("should call onToggle with the new value when the switch is toggled", async () => {
const onToggle = vi.fn();
const user = userEvent.setup();
render(
<TagFilteringToggle enabled={false} routerFieldsMetadata={{}} onToggle={onToggle} />
);
await user.click(screen.getByRole("switch"));
expect(onToggle).toHaveBeenCalledWith(true);
});
});

View file

@ -0,0 +1,170 @@
import { describe, it, expect, vi, beforeEach } from "vitest";
import { renderWithProviders, screen, waitFor } from "../../../tests/test-utils";
import userEvent from "@testing-library/user-event";
import RouterSettings from "./index";
vi.mock("antd", () => ({
Select: Object.assign(
({ value, onChange, children }: any) => (
<select
data-testid="strategy-select"
value={value ?? ""}
onChange={(e) => onChange(e.target.value)}
>
{children}
</select>
),
{
Option: ({ value, children }: any) => (
<option value={value}>{children}</option>
),
}
),
}));
vi.mock("@tremor/react", async (importOriginal) => {
const actual = await importOriginal<typeof import("@tremor/react")>();
return {
...actual,
Switch: ({ checked, onChange }: any) => (
<input
type="checkbox"
role="switch"
checked={checked}
onChange={(e) => onChange(e.target.checked)}
/>
),
};
});
vi.mock("@/components/networking", () => ({
getCallbacksCall: vi.fn(),
getRouterSettingsCall: vi.fn(),
setCallbacksCall: vi.fn(),
}));
import {
getCallbacksCall,
getRouterSettingsCall,
setCallbacksCall,
} from "@/components/networking";
const mockCallbacksResponse = {
router_settings: {
routing_strategy: "simple-shuffle",
num_retries: 3,
timeout: 30,
},
};
const mockRouterSettingsResponse = {
fields: [
{
field_name: "routing_strategy",
ui_field_name: "Routing Strategy",
field_description: "How requests are distributed",
options: ["simple-shuffle", "latency-based-routing"],
link: null,
},
{
field_name: "enable_tag_filtering",
ui_field_name: "Tag Filtering",
field_description: "Route by tag",
field_value: false,
link: null,
},
],
routing_strategy_descriptions: {
"simple-shuffle": "Randomly pick a deployment",
"latency-based-routing": "Pick the lowest-latency deployment",
},
};
const defaultProps = {
accessToken: "test-token",
userRole: "Admin",
userID: "user-1",
modelData: null,
};
describe("RouterSettings", () => {
beforeEach(() => {
vi.clearAllMocks();
vi.mocked(getCallbacksCall).mockResolvedValue(mockCallbacksResponse);
vi.mocked(getRouterSettingsCall).mockResolvedValue(mockRouterSettingsResponse);
vi.mocked(setCallbacksCall).mockResolvedValue({});
});
it("should render nothing when accessToken is null", () => {
const { container } = renderWithProviders(
<RouterSettings {...defaultProps} accessToken={null} />
);
expect(container).toBeEmptyDOMElement();
});
it("should render the Save Changes and Reset buttons when authenticated", () => {
renderWithProviders(<RouterSettings {...defaultProps} />);
expect(screen.getByRole("button", { name: /save changes/i })).toBeInTheDocument();
expect(screen.getByRole("button", { name: /reset/i })).toBeInTheDocument();
});
it("should fetch callbacks and router settings on mount", async () => {
renderWithProviders(<RouterSettings {...defaultProps} />);
await waitFor(() => {
expect(getCallbacksCall).toHaveBeenCalledWith("test-token", "user-1", "Admin");
});
expect(getRouterSettingsCall).toHaveBeenCalledWith("test-token");
});
it("should not fetch data when any required prop is missing", () => {
renderWithProviders(
<RouterSettings {...defaultProps} userRole={null} />
);
expect(getCallbacksCall).not.toHaveBeenCalled();
});
it("should render routing strategies loaded from the API", async () => {
renderWithProviders(<RouterSettings {...defaultProps} />);
await waitFor(() => {
expect(screen.getByTestId("strategy-select")).toBeInTheDocument();
});
const select = screen.getByTestId("strategy-select") as HTMLSelectElement;
const optionValues = Array.from(select.options).map((o) => o.value);
expect(optionValues).toContain("simple-shuffle");
expect(optionValues).toContain("latency-based-routing");
});
it("should call setCallbacksCall with updated settings on Save Changes", async () => {
const user = userEvent.setup();
renderWithProviders(<RouterSettings {...defaultProps} />);
await waitFor(() => {
expect(screen.getByRole("button", { name: /save changes/i })).toBeInTheDocument();
});
await user.click(screen.getByRole("button", { name: /save changes/i }));
expect(setCallbacksCall).toHaveBeenCalledWith(
"test-token",
expect.objectContaining({ router_settings: expect.any(Object) })
);
});
it("should show a success notification after saving", async () => {
const NotificationsManager = await import("@/components/molecules/notifications_manager");
const user = userEvent.setup();
renderWithProviders(<RouterSettings {...defaultProps} />);
await waitFor(() =>
expect(screen.getByRole("button", { name: /save changes/i })).toBeInTheDocument()
);
await user.click(screen.getByRole("button", { name: /save changes/i }));
expect(NotificationsManager.default.success).toHaveBeenCalledWith(
"router settings updated successfully"
);
});
});