diff --git a/src/App.tsx b/src/App.tsx index f0da106f..cbfe765b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -18,6 +18,7 @@ import { } from "./components/ui/breadcrumb"; import { useBreadcrumb } from "./hooks/useBreadcrumb"; import { RouteWorkspace } from "./routes/route-workspace"; +import { Workspaces } from "./components/Workspaces"; function App() { const { data: prompts, isLoading } = usePromptsData(); @@ -59,6 +60,7 @@ function App() { } /> } /> } /> + } /> } diff --git a/src/components/Workspaces.test.tsx b/src/components/Workspaces.test.tsx new file mode 100644 index 00000000..e6f706b0 --- /dev/null +++ b/src/components/Workspaces.test.tsx @@ -0,0 +1,44 @@ +import { render } from "@/lib/test-utils"; +import { screen, waitFor, within } from "@testing-library/react"; +import { describe, expect, it } from "vitest"; +import { Workspaces } from "./Workspaces"; + +describe("Workspaces page", () => { + beforeEach(() => { + render(); + }); + + it("has a title", () => { + expect( + screen.getByRole("heading", { name: /manage workspaces/i }), + ).toBeVisible(); + }); + + it("has a table with the correct columns", () => { + expect(screen.getByRole("columnheader", { name: /name/i })).toBeVisible(); + expect( + screen.getByRole("columnheader", { name: /configuration/i }), + ).toBeVisible(); + }); + + it("has a row for each workspace", async () => { + await waitFor(() => { + expect(screen.getAllByRole("row").length).toBeGreaterThan(1); + }); + + expect( + screen.getByRole("rowheader", { name: /myworkspace/i }), + ).toBeVisible(); + expect( + screen.getByRole("rowheader", { name: /anotherworkspae/i }), + ).toBeVisible(); + + const firstRow = screen.getByRole("row", { name: /myworkspace/i }); + const firstButton = within(firstRow).getByRole("link", { + name: /settings/i, + }); + + expect(firstButton).toBeVisible(); + expect(firstButton).toHaveAttribute("href", "/workspace/myworkspace"); + }); +}); diff --git a/src/components/Workspaces.tsx b/src/components/Workspaces.tsx new file mode 100644 index 00000000..e57787a5 --- /dev/null +++ b/src/components/Workspaces.tsx @@ -0,0 +1,54 @@ +import { useWorkspacesData } from "@/hooks/useWorkspacesData"; +import { + Cell, + Column, + Heading, + LinkButton, + Row, + Table, + TableBody, + TableHeader, +} from "@stacklok/ui-kit"; +import { Settings } from "lucide-react"; + +export function Workspaces() { + const result = useWorkspacesData(); + const workspaces = result.data?.workspaces ?? []; + + return ( +
+ + Manage Workspaces + + + + + + + Name + + + Configuration + + + + + {workspaces.map((workspace) => ( + + {workspace.name} + + + + Settings + + + + ))} + +
+
+ ); +} diff --git a/src/mocks/msw/fixtures/GET_WORKSPACES.json b/src/mocks/msw/fixtures/GET_WORKSPACES.json index e7669999..571fdb2b 100644 --- a/src/mocks/msw/fixtures/GET_WORKSPACES.json +++ b/src/mocks/msw/fixtures/GET_WORKSPACES.json @@ -1,10 +1,20 @@ -[ - { - "name": "workspace-1", - "is_active": true - }, - { - "name": "workspace-2", - "is_active": false - } -] \ No newline at end of file +{ + "workspaces": [ + { + "name": "default", + "is_active": true + }, + { + "name": "myworkspace", + "is_active": false + }, + { + "name": "anotherworkspae", + "is_active": false + }, + { + "name": "favoriteworkspace", + "is_active": false + } + ] +}