feat(web): add teams settings page (MS21-UI-005) (#576)
All checks were successful
ci/woodpecker/push/web Pipeline was successful

Co-authored-by: Jason Woltje <jason@diversecanvas.com>
Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #576.
This commit is contained in:
2026-02-28 22:12:04 +00:00
committed by jason.woltje
parent 31814f181a
commit 307639eca0
6 changed files with 513 additions and 328 deletions

View File

@@ -0,0 +1,76 @@
import type { ReactElement, ReactNode } from "react";
import type { TeamRecord } from "@/lib/api/teams";
import { render, screen } from "@testing-library/react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { fetchTeams } from "@/lib/api/teams";
import TeamsSettingsPage from "./page";
vi.mock("next/link", () => ({
default: function LinkMock({
children,
href,
}: {
children: ReactNode;
href: string;
}): ReactElement {
return <a href={href}>{children}</a>;
},
}));
vi.mock("@/lib/api/teams", () => ({
fetchTeams: vi.fn(),
createTeam: vi.fn(),
}));
const fetchTeamsMock = vi.mocked(fetchTeams);
const baseTeam: TeamRecord = {
id: "team-1",
workspaceId: "workspace-1",
name: "Platform Team",
description: "Owns platform services",
metadata: {},
createdAt: "2026-02-01T00:00:00.000Z",
updatedAt: "2026-02-01T00:00:00.000Z",
_count: {
members: 3,
},
};
describe("TeamsSettingsPage", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("loads and renders teams from the API", async () => {
fetchTeamsMock.mockResolvedValue([baseTeam]);
render(<TeamsSettingsPage />);
expect(screen.getByText("Loading teams...")).toBeInTheDocument();
expect(await screen.findByText("Your Teams (1)")).toBeInTheDocument();
expect(screen.getByText("Platform Team")).toBeInTheDocument();
expect(fetchTeamsMock).toHaveBeenCalledTimes(1);
});
it("shows empty state when the API returns no teams", async () => {
fetchTeamsMock.mockResolvedValue([]);
render(<TeamsSettingsPage />);
expect(await screen.findByText("Your Teams (0)")).toBeInTheDocument();
expect(screen.getByText("No teams yet")).toBeInTheDocument();
});
it("shows error state and does not show empty state", async () => {
fetchTeamsMock.mockRejectedValue(new Error("Unable to load teams"));
render(<TeamsSettingsPage />);
expect(await screen.findByText("Unable to load teams")).toBeInTheDocument();
expect(screen.queryByText("No teams yet")).not.toBeInTheDocument();
});
});