litellm/ui/litellm-dashboard/src/components/view_logs/ErrorViewer.test.tsx
yuneng-jiang bead0b7d90 [Test] UI - Logs: Add unit tests for 5 untested view_logs components
Add vitest tests for TypeBadges, ErrorViewer, ConfigInfoMessage, TimeCell, and TruncatedValue covering rendering, user interactions, and edge cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 13:42:30 -07:00

88 lines
3.2 KiB
TypeScript

import { render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import userEvent from "@testing-library/user-event";
import { ErrorViewer } from "./ErrorViewer";
const basicError = {
error_class: "NotFoundError",
error_message: "Model gpt-5 not found",
};
const errorWithTraceback = {
error_class: "AuthenticationError",
error_message: "Invalid API key",
traceback: `Traceback (most recent call last):
File "/app/main.py", line 42, in handle_request
result = await client.chat(model="gpt-4")
File "/app/llms/openai.py", line 100, in chat
response = self._make_request(payload)
File "/app/llms/base.py", line 55, in _make_request
raise AuthenticationError("Invalid API key")`,
};
describe("ErrorViewer", () => {
it("should render error type and message", () => {
render(<ErrorViewer errorInfo={basicError} />);
expect(screen.getByText("NotFoundError")).toBeInTheDocument();
expect(screen.getByText("Model gpt-5 not found")).toBeInTheDocument();
});
it("should show 'Unknown Error' when error_class is missing", () => {
render(<ErrorViewer errorInfo={{ error_message: "something broke" }} />);
expect(screen.getByText("Unknown Error")).toBeInTheDocument();
});
it("should show 'Unknown error occurred' when error_message is missing", () => {
render(<ErrorViewer errorInfo={{ error_class: "RuntimeError" }} />);
expect(screen.getByText("Unknown error occurred")).toBeInTheDocument();
});
it("should render traceback frames when traceback is present", () => {
render(<ErrorViewer errorInfo={errorWithTraceback} />);
expect(screen.getByText("Traceback")).toBeInTheDocument();
expect(screen.getByText("main.py")).toBeInTheDocument();
expect(screen.getByText("openai.py")).toBeInTheDocument();
expect(screen.getByText("base.py")).toBeInTheDocument();
});
it("should expand a frame when clicked", async () => {
const user = userEvent.setup();
render(<ErrorViewer errorInfo={errorWithTraceback} />);
await user.click(screen.getByText("main.py"));
expect(
screen.getByText("result = await client.chat(model=\"gpt-4\")")
).toBeInTheDocument();
});
it("should expand all frames when 'Expand All' is clicked", async () => {
const user = userEvent.setup();
render(<ErrorViewer errorInfo={errorWithTraceback} />);
await user.click(screen.getByText("Expand All"));
expect(screen.getByText("Collapse All")).toBeInTheDocument();
});
it("should copy traceback to clipboard when copy button is clicked", async () => {
const user = userEvent.setup();
const mockWriteText = vi.fn().mockResolvedValue(undefined);
Object.defineProperty(navigator, "clipboard", {
value: { writeText: mockWriteText },
writable: true,
configurable: true,
});
render(<ErrorViewer errorInfo={errorWithTraceback} />);
await user.click(screen.getByTitle("Copy traceback"));
expect(mockWriteText).toHaveBeenCalledWith(errorWithTraceback.traceback);
});
it("should not render traceback section when traceback is absent", () => {
render(<ErrorViewer errorInfo={basicError} />);
expect(screen.queryByText("Traceback")).not.toBeInTheDocument();
});
});