All checks were successful
Build App / build-macos (push) Successful in 2m20s
Build App / build-windows (push) Successful in 3m21s
Build App / build-linux (push) Successful in 5m8s
Build Container / build-container (push) Successful in 1m4s
Sync Release to GitHub / sync-release (release) Successful in 2s
Add Model Context Protocol (MCP) server configuration support. Users can define MCP servers globally (new sidebar tab) and enable them per-project. Enabled servers are injected into containers as MCP_SERVERS_JSON env var and merged into ~/.claude.json by the entrypoint. Backend: McpServer model, McpStore (JSON + atomic writes), 4 CRUD commands, container injection with fingerprint-based recreation detection. Frontend: MCP sidebar tab, McpPanel/McpServerCard components, useMcpServers hook, per-project MCP checkboxes in ProjectCard config. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
58 lines
1.9 KiB
TypeScript
58 lines
1.9 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
import { render, screen } from "@testing-library/react";
|
|
import Sidebar from "./Sidebar";
|
|
|
|
// Mock zustand store
|
|
vi.mock("../../store/appState", () => ({
|
|
useAppState: vi.fn((selector) =>
|
|
selector({
|
|
sidebarView: "projects",
|
|
setSidebarView: vi.fn(),
|
|
})
|
|
),
|
|
}));
|
|
|
|
// Mock child components to isolate Sidebar layout testing
|
|
vi.mock("../projects/ProjectList", () => ({
|
|
default: () => <div data-testid="project-list">ProjectList</div>,
|
|
}));
|
|
vi.mock("../settings/SettingsPanel", () => ({
|
|
default: () => <div data-testid="settings-panel">SettingsPanel</div>,
|
|
}));
|
|
vi.mock("../mcp/McpPanel", () => ({
|
|
default: () => <div data-testid="mcp-panel">McpPanel</div>,
|
|
}));
|
|
|
|
describe("Sidebar", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it("renders the sidebar with content area", () => {
|
|
render(<Sidebar />);
|
|
expect(screen.getByText("Projects")).toBeInTheDocument();
|
|
expect(screen.getByText("Settings")).toBeInTheDocument();
|
|
});
|
|
|
|
it("content area has min-w-0 to prevent flex overflow", () => {
|
|
const { container } = render(<Sidebar />);
|
|
const contentArea = container.querySelector(".overflow-y-auto");
|
|
expect(contentArea).not.toBeNull();
|
|
expect(contentArea!.className).toContain("min-w-0");
|
|
});
|
|
|
|
it("content area has overflow-x-hidden to prevent horizontal scroll", () => {
|
|
const { container } = render(<Sidebar />);
|
|
const contentArea = container.querySelector(".overflow-y-auto");
|
|
expect(contentArea).not.toBeNull();
|
|
expect(contentArea!.className).toContain("overflow-x-hidden");
|
|
});
|
|
|
|
it("sidebar outer container has overflow-hidden", () => {
|
|
const { container } = render(<Sidebar />);
|
|
const sidebar = container.firstElementChild;
|
|
expect(sidebar).not.toBeNull();
|
|
expect(sidebar!.className).toContain("overflow-hidden");
|
|
});
|
|
});
|