2026-09-24 20:48:09 -03:00
|
|
|
import { screen, within } from "@testing-library/react";
|
|
|
|
|
import { describe, expect, it, vi } from "vitest";
|
|
|
|
|
|
|
|
|
|
import { AppSidebar } from "@/components/layout/app-sidebar";
|
|
|
|
|
import { renderWithProviders } from "@/test/test-utils";
|
|
|
|
|
|
|
|
|
|
const canApproveMock = vi.hoisted(() => vi.fn());
|
|
|
|
|
|
|
|
|
|
vi.mock("@/domain/uplifts/use-cases/use-uplifts-can-approve", () => ({
|
|
|
|
|
useUpliftsCanApprove: canApproveMock,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
function renderSidebar(route: string) {
|
|
|
|
|
return renderWithProviders(<AppSidebar collapsed={false} />, {
|
|
|
|
|
route,
|
|
|
|
|
withAuth: false,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function sidebarLinks(): Record<string, string> {
|
|
|
|
|
const nav = document.getElementById("primary-navigation");
|
|
|
|
|
const links = Array.from(within(nav as HTMLElement).getAllByRole("link"));
|
|
|
|
|
return Object.fromEntries(
|
|
|
|
|
links.map((link) => [link.textContent ?? "", link.getAttribute("href") ?? ""]),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
describe("AppSidebar navigation entries", () => {
|
|
|
|
|
it("shows Uplift Approvals for a user the backend says can approve uplifts", () => {
|
|
|
|
|
canApproveMock.mockReturnValue({ data: true });
|
|
|
|
|
|
|
|
|
|
renderSidebar("/");
|
|
|
|
|
const links = sidebarLinks();
|
|
|
|
|
|
|
|
|
|
expect(links["Uplift Approvals"]).toBe("/uplifts");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("hides Uplift Approvals when the backend says the user cannot approve uplifts", () => {
|
|
|
|
|
canApproveMock.mockReturnValue({ data: false });
|
|
|
|
|
|
|
|
|
|
renderSidebar("/");
|
|
|
|
|
const links = sidebarLinks();
|
|
|
|
|
|
|
|
|
|
expect(links["Uplift Approvals"]).toBeUndefined();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("hides Uplift Approvals while the backend answer is still loading", () => {
|
|
|
|
|
canApproveMock.mockReturnValue({ data: undefined });
|
|
|
|
|
|
|
|
|
|
renderSidebar("/");
|
|
|
|
|
const links = sidebarLinks();
|
|
|
|
|
|
|
|
|
|
expect(links["Uplift Approvals"]).toBeUndefined();
|
|
|
|
|
});
|
|
|
|
|
|
2026-09-24 20:50:20 -03:00
|
|
|
it.each([
|
|
|
|
|
[1, "tier 1"],
|
|
|
|
|
[2, "tier 2"],
|
|
|
|
|
])("shows Uplift Approvals when only %s approval is allowed (%s)", (allowedTier) => {
|
|
|
|
|
canApproveMock.mockImplementation((tier: number) => ({ data: tier === allowedTier }));
|
|
|
|
|
|
|
|
|
|
renderSidebar("/");
|
|
|
|
|
const links = sidebarLinks();
|
|
|
|
|
|
|
|
|
|
expect(links["Uplift Approvals"]).toBe("/uplifts");
|
|
|
|
|
expect(canApproveMock).toHaveBeenCalledWith(1);
|
|
|
|
|
expect(canApproveMock).toHaveBeenCalledWith(2);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("hides Uplift Approvals when the can-approve request fails", () => {
|
|
|
|
|
canApproveMock.mockReturnValue({ data: undefined, isError: true, error: new Error("403") });
|
|
|
|
|
|
|
|
|
|
renderSidebar("/");
|
|
|
|
|
const links = sidebarLinks();
|
|
|
|
|
|
|
|
|
|
expect(links["Uplift Approvals"]).toBeUndefined();
|
|
|
|
|
});
|
|
|
|
|
|
2026-09-24 20:53:05 -03:00
|
|
|
it("hides Uplift Approvals when a refetch fails after an earlier approval", () => {
|
|
|
|
|
canApproveMock.mockReturnValue({ data: true, isError: true, error: new Error("403") });
|
|
|
|
|
|
|
|
|
|
renderSidebar("/");
|
|
|
|
|
const links = sidebarLinks();
|
|
|
|
|
|
|
|
|
|
expect(links["Uplift Approvals"]).toBeUndefined();
|
|
|
|
|
});
|
|
|
|
|
|
2026-09-24 20:48:09 -03:00
|
|
|
it("offers Services to every user", () => {
|
|
|
|
|
canApproveMock.mockReturnValue({ data: false });
|
|
|
|
|
|
|
|
|
|
renderSidebar("/");
|
|
|
|
|
const links = sidebarLinks();
|
|
|
|
|
|
|
|
|
|
expect(links["Services"]).toBe("/settings/services");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("highlights the Uplift Approvals entry on /uplifts", () => {
|
|
|
|
|
canApproveMock.mockReturnValue({ data: true });
|
|
|
|
|
|
|
|
|
|
renderSidebar("/uplifts");
|
|
|
|
|
|
|
|
|
|
expect(screen.getByRole("link", { name: "Uplift Approvals" })).toHaveAttribute(
|
|
|
|
|
"aria-current",
|
|
|
|
|
"page",
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("highlights the Services entry on /settings/services", () => {
|
|
|
|
|
canApproveMock.mockReturnValue({ data: false });
|
|
|
|
|
|
|
|
|
|
renderSidebar("/settings/services");
|
|
|
|
|
|
|
|
|
|
expect(screen.getByRole("link", { name: "Services" })).toHaveAttribute("aria-current", "page");
|
|
|
|
|
});
|
|
|
|
|
});
|