Files
headquarter/apps/web/src/pages/WorkspaceDetailPage.test.tsx
T
Developer ce8b5dc86d feat: complete reorganize-long-files cleanup
- Extract tool instance lifecycle endpoints (start/stop/restart/delete) from
  api/tool/tool_instances.py into new api/tool/tool_lifecycle.py.
- Register tool_lifecycle_router in main.py and api/tool/__init__.py.
- Extract inline WorkspaceDetailPage components into
  components/features/workspace/: detail header, tab bars, file/git/tools/settings
  panels. Slim page from ~446 to ~62 lines.
- Update OpenSpec reorganize-long-files tasks to reflect completed work and
  current source state; mark change completed.
- Regenerate project maps.

Quality gates: python3 -m py_compile (backend clean), npm run typecheck,
npm run lint, npm test -- --run (87 passed), pytest workspace integration
and unit tests (27 passed, 1 skipped).
2026-06-12 18:53:23 +00:00

135 lines
2.8 KiB
TypeScript

import "@testing-library/jest-dom/vitest";
import {
cleanup,
fireEvent,
render,
screen,
waitFor,
} from "@testing-library/react";
import { MemoryRouter, Routes, Route } from "react-router-dom";
import { afterEach, describe, expect, it, vi } from "vitest";
afterEach(() => {
cleanup();
});
import { WorkspaceDetailPage } from "./WorkspaceDetailPage";
const mockWorkspaces = [
{
id: "ws-1",
name: "dev",
repo_name: "my-repo",
project_name: "My Project",
branch: "main",
path: "/data/ws/dev",
status: "ready",
instance_count: 0,
},
];
vi.mock("../hooks/use-workspaces", () => ({
useWorkspaces: () => ({
workspaces: mockWorkspaces,
loading: false,
error: null,
refresh: vi.fn(),
}),
}));
vi.mock("../hooks/use-workspace-files", () => ({
useWorkspaceFiles: () => ({
entries: [],
content: null,
currentPath: "",
loading: false,
error: null,
loadFile: vi.fn(),
saveFile: vi.fn(),
navigateTo: vi.fn(),
}),
}));
vi.mock("../hooks/use-workspace-git", () => ({
useWorkspaceGit: () => ({
status: {
branch: "main",
modified: [],
added: [],
deleted: [],
untracked: [],
ahead: 0,
behind: 0,
},
history: [],
branches: ["main"],
currentBranch: "main",
loading: false,
error: null,
commit: vi.fn(),
push: vi.fn(),
pull: vi.fn(),
fetch: vi.fn(),
checkout: vi.fn(),
}),
}));
vi.mock("../hooks/use-workspace-instances", () => ({
useWorkspaceInstances: () => ({
instances: [],
loading: false,
error: null,
refresh: vi.fn(),
}),
}));
vi.mock("../hooks/use-mobile-viewport", () => ({
useMobileViewport: () => false,
}));
describe("WorkspaceDetailPage", () => {
it("renders workspace header and tabs", async () => {
render(
<MemoryRouter initialEntries={["/workspaces/ws-1"]}>
<Routes>
<Route
path="/workspaces/:workspaceId"
element={<WorkspaceDetailPage />}
/>
</Routes>
</MemoryRouter>,
);
await waitFor(() => {
expect(screen.getByText("dev")).toBeInTheDocument();
});
expect(screen.getByText(/my-repo/i)).toBeInTheDocument();
expect(screen.getByRole("tab", { name: /files/i })).toBeInTheDocument();
expect(screen.getByRole("tab", { name: /git/i })).toBeInTheDocument();
expect(screen.getByRole("tab", { name: /tools/i })).toBeInTheDocument();
expect(screen.getByRole("tab", { name: /settings/i })).toBeInTheDocument();
});
it("switches tabs", async () => {
render(
<MemoryRouter initialEntries={["/workspaces/ws-1"]}>
<Routes>
<Route
path="/workspaces/:workspaceId"
element={<WorkspaceDetailPage />}
/>
</Routes>
</MemoryRouter>,
);
await waitFor(() => {
expect(
screen.getByRole("tab", { name: /settings/i }),
).toBeInTheDocument();
});
fireEvent.click(screen.getByRole("tab", { name: /settings/i }));
expect(screen.getByText(/workspace info/i)).toBeInTheDocument();
});
});