diff --git a/ui/litellm-dashboard/src/components/OldTeams.test.tsx b/ui/litellm-dashboard/src/components/OldTeams.test.tsx index 0ca37cc82d7..5c312900888 100644 --- a/ui/litellm-dashboard/src/components/OldTeams.test.tsx +++ b/ui/litellm-dashboard/src/components/OldTeams.test.tsx @@ -72,7 +72,13 @@ vi.mock("./ModelSelect/ModelSelect", () => { onChange={(e) => { // Mock onChange - in real usage this would be handled by Ant Design Select if (onChange) { - onChange(value || []); + const newVal = e.target.value + ? e.target.value + .split(",") + .map((s: string) => s.trim()) + .filter(Boolean) + : []; + onChange(newVal); } }} readOnly @@ -740,6 +746,79 @@ describe("OldTeams - Default Team Settings tab visibility", () => { }); }); +describe("OldTeams - access_group_ids in team create", () => { + beforeEach(() => { + vi.clearAllMocks(); + mockTeamInfoView.mockClear(); + vi.mocked(fetchAvailableModelsForTeamOrKey).mockResolvedValue(["gpt-4", "gpt-3.5-turbo"]); + vi.mocked(fetchMCPAccessGroups).mockResolvedValue([]); + vi.mocked(getGuardrailsList).mockResolvedValue({ guardrails: [] }); + vi.mocked(teamCreateCall).mockResolvedValue({ + team_id: "new-team-1", + team_alias: "Test Team", + models: ["gpt-4"], + organization_id: null, + keys: [], + members_with_roles: [], + spend: 0, + } as any); + mockUseOrganizations.mockReturnValue({ data: [{ organization_id: "org-1", organization_alias: "Org 1", models: [], members: [] }] }); + }); + + it("should pass access_group_ids to teamCreateCall when creating team", async () => { + renderWithQueryClient( + , + ); + + const createButton = screen.getByRole("button", { name: /create new team/i }); + act(() => { + fireEvent.click(createButton); + }); + + await waitFor(() => { + expect(screen.getByLabelText(/team name/i)).toBeInTheDocument(); + }); + + const teamNameInput = screen.getByLabelText(/team name/i); + fireEvent.change(teamNameInput, { target: { value: "Test Team" } }); + + const modelsInput = screen.getByTestId("create-team-models-select"); + fireEvent.change(modelsInput, { target: { value: "gpt-4" } }); + + const additionalSettingsAccordion = screen.getByText("Additional Settings"); + fireEvent.click(additionalSettingsAccordion); + + await waitFor(() => { + expect(screen.getByTestId("access-group-selector")).toBeInTheDocument(); + }); + + const accessGroupInput = screen.getByTestId("access-group-selector"); + fireEvent.change(accessGroupInput, { target: { value: "ag-1,ag-2" } }); + + const createTeamSubmitButton = screen.getByRole("button", { name: /create team/i }); + fireEvent.click(createTeamSubmitButton); + + await waitFor(() => { + expect(teamCreateCall).toHaveBeenCalledWith( + "test-token", + expect.objectContaining({ + team_alias: "Test Team", + models: ["gpt-4"], + access_group_ids: ["ag-1", "ag-2"], + }), + ); + }); + }, { timeout: 30000 }); +}); + describe("OldTeams - models dropdown options", () => { beforeEach(() => { vi.clearAllMocks(); diff --git a/ui/litellm-dashboard/src/components/organisms/create_key_button.test.tsx b/ui/litellm-dashboard/src/components/organisms/create_key_button.test.tsx index bd5e0ee1cbc..54a75837d7b 100644 --- a/ui/litellm-dashboard/src/components/organisms/create_key_button.test.tsx +++ b/ui/litellm-dashboard/src/components/organisms/create_key_button.test.tsx @@ -61,4 +61,54 @@ describe("CreateKey", () => { renderWithProviders(); expect(screen.getByRole("button", { name: /create new key/i })).toBeInTheDocument(); }); + + it("should include access_group_ids in keyCreateCall payload when access groups are selected", async () => { + renderWithProviders(); + + act(() => { + fireEvent.click(screen.getByRole("button", { name: /create new key/i })); + }); + + await waitFor(() => { + expect(screen.getByLabelText(/key name/i)).toBeInTheDocument(); + }); + + fireEvent.change(screen.getByLabelText(/key name/i), { target: { value: "Test Key" } }); + + const optionalSettingsAccordion = screen.getByText("Optional Settings"); + act(() => { + fireEvent.click(optionalSettingsAccordion); + }); + + await waitFor(() => { + expect(screen.getByTestId("access-group-selector")).toBeInTheDocument(); + }); + + fireEvent.change(screen.getByTestId("access-group-selector"), { target: { value: "ag-1,ag-2" } }); + + const modelsCombobox = screen.getAllByRole("combobox").find((el) => el.closest('[class*="ant-form-item"]')?.textContent?.includes("Models")) || + screen.getAllByRole("combobox")[1]; + if (modelsCombobox) { + act(() => fireEvent.mouseDown(modelsCombobox)); + await waitFor(() => { + const allTeamModels = [...document.body.querySelectorAll(".ant-select-item")].find( + (el) => el.textContent?.includes("All Team Models"), + ); + if (allTeamModels) fireEvent.click(allTeamModels); + }); + } + + const createButton = screen.getByRole("button", { name: /create key/i }); + act(() => fireEvent.click(createButton)); + + await waitFor( + () => { + expect(mockKeyCreateCall).toHaveBeenCalled(); + const formValues = mockKeyCreateCall.mock.calls[0][2]; + expect(formValues).toHaveProperty("access_group_ids"); + expect(formValues.access_group_ids).toEqual(["ag-1", "ag-2"]); + }, + { timeout: 15000 }, + ); + }, { timeout: 30000 }); });