mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-12 23:01:41 +00:00
test(ui): mock useCan so cost-optimization tests don't need a QueryClientProvider
The Cost Optimization view and UsageTab started calling useCan after
255d65192e, which pulls in useIsOrgAdmin -> useOrganizations -> useQuery.
Their unit tests render outside a QueryClientProvider, so every case blew
up with 'No QueryClient set'. Mock useCan directly, wired to the real
hasCapability so the role gating still exercises production logic.
The three page integration tests (guardrails-monitor, memory, workflows)
do run under a QueryClientProvider, so useCan fires an /organization/list
fetch that tripped the loose 'fetchMock not toHaveBeenCalled' assertion.
Narrow those to check only that the specific admin-only endpoint stays
unfetched, which is what the gate actually promises.
Co-authored-by: Krrish Dholakia <krrish-berri-2@users.noreply.github.com>
This commit is contained in:
parent
b0fac57fe4
commit
b0a8caad57
6 changed files with 29 additions and 8 deletions
|
|
@ -1,6 +1,10 @@
|
|||
import { fireEvent, render, waitFor } from "@testing-library/react";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
vi.mock("@/app/(dashboard)/hooks/useCan", () => ({
|
||||
default: () => true,
|
||||
}));
|
||||
|
||||
const mockUserDailyActivityCall = vi.fn();
|
||||
|
||||
vi.mock("@/components/networking", () => ({
|
||||
|
|
|
|||
|
|
@ -1,12 +1,20 @@
|
|||
import { fireEvent, render } from "@testing-library/react";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { hasCapability, type Capability } from "@/utils/capabilities";
|
||||
|
||||
const { useAuthorizedMock } = vi.hoisted(() => ({ useAuthorizedMock: vi.fn() }));
|
||||
const { useAuthorizedMock, useCanMock } = vi.hoisted(() => ({
|
||||
useAuthorizedMock: vi.fn(),
|
||||
useCanMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/app/(dashboard)/hooks/useAuthorized", () => ({
|
||||
default: useAuthorizedMock,
|
||||
}));
|
||||
|
||||
vi.mock("@/app/(dashboard)/hooks/useCan", () => ({
|
||||
default: useCanMock,
|
||||
}));
|
||||
|
||||
vi.mock("./UsageTab", () => ({ __esModule: true, default: () => <div data-testid="usage-tab" /> }));
|
||||
vi.mock("./PromptCompressionTab", () => ({ __esModule: true, default: () => <div data-testid="compression-tab" /> }));
|
||||
vi.mock("./PromptCachingTab", () => ({ __esModule: true, default: () => <div data-testid="caching-tab" /> }));
|
||||
|
|
@ -19,12 +27,14 @@ import CostOptimizationView from "./CostOptimizationView";
|
|||
|
||||
const renderView = (userRole = "Admin") => {
|
||||
useAuthorizedMock.mockReturnValue({ accessToken: "test-token", userId: "u1", userRole });
|
||||
useCanMock.mockImplementation((capability: Capability) => hasCapability(userRole, capability));
|
||||
return render(<CostOptimizationView accessToken="test-token" userId="u1" userRole={userRole} />);
|
||||
};
|
||||
|
||||
describe("CostOptimizationView", () => {
|
||||
beforeEach(() => {
|
||||
useAuthorizedMock.mockReturnValue({ accessToken: "test-token", userId: "u1", userRole: "Admin" });
|
||||
useCanMock.mockImplementation((capability: Capability) => hasCapability("Admin", capability));
|
||||
});
|
||||
|
||||
it("renders the four cost-optimization tabs", () => {
|
||||
|
|
|
|||
|
|
@ -5,14 +5,23 @@ import type { ToolSpendResponse } from "@/components/networking";
|
|||
|
||||
import type { DailyData, SpendMetrics } from "@/components/UsagePage/types";
|
||||
|
||||
import { hasCapability, type Capability } from "@/utils/capabilities";
|
||||
|
||||
const mockGetToolSpend = vi.fn();
|
||||
|
||||
const { useAuthorizedMock } = vi.hoisted(() => ({ useAuthorizedMock: vi.fn() }));
|
||||
const { useAuthorizedMock, useCanMock } = vi.hoisted(() => ({
|
||||
useAuthorizedMock: vi.fn(),
|
||||
useCanMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/app/(dashboard)/hooks/useAuthorized", () => ({
|
||||
default: useAuthorizedMock,
|
||||
}));
|
||||
|
||||
vi.mock("@/app/(dashboard)/hooks/useCan", () => ({
|
||||
default: useCanMock,
|
||||
}));
|
||||
|
||||
vi.mock("@/components/networking", () => ({
|
||||
getToolSpend: (...args: unknown[]) => mockGetToolSpend(...args),
|
||||
}));
|
||||
|
|
@ -106,6 +115,7 @@ const renderWith = (results: DailyData[], options: RenderOptions = {}) => {
|
|||
} = options;
|
||||
mockGetToolSpend.mockResolvedValue(toolSpend);
|
||||
useAuthorizedMock.mockReturnValue({ accessToken: "test-token", userId: "u1", userRole });
|
||||
useCanMock.mockImplementation((capability: Capability) => hasCapability(userRole, capability));
|
||||
return render(
|
||||
<UsageTab
|
||||
accessToken="test-token"
|
||||
|
|
|
|||
|
|
@ -46,8 +46,7 @@ describe("Guardrails Monitor page access by role", () => {
|
|||
renderAs(userRole);
|
||||
|
||||
expect(await screen.findByText("Guardrails Monitor is only available to admin users.")).toBeInTheDocument();
|
||||
await waitFor(() => expect(fetchMock).not.toHaveBeenCalled());
|
||||
expect(requestedUrls().filter((url) => url.includes("/guardrails/usage"))).toEqual([]);
|
||||
await waitFor(() => expect(requestedUrls().filter((url) => url.includes("/guardrails/usage"))).toEqual([]));
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -46,8 +46,7 @@ describe("Memory page access by role", () => {
|
|||
renderAs(userRole);
|
||||
|
||||
expect(await screen.findByText("Memory is only available to admin users.")).toBeInTheDocument();
|
||||
await waitFor(() => expect(fetchMock).not.toHaveBeenCalled());
|
||||
expect(requestedUrls().filter((url) => url.includes("/v1/memory"))).toEqual([]);
|
||||
await waitFor(() => expect(requestedUrls().filter((url) => url.includes("/v1/memory"))).toEqual([]));
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -46,8 +46,7 @@ describe("Workflows page access by role", () => {
|
|||
renderAs(userRole);
|
||||
|
||||
expect(await screen.findByText("Workflow Runs is only available to admin users.")).toBeInTheDocument();
|
||||
await waitFor(() => expect(fetchMock).not.toHaveBeenCalled());
|
||||
expect(requestedUrls().filter((url) => url.includes("/v1/workflows"))).toEqual([]);
|
||||
await waitFor(() => expect(requestedUrls().filter((url) => url.includes("/v1/workflows"))).toEqual([]));
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue