chore(repo): reinitialize repository
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
import { screen, waitFor, within } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { renderWithProviders } from "../test/renderWithProviders";
|
||||
import WorkspaceSelector from "./WorkspaceSelector";
|
||||
|
||||
function makeWorkspace(name: string, overrides: Record<string, unknown> = {}) {
|
||||
return {
|
||||
id: `ws-${name}`,
|
||||
name,
|
||||
slug: name,
|
||||
path: `/workspaces/${name}`,
|
||||
runtime_backend: "container",
|
||||
container_name: `codex-${name}`,
|
||||
status: "active",
|
||||
provision_state: "ready",
|
||||
provision_error: "",
|
||||
last_provisioned_at: "",
|
||||
container_state: "running",
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe("WorkspaceSelector", () => {
|
||||
it("shows a loading label while workspaces are being resolved", () => {
|
||||
renderWithProviders(
|
||||
<WorkspaceSelector value="" workspaces={[]} loading onChange={vi.fn()} />,
|
||||
{ locale: "en" },
|
||||
);
|
||||
|
||||
expect(screen.getByRole("button", { name: /loading workspaces/i })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("lets the user switch to another existing workspace", async () => {
|
||||
const onChange = vi.fn();
|
||||
const user = userEvent.setup();
|
||||
|
||||
renderWithProviders(
|
||||
<WorkspaceSelector
|
||||
value="alpha"
|
||||
workspaces={[makeWorkspace("alpha"), makeWorkspace("beta")]}
|
||||
onChange={onChange}
|
||||
/>,
|
||||
{ locale: "en" },
|
||||
);
|
||||
|
||||
await user.click(await screen.findByRole("button", { name: /alpha/i }));
|
||||
|
||||
const betaOption = (await screen.findByText("beta")).closest("button");
|
||||
if (!betaOption) {
|
||||
throw new Error("beta workspace option not found");
|
||||
}
|
||||
|
||||
await user.click(betaOption);
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith("beta");
|
||||
});
|
||||
|
||||
it("updates the trigger label when the active workspace prop changes", async () => {
|
||||
const { rerender } = renderWithProviders(
|
||||
<WorkspaceSelector
|
||||
value="alpha"
|
||||
workspaces={[makeWorkspace("alpha"), makeWorkspace("beta")]}
|
||||
onChange={vi.fn()}
|
||||
/>,
|
||||
{ locale: "en" },
|
||||
);
|
||||
|
||||
expect(await screen.findByRole("button", { name: /alpha/i })).toBeInTheDocument();
|
||||
|
||||
rerender(
|
||||
<WorkspaceSelector
|
||||
value="beta"
|
||||
workspaces={[makeWorkspace("alpha"), makeWorkspace("beta")]}
|
||||
onChange={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(await screen.findByRole("button", { name: /beta/i })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("opens a labeled dialog, focuses the active project, and restores focus on escape", async () => {
|
||||
const user = userEvent.setup();
|
||||
|
||||
renderWithProviders(
|
||||
<WorkspaceSelector
|
||||
value="alpha"
|
||||
workspaces={[makeWorkspace("alpha"), makeWorkspace("beta")]}
|
||||
onChange={vi.fn()}
|
||||
/>,
|
||||
{ locale: "en" },
|
||||
);
|
||||
|
||||
const trigger = await screen.findByRole("button", { name: /alpha/i });
|
||||
expect(trigger).toHaveAttribute("aria-expanded", "false");
|
||||
|
||||
await user.click(trigger);
|
||||
expect(trigger).toHaveAttribute("aria-expanded", "true");
|
||||
|
||||
const dialog = await screen.findByRole("dialog", { name: "Workspaces" });
|
||||
await waitFor(() => {
|
||||
expect(within(dialog).getByRole("button", { name: /alpha/i })).toHaveFocus();
|
||||
});
|
||||
|
||||
for (let i = 0; i < 4; i += 1) {
|
||||
await user.tab();
|
||||
expect(dialog.contains(document.activeElement)).toBe(true);
|
||||
}
|
||||
|
||||
await user.keyboard("{Escape}");
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(trigger).toHaveFocus();
|
||||
});
|
||||
expect(trigger).toHaveAttribute("aria-expanded", "false");
|
||||
});
|
||||
|
||||
it("keeps the current workspace selected when the next workspace has no id", async () => {
|
||||
const onChange = vi.fn();
|
||||
const user = userEvent.setup();
|
||||
|
||||
renderWithProviders(
|
||||
<WorkspaceSelector
|
||||
value="alpha"
|
||||
workspaces={[
|
||||
makeWorkspace("alpha"),
|
||||
makeWorkspace("beta", {
|
||||
id: "",
|
||||
provision_state: "failed",
|
||||
container_state: "missing",
|
||||
}),
|
||||
]}
|
||||
onChange={onChange}
|
||||
/>,
|
||||
{ locale: "en" },
|
||||
);
|
||||
|
||||
await user.click(await screen.findByRole("button", { name: /alpha/i }));
|
||||
|
||||
const betaOption = (await screen.findByText("beta")).closest("button");
|
||||
if (!betaOption) {
|
||||
throw new Error("beta workspace option not found");
|
||||
}
|
||||
|
||||
await user.click(betaOption);
|
||||
|
||||
expect(await screen.findByText("Couldn't prepare the workspace runtime.")).toBeInTheDocument();
|
||||
expect(onChange).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("shows a header-managed empty state when no workspaces exist", async () => {
|
||||
const user = userEvent.setup();
|
||||
|
||||
renderWithProviders(
|
||||
<WorkspaceSelector value="" workspaces={[]} onChange={vi.fn()} />,
|
||||
{ locale: "en" },
|
||||
);
|
||||
|
||||
await user.click(await screen.findByRole("button", { name: /no workspaces/i }));
|
||||
|
||||
expect(await screen.findByText("No workspaces yet")).toBeInTheDocument();
|
||||
expect(screen.getByText("Workspaces must be created outside the header picker.")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user