From 18afe6ab64019eee2bea8a3221a56c2d873019ab Mon Sep 17 00:00:00 2001 From: Ryan Crabbe Date: Wed, 15 Apr 2026 13:47:13 -0700 Subject: [PATCH] test(ui): update organization_view tests for useOrganization hook Replace the organizationInfoCall mock with a vi.mock of the useOrganizations hook module that stubs useOrganization (and organizationKeys, which the component still imports for invalidation). Each test now sets mockUseOrganization.mockReturnValue(...) instead of mocking the underlying network call, matching the existing pattern in TeamInfo.test.tsx. Renders go through the canonical renderWithProviders helper from tests/test-utils so the component's useQueryClient() call has a QueryClientProvider in context. This is the standard wrapper used by ~96 other test files in the dashboard. Fixes "No QueryClient set" failures in the 4 organization_view tests introduced by the imperative-fetch -> useOrganization migration. --- .../organization/organization_view.test.tsx | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/ui/litellm-dashboard/src/components/organization/organization_view.test.tsx b/ui/litellm-dashboard/src/components/organization/organization_view.test.tsx index a54c7e1fba..8325bea0fc 100644 --- a/ui/litellm-dashboard/src/components/organization/organization_view.test.tsx +++ b/ui/litellm-dashboard/src/components/organization/organization_view.test.tsx @@ -1,14 +1,15 @@ import React from "react"; -import { render, screen, waitFor } from "@testing-library/react"; +import { screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import { vi, test, expect } from "vitest"; +import { vi, test, expect, beforeEach } from "vitest"; +import { renderWithProviders } from "../../../tests/test-utils"; import OrganizationInfoView from "./organization_view"; +import { useOrganization } from "@/app/(dashboard)/hooks/organizations/useOrganizations"; -// Mock networking calls used by the component +// Mock networking calls used by the component's mutation handlers vi.mock("../networking", () => { return { __esModule: true, - organizationInfoCall: vi.fn(), organizationMemberAddCall: vi.fn(), organizationMemberUpdateCall: vi.fn(), organizationMemberDeleteCall: vi.fn(), @@ -16,6 +17,20 @@ vi.mock("../networking", () => { }; }); +// Mock the React Query hook the component now reads org data from. The component +// also imports organizationKeys (used inside mutation handlers for invalidation), +// so provide a stub shape here too. +vi.mock("@/app/(dashboard)/hooks/organizations/useOrganizations", () => ({ + useOrganization: vi.fn(), + organizationKeys: { + all: ["organizations"], + list: () => ["organizations", "list", { params: {} }], + detail: (id: string) => ["organizations", "detail", id], + }, +})); + +const mockUseOrganization = vi.mocked(useOrganization); + // Mock noisy/heavy child components to keep this test focused on render vi.mock("../object_permissions_view", () => ({ __esModule: true, @@ -81,11 +96,14 @@ const mockOrg = { metadata: null, }; -test("renders organization view after loading data", async () => { - const { organizationInfoCall } = await import("../networking"); - (organizationInfoCall as unknown as ReturnType).mockResolvedValueOnce(mockOrg); +beforeEach(() => { + mockUseOrganization.mockReset(); +}); - const { findAllByText } = render( +test("renders organization view after loading data", async () => { + mockUseOrganization.mockReturnValue({ data: mockOrg, isLoading: false } as any); + + const { findAllByText } = renderWithProviders( {}} @@ -103,11 +121,10 @@ test("renders organization view after loading data", async () => { }); test("should display empty state when organization has no members", async () => { - const { organizationInfoCall } = await import("../networking"); - (organizationInfoCall as unknown as ReturnType).mockResolvedValueOnce(mockOrg); + mockUseOrganization.mockReturnValue({ data: mockOrg, isLoading: false } as any); const user = userEvent.setup(); - render( + renderWithProviders( {}} @@ -131,14 +148,13 @@ test("should display empty state when organization has no members", async () => }); test("should display team aliases when teams are available", async () => { - const { organizationInfoCall } = await import("../networking"); const orgWithTeams = { ...mockOrg, teams: [{ team_id: "team_123" }, { team_id: "team_456" }], }; - (organizationInfoCall as unknown as ReturnType).mockResolvedValueOnce(orgWithTeams); + mockUseOrganization.mockReturnValue({ data: orgWithTeams, isLoading: false } as any); - render( + renderWithProviders( {}} @@ -157,7 +173,6 @@ test("should display team aliases when teams are available", async () => { }); test("should display team ID as fallback when alias is not found", async () => { - const { organizationInfoCall } = await import("../networking"); mockUseTeams.mockReturnValueOnce({ data: [ { @@ -171,9 +186,9 @@ test("should display team ID as fallback when alias is not found", async () => { ...mockOrg, teams: [{ team_id: "team_999" }], }; - (organizationInfoCall as unknown as ReturnType).mockResolvedValueOnce(orgWithUnknownTeam); + mockUseOrganization.mockReturnValue({ data: orgWithUnknownTeam, isLoading: false } as any); - render( + renderWithProviders( {}}