Merge pull request #25468 from BerriAI/litellm_/compassionate-shannon

[Test] UI - Unit tests: raise global vitest timeout and remove per-test overrides
This commit is contained in:
yuneng-jiang 2026-04-09 21:35:43 -07:00 committed by GitHub
commit 9e6d2d2069
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 1030 additions and 1032 deletions

View file

@ -131,7 +131,7 @@ describe("ModelsAndEndpointsView", () => {
</QueryClientProvider>,
);
expect(await findByText("Model Management", {}, { timeout: 10000 })).toBeInTheDocument();
}, 15000);
});
it("should show Missing provider banner by default", async () => {
localStorageMock.clear();
@ -149,7 +149,7 @@ describe("ModelsAndEndpointsView", () => {
</QueryClientProvider>,
);
expect(await findByText("Missing a provider?", {}, { timeout: 10000 })).toBeInTheDocument();
}, 15000);
});
it("should hide Missing provider banner when dismiss button is clicked and persist to localStorage", async () => {
localStorageMock.clear();
@ -180,7 +180,7 @@ describe("ModelsAndEndpointsView", () => {
// LocalStorage should be updated
expect(localStorageMock.getItem("hideMissingProviderBanner")).toBe("true");
}, 15000);
});
it("should show compact Request Provider button when banner is dismissed", async () => {
// Set localStorage to hide banner
@ -209,7 +209,7 @@ describe("ModelsAndEndpointsView", () => {
const requestProviderLinks = document.querySelectorAll('a[href="https://models.litellm.ai/?request=true"]');
// There should be a compact button when banner is hidden
expect(requestProviderLinks.length).toBeGreaterThan(0);
}, 15000);
});
it("should pass model IDs (not model names) to HealthCheckComponent as all_models_on_proxy", async () => {
mockHealthCheckComponent.mockClear();

View file

@ -51,7 +51,7 @@ function renderWithProviders(ui: React.ReactElement) {
return render(<QueryClientProvider client={qc}>{ui}</QueryClientProvider>);
}
describe("CreateUserButton", { timeout: 20000 }, () => {
describe("CreateUserButton", () => {
beforeEach(() => {
vi.clearAllMocks();
mockGetProxyUISettings.mockResolvedValue({
@ -62,288 +62,296 @@ describe("CreateUserButton", { timeout: 20000 }, () => {
});
});
it("should render the create user form when embedded", () => {
renderWithProviders(
<CreateUserButton {...defaultProps} isEmbedded />,
);
expect(screen.getByRole("button", { name: /create user/i })).toBeInTheDocument();
});
describe("rendering and visibility", () => {
it("should render the create user form when embedded", () => {
renderWithProviders(
<CreateUserButton {...defaultProps} isEmbedded />,
);
expect(screen.getByRole("button", { name: /create user/i })).toBeInTheDocument();
});
it("should render the invite user button when not embedded", async () => {
renderWithProviders(<CreateUserButton {...defaultProps} />);
await waitFor(() => {
expect(screen.getByRole("button", { name: /\+ invite user/i })).toBeInTheDocument();
it("should render the invite user button when not embedded", async () => {
renderWithProviders(<CreateUserButton {...defaultProps} />);
await waitFor(() => {
expect(screen.getByRole("button", { name: /\+ invite user/i })).toBeInTheDocument();
});
});
it("should open the invite modal when invite user button is clicked", async () => {
const user = userEvent.setup();
renderWithProviders(<CreateUserButton {...defaultProps} />);
await waitFor(() => {
expect(screen.getByRole("button", { name: /\+ invite user/i })).toBeInTheDocument();
});
await user.click(screen.getByRole("button", { name: /\+ invite user/i }));
const dialog = screen.getByRole("dialog", { name: /invite user/i });
expect(dialog).toBeInTheDocument();
expect(within(dialog).getByRole("button", { name: /invite user/i })).toBeInTheDocument();
});
it("should display email invitations info message in embedded mode", () => {
renderWithProviders(<CreateUserButton {...defaultProps} isEmbedded />);
expect(screen.getByText("Email invitations")).toBeInTheDocument();
});
it("should display user role options when possibleUIRoles is provided", async () => {
const possibleUIRoles = {
proxy_admin: { ui_label: "Admin", description: "Full access" },
proxy_user: { ui_label: "User", description: "Limited access" },
};
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={possibleUIRoles} isEmbedded />,
);
await userEvent.click(screen.getByRole("combobox", { name: /user role/i }));
expect(screen.getByText("Admin")).toBeInTheDocument();
expect(screen.getByText("User")).toBeInTheDocument();
});
it("should close modal when cancel is clicked in standalone mode", async () => {
const user = userEvent.setup();
renderWithProviders(<CreateUserButton {...defaultProps} />);
await waitFor(() => {
expect(screen.getByRole("button", { name: /\+ invite user/i })).toBeInTheDocument();
});
await user.click(screen.getByRole("button", { name: /\+ invite user/i }));
expect(screen.getByRole("dialog", { name: /invite user/i })).toBeInTheDocument();
const dialog = screen.getByRole("dialog", { name: /invite user/i });
await user.click(within(dialog).getByRole("button", { name: /close/i }));
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
});
});
it("should open the invite modal when invite user button is clicked", async () => {
const user = userEvent.setup();
renderWithProviders(<CreateUserButton {...defaultProps} />);
await waitFor(() => {
expect(screen.getByRole("button", { name: /\+ invite user/i })).toBeInTheDocument();
describe("embedded mode submission", () => {
it("should call userCreateCall when form is submitted in embedded mode", async () => {
const user = userEvent.setup();
mockUserCreateCall.mockResolvedValue({ data: { user_id: "new-user-123" } });
mockInvitationCreateCall.mockResolvedValue({
id: "inv-1",
user_id: "new-user-123",
has_user_setup_sso: false,
} as any);
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} isEmbedded />,
);
await user.type(screen.getByLabelText(/user email/i), "test@example.com");
await user.click(screen.getByRole("combobox", { name: /user role/i }));
await user.click(screen.getByText("User"));
await user.click(screen.getByRole("button", { name: /create user/i }));
await waitFor(() => {
expect(mockUserCreateCall).toHaveBeenCalledWith("token", null, expect.objectContaining({
user_email: "test@example.com",
user_role: "proxy_user",
}));
});
});
await user.click(screen.getByRole("button", { name: /\+ invite user/i }));
const dialog = screen.getByRole("dialog", { name: /invite user/i });
expect(dialog).toBeInTheDocument();
expect(within(dialog).getByRole("button", { name: /invite user/i })).toBeInTheDocument();
});
it("should display email invitations info message in embedded mode", () => {
renderWithProviders(<CreateUserButton {...defaultProps} isEmbedded />);
expect(screen.getByText("Email invitations")).toBeInTheDocument();
});
it("should call onUserCreated callback when user is created in embedded mode", async () => {
const user = userEvent.setup();
const onUserCreated = vi.fn();
mockUserCreateCall.mockResolvedValue({ data: { user_id: "new-user-456" } });
it("should display user role options when possibleUIRoles is provided", async () => {
const possibleUIRoles = {
proxy_admin: { ui_label: "Admin", description: "Full access" },
proxy_user: { ui_label: "User", description: "Limited access" },
};
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={possibleUIRoles} isEmbedded />,
);
await userEvent.click(screen.getByRole("combobox", { name: /user role/i }));
expect(screen.getByText("Admin")).toBeInTheDocument();
expect(screen.getByText("User")).toBeInTheDocument();
});
renderWithProviders(
<CreateUserButton {...defaultProps} onUserCreated={onUserCreated} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} isEmbedded />,
);
it("should call userCreateCall when form is submitted in embedded mode", async () => {
const user = userEvent.setup();
mockUserCreateCall.mockResolvedValue({ data: { user_id: "new-user-123" } });
mockInvitationCreateCall.mockResolvedValue({
id: "inv-1",
user_id: "new-user-123",
has_user_setup_sso: false,
} as any);
await user.type(screen.getByLabelText(/user email/i), "embedded@example.com");
await user.click(screen.getByRole("combobox", { name: /user role/i }));
await user.click(screen.getByText("User"));
await user.click(screen.getByRole("button", { name: /create user/i }));
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} isEmbedded />,
);
await waitFor(() => {
expect(onUserCreated).toHaveBeenCalledWith("new-user-456");
});
});
await user.type(screen.getByLabelText(/user email/i), "test@example.com");
await user.click(screen.getByRole("combobox", { name: /user role/i }));
await user.click(screen.getByText("User"));
await user.click(screen.getByRole("button", { name: /create user/i }));
it("should show error notification when user creation fails", async () => {
const user = userEvent.setup();
mockUserCreateCall.mockRejectedValue({ response: { data: { detail: "Email already exists" } } });
await waitFor(() => {
expect(mockUserCreateCall).toHaveBeenCalledWith("token", null, expect.objectContaining({
user_email: "test@example.com",
user_role: "proxy_user",
}));
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} isEmbedded />,
);
await user.type(screen.getByLabelText(/user email/i), "duplicate@example.com");
await user.click(screen.getByRole("combobox", { name: /user role/i }));
await user.click(screen.getByText("User"));
await user.click(screen.getByRole("button", { name: /create user/i }));
await waitFor(() => {
expect(mockNotificationsManager.fromBackend).toHaveBeenCalledWith("Email already exists");
});
});
it("should show info notification when making API call", async () => {
const user = userEvent.setup();
mockUserCreateCall.mockResolvedValue({ data: { user_id: "new-user" } });
mockInvitationCreateCall.mockResolvedValue({
id: "inv-3",
user_id: "new-user",
has_user_setup_sso: false,
} as any);
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} isEmbedded />,
);
await user.type(screen.getByLabelText(/user email/i), "info@example.com");
await user.click(screen.getByRole("combobox", { name: /user role/i }));
await user.click(screen.getByText("User"));
await user.click(screen.getByRole("button", { name: /create user/i }));
await waitFor(() => {
expect(mockNotificationsManager.info).toHaveBeenCalledWith("Making API Call");
});
});
});
it("should call onUserCreated callback when user is created in embedded mode", async () => {
const user = userEvent.setup();
const onUserCreated = vi.fn();
mockUserCreateCall.mockResolvedValue({ data: { user_id: "new-user-456" } });
describe("standalone mode submission", () => {
it("should show success notification when user is created successfully in standalone mode", async () => {
const user = userEvent.setup();
mockUserCreateCall.mockResolvedValue({ data: { user_id: "new-user-789" } });
mockInvitationCreateCall.mockResolvedValue({
id: "inv-2",
user_id: "new-user-789",
has_user_setup_sso: false,
} as any);
renderWithProviders(
<CreateUserButton {...defaultProps} onUserCreated={onUserCreated} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} isEmbedded />,
);
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} />,
);
await user.type(screen.getByLabelText(/user email/i), "embedded@example.com");
await user.click(screen.getByRole("combobox", { name: /user role/i }));
await user.click(screen.getByText("User"));
await user.click(screen.getByRole("button", { name: /create user/i }));
await waitFor(() => {
expect(screen.getByRole("button", { name: /\+ invite user/i })).toBeInTheDocument();
});
await user.click(screen.getByRole("button", { name: /\+ invite user/i }));
await waitFor(() => {
expect(onUserCreated).toHaveBeenCalledWith("new-user-456");
const dialog = screen.getByRole("dialog", { name: /invite user/i });
await user.type(within(dialog).getByLabelText(/user email/i), "standalone@example.com");
await user.click(within(dialog).getByRole("combobox", { name: /global proxy role/i }));
await user.click(screen.getByText("User"));
await user.click(within(dialog).getByRole("button", { name: /invite user/i }));
await waitFor(() => {
expect(mockNotificationsManager.success).toHaveBeenCalledWith("API user Created");
});
});
it("should show onboarding modal when user is created and SSO is disabled", async () => {
const user = userEvent.setup();
mockUserCreateCall.mockResolvedValue({ data: { user_id: "sso-user" } });
mockInvitationCreateCall.mockResolvedValue({
id: "inv-sso",
user_id: "sso-user",
has_user_setup_sso: false,
} as any);
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} />,
);
await waitFor(() => {
expect(screen.getByRole("button", { name: /\+ invite user/i })).toBeInTheDocument();
});
await user.click(screen.getByRole("button", { name: /\+ invite user/i }));
const dialog = screen.getByRole("dialog", { name: /invite user/i });
await user.type(within(dialog).getByLabelText(/user email/i), "sso@example.com");
await user.click(within(dialog).getByRole("combobox", { name: /global proxy role/i }));
await user.click(screen.getByText("User"));
await user.click(within(dialog).getByRole("button", { name: /invite user/i }));
await waitFor(() => {
expect(mockInvitationCreateCall).toHaveBeenCalledWith("token", "sso-user");
});
await waitFor(() => {
expect(mockNotificationsManager.success).toHaveBeenCalledWith("API user Created");
});
});
});
it("should show success notification when user is created successfully in standalone mode", async () => {
const user = userEvent.setup();
mockUserCreateCall.mockResolvedValue({ data: { user_id: "new-user-789" } });
mockInvitationCreateCall.mockResolvedValue({
id: "inv-2",
user_id: "new-user-789",
has_user_setup_sso: false,
} as any);
describe("organizations", () => {
it("should send organizations list in POST body when organizations are selected", async () => {
const { useOrganizations } = await import("@/app/(dashboard)/hooks/organizations/useOrganizations");
vi.mocked(useOrganizations).mockReturnValue({
data: [{ organization_id: "org-1", organization_alias: "My Org" }],
isLoading: false,
} as any);
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} />,
);
const user = userEvent.setup();
mockUserCreateCall.mockResolvedValue({ data: { user_id: "org-user" } });
mockInvitationCreateCall.mockResolvedValue({
id: "inv-org",
user_id: "org-user",
has_user_setup_sso: false,
} as any);
await waitFor(() => {
expect(screen.getByRole("button", { name: /\+ invite user/i })).toBeInTheDocument();
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} />,
);
await waitFor(() => {
expect(screen.getByRole("button", { name: /\+ invite user/i })).toBeInTheDocument();
});
await user.click(screen.getByRole("button", { name: /\+ invite user/i }));
const dialog = screen.getByRole("dialog", { name: /invite user/i });
await user.type(within(dialog).getByLabelText(/user email/i), "org@example.com");
await user.click(within(dialog).getByRole("combobox", { name: /global proxy role/i }));
await user.click(screen.getByText("User"));
// Select org from the dropdown
const orgSelect = within(dialog).getByRole("combobox", { name: /organization/i });
await user.click(orgSelect);
await user.click(screen.getByText("My Org (org-1)"));
await user.click(within(dialog).getByRole("button", { name: /invite user/i }));
await waitFor(() => {
expect(mockUserCreateCall).toHaveBeenCalledWith("token", null, expect.objectContaining({
organizations: ["org-1"],
}));
});
});
await user.click(screen.getByRole("button", { name: /\+ invite user/i }));
const dialog = screen.getByRole("dialog", { name: /invite user/i });
await user.type(within(dialog).getByLabelText(/user email/i), "standalone@example.com");
await user.click(within(dialog).getByRole("combobox", { name: /global proxy role/i }));
await user.click(screen.getByText("User"));
await user.click(within(dialog).getByRole("button", { name: /invite user/i }));
it("should not call organizationMemberAddCall after user creation", async () => {
const { useOrganizations } = await import("@/app/(dashboard)/hooks/organizations/useOrganizations");
vi.mocked(useOrganizations).mockReturnValue({
data: [{ organization_id: "org-1", organization_alias: "My Org" }],
isLoading: false,
} as any);
await waitFor(() => {
expect(mockNotificationsManager.success).toHaveBeenCalledWith("API user Created");
const user = userEvent.setup();
mockUserCreateCall.mockResolvedValue({ data: { user_id: "no-member-add-user" } });
mockInvitationCreateCall.mockResolvedValue({
id: "inv-nma",
user_id: "no-member-add-user",
has_user_setup_sso: false,
} as any);
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} />,
);
await waitFor(() => {
expect(screen.getByRole("button", { name: /\+ invite user/i })).toBeInTheDocument();
});
await user.click(screen.getByRole("button", { name: /\+ invite user/i }));
const dialog = screen.getByRole("dialog", { name: /invite user/i });
await user.type(within(dialog).getByLabelText(/user email/i), "nomemberadd@example.com");
await user.click(within(dialog).getByRole("combobox", { name: /global proxy role/i }));
await user.click(screen.getByText("User"));
await user.click(within(dialog).getByRole("button", { name: /invite user/i }));
await waitFor(() => {
expect(mockUserCreateCall).toHaveBeenCalled();
});
expect(mockOrganizationMemberAddCall).not.toHaveBeenCalled();
});
});
it("should show error notification when user creation fails", async () => {
const user = userEvent.setup();
mockUserCreateCall.mockRejectedValue({ response: { data: { detail: "Email already exists" } } });
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} isEmbedded />,
);
await user.type(screen.getByLabelText(/user email/i), "duplicate@example.com");
await user.click(screen.getByRole("combobox", { name: /user role/i }));
await user.click(screen.getByText("User"));
await user.click(screen.getByRole("button", { name: /create user/i }));
await waitFor(() => {
expect(mockNotificationsManager.fromBackend).toHaveBeenCalledWith("Email already exists");
});
});
it("should show info notification when making API call", async () => {
const user = userEvent.setup();
mockUserCreateCall.mockResolvedValue({ data: { user_id: "new-user" } });
mockInvitationCreateCall.mockResolvedValue({
id: "inv-3",
user_id: "new-user",
has_user_setup_sso: false,
} as any);
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} isEmbedded />,
);
await user.type(screen.getByLabelText(/user email/i), "info@example.com");
await user.click(screen.getByRole("combobox", { name: /user role/i }));
await user.click(screen.getByText("User"));
await user.click(screen.getByRole("button", { name: /create user/i }));
await waitFor(() => {
expect(mockNotificationsManager.info).toHaveBeenCalledWith("Making API Call");
});
});
it("should close modal when cancel is clicked in standalone mode", async () => {
const user = userEvent.setup();
renderWithProviders(<CreateUserButton {...defaultProps} />);
await waitFor(() => {
expect(screen.getByRole("button", { name: /\+ invite user/i })).toBeInTheDocument();
});
await user.click(screen.getByRole("button", { name: /\+ invite user/i }));
expect(screen.getByRole("dialog", { name: /invite user/i })).toBeInTheDocument();
const dialog = screen.getByRole("dialog", { name: /invite user/i });
await user.click(within(dialog).getByRole("button", { name: /close/i }));
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
});
it("should show onboarding modal when user is created and SSO is disabled", async () => {
const user = userEvent.setup();
mockUserCreateCall.mockResolvedValue({ data: { user_id: "sso-user" } });
mockInvitationCreateCall.mockResolvedValue({
id: "inv-sso",
user_id: "sso-user",
has_user_setup_sso: false,
} as any);
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} />,
);
await waitFor(() => {
expect(screen.getByRole("button", { name: /\+ invite user/i })).toBeInTheDocument();
});
await user.click(screen.getByRole("button", { name: /\+ invite user/i }));
const dialog = screen.getByRole("dialog", { name: /invite user/i });
await user.type(within(dialog).getByLabelText(/user email/i), "sso@example.com");
await user.click(within(dialog).getByRole("combobox", { name: /global proxy role/i }));
await user.click(screen.getByText("User"));
await user.click(within(dialog).getByRole("button", { name: /invite user/i }));
await waitFor(() => {
expect(mockInvitationCreateCall).toHaveBeenCalledWith("token", "sso-user");
});
await waitFor(() => {
expect(mockNotificationsManager.success).toHaveBeenCalledWith("API user Created");
});
});
it("should send organizations list in POST body when organizations are selected", async () => {
const { useOrganizations } = await import("@/app/(dashboard)/hooks/organizations/useOrganizations");
vi.mocked(useOrganizations).mockReturnValue({
data: [{ organization_id: "org-1", organization_alias: "My Org" }],
isLoading: false,
} as any);
const user = userEvent.setup();
mockUserCreateCall.mockResolvedValue({ data: { user_id: "org-user" } });
mockInvitationCreateCall.mockResolvedValue({
id: "inv-org",
user_id: "org-user",
has_user_setup_sso: false,
} as any);
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} />,
);
await waitFor(() => {
expect(screen.getByRole("button", { name: /\+ invite user/i })).toBeInTheDocument();
});
await user.click(screen.getByRole("button", { name: /\+ invite user/i }));
const dialog = screen.getByRole("dialog", { name: /invite user/i });
await user.type(within(dialog).getByLabelText(/user email/i), "org@example.com");
await user.click(within(dialog).getByRole("combobox", { name: /global proxy role/i }));
await user.click(screen.getByText("User"));
// Select org from the dropdown
const orgSelect = within(dialog).getByRole("combobox", { name: /organization/i });
await user.click(orgSelect);
await user.click(screen.getByText("My Org (org-1)"));
await user.click(within(dialog).getByRole("button", { name: /invite user/i }));
await waitFor(() => {
expect(mockUserCreateCall).toHaveBeenCalledWith("token", null, expect.objectContaining({
organizations: ["org-1"],
}));
});
});
it("should not call organizationMemberAddCall after user creation", async () => {
const { useOrganizations } = await import("@/app/(dashboard)/hooks/organizations/useOrganizations");
vi.mocked(useOrganizations).mockReturnValue({
data: [{ organization_id: "org-1", organization_alias: "My Org" }],
isLoading: false,
} as any);
const user = userEvent.setup();
mockUserCreateCall.mockResolvedValue({ data: { user_id: "no-member-add-user" } });
mockInvitationCreateCall.mockResolvedValue({
id: "inv-nma",
user_id: "no-member-add-user",
has_user_setup_sso: false,
} as any);
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} />,
);
await waitFor(() => {
expect(screen.getByRole("button", { name: /\+ invite user/i })).toBeInTheDocument();
});
await user.click(screen.getByRole("button", { name: /\+ invite user/i }));
const dialog = screen.getByRole("dialog", { name: /invite user/i });
await user.type(within(dialog).getByLabelText(/user email/i), "nomemberadd@example.com");
await user.click(within(dialog).getByRole("combobox", { name: /global proxy role/i }));
await user.click(screen.getByText("User"));
await user.click(within(dialog).getByRole("button", { name: /invite user/i }));
await waitFor(() => {
expect(mockUserCreateCall).toHaveBeenCalled();
});
expect(mockOrganizationMemberAddCall).not.toHaveBeenCalled();
});
});

View file

@ -843,7 +843,7 @@ describe("OldTeams - access_group_ids in team create", () => {
}),
);
});
}, { timeout: 30000 });
});
});
describe("OldTeams - models dropdown options", () => {

View file

@ -175,7 +175,7 @@ describe("Add Model Tab", () => {
);
expect(await screen.findByRole("tab", { name: "Add Model" })).toBeInTheDocument();
}, 10000); // This test is flaky, adding a timeout until we find a better solution
});
it("should display both Add Model and Add Auto Router tabs", async () => {
const props = createTestProps();
@ -269,7 +269,7 @@ describe("Add Model Tab", () => {
},
{ timeout: 10000 },
);
}, 15000); // 15 second timeout to allow waitFor to complete
});
it("should show team selection when team-only switch is enabled", async () => {
const props = createTestProps();

View file

@ -150,151 +150,139 @@ describe("CreateMCPServer", () => {
});
});
it(
"should not require auth value when creating a server with API Key auth type",
{ timeout: 15000 },
async () => {
await selectHttpTransport();
it("should not require auth value when creating a server with API Key auth type", async () => {
await selectHttpTransport();
const user = userEvent.setup({ delay: null });
const user = userEvent.setup({ delay: null });
// Fill in server name (use id to avoid duplicate placeholder)
const nameInput = getServerNameInput();
await user.type(nameInput, "Test_Server");
// Fill in server name (use id to avoid duplicate placeholder)
const nameInput = getServerNameInput();
await user.type(nameInput, "Test_Server");
// Fill in URL
const urlInput = screen.getByPlaceholderText("https://your-mcp-server.com");
await user.type(urlInput, "https://example.com/mcp");
// Fill in URL
const urlInput = screen.getByPlaceholderText("https://your-mcp-server.com");
await user.type(urlInput, "https://example.com/mcp");
// Select API Key auth type
await selectAntOption("Authentication", "API Key");
// Select API Key auth type
await selectAntOption("Authentication", "API Key");
await waitFor(() => {
expect(screen.getByText("Authentication Value")).toBeInTheDocument();
});
await waitFor(() => {
expect(screen.getByText("Authentication Value")).toBeInTheDocument();
});
// Leave auth value empty and submit
vi.mocked(networking.createMCPServer).mockResolvedValue({
server_id: "new-server-1",
server_name: "Test_Server",
alias: "Test_Server",
url: "https://example.com/mcp",
transport: "http",
auth_type: "api_key",
created_at: "2024-01-01T00:00:00Z",
created_by: "user-1",
updated_at: "2024-01-01T00:00:00Z",
updated_by: "user-1",
});
// Leave auth value empty and submit
vi.mocked(networking.createMCPServer).mockResolvedValue({
server_id: "new-server-1",
server_name: "Test_Server",
alias: "Test_Server",
url: "https://example.com/mcp",
transport: "http",
auth_type: "api_key",
created_at: "2024-01-01T00:00:00Z",
created_by: "user-1",
updated_at: "2024-01-01T00:00:00Z",
updated_by: "user-1",
});
const submitButton = screen.getByRole("button", { name: "Add MCP Server" });
await act(async () => {
fireEvent.click(submitButton);
});
const submitButton = screen.getByRole("button", { name: "Add MCP Server" });
await act(async () => {
fireEvent.click(submitButton);
});
// The form should submit without validation error on auth_value
await waitFor(() => {
expect(networking.createMCPServer).toHaveBeenCalledTimes(1);
});
},
);
// The form should submit without validation error on auth_value
await waitFor(() => {
expect(networking.createMCPServer).toHaveBeenCalledTimes(1);
});
});
it(
"should not require auth value when creating a server with Bearer Token auth type",
{ timeout: 15000 },
async () => {
await selectHttpTransport();
it("should not require auth value when creating a server with Bearer Token auth type", async () => {
await selectHttpTransport();
const user = userEvent.setup({ delay: null });
const user = userEvent.setup({ delay: null });
const nameInput = getServerNameInput();
await user.type(nameInput, "Test_Server");
const nameInput = getServerNameInput();
await user.type(nameInput, "Test_Server");
const urlInput = screen.getByPlaceholderText("https://your-mcp-server.com");
await user.type(urlInput, "https://example.com/mcp");
const urlInput = screen.getByPlaceholderText("https://your-mcp-server.com");
await user.type(urlInput, "https://example.com/mcp");
await selectAntOption("Authentication", "Bearer Token");
await selectAntOption("Authentication", "Bearer Token");
await waitFor(() => {
expect(screen.getByText("Authentication Value")).toBeInTheDocument();
});
await waitFor(() => {
expect(screen.getByText("Authentication Value")).toBeInTheDocument();
});
// Leave auth value empty and submit
vi.mocked(networking.createMCPServer).mockResolvedValue({
server_id: "new-server-1",
server_name: "Test_Server",
alias: "Test_Server",
url: "https://example.com/mcp",
transport: "http",
auth_type: "bearer_token",
created_at: "2024-01-01T00:00:00Z",
created_by: "user-1",
updated_at: "2024-01-01T00:00:00Z",
updated_by: "user-1",
});
// Leave auth value empty and submit
vi.mocked(networking.createMCPServer).mockResolvedValue({
server_id: "new-server-1",
server_name: "Test_Server",
alias: "Test_Server",
url: "https://example.com/mcp",
transport: "http",
auth_type: "bearer_token",
created_at: "2024-01-01T00:00:00Z",
created_by: "user-1",
updated_at: "2024-01-01T00:00:00Z",
updated_by: "user-1",
});
const submitButton = screen.getByRole("button", { name: "Add MCP Server" });
await act(async () => {
fireEvent.click(submitButton);
});
const submitButton = screen.getByRole("button", { name: "Add MCP Server" });
await act(async () => {
fireEvent.click(submitButton);
});
await waitFor(() => {
expect(networking.createMCPServer).toHaveBeenCalledTimes(1);
});
},
);
await waitFor(() => {
expect(networking.createMCPServer).toHaveBeenCalledTimes(1);
});
});
it(
"should successfully create a server when auth value is provided",
{ timeout: 15000 },
async () => {
await selectHttpTransport();
it("should successfully create a server when auth value is provided", async () => {
await selectHttpTransport();
const user = userEvent.setup({ delay: null });
const user = userEvent.setup({ delay: null });
const nameInput = getServerNameInput();
await user.type(nameInput, "My_Server");
const nameInput = getServerNameInput();
await user.type(nameInput, "My_Server");
const urlInput = screen.getByPlaceholderText("https://your-mcp-server.com");
await user.type(urlInput, "https://example.com/mcp");
const urlInput = screen.getByPlaceholderText("https://your-mcp-server.com");
await user.type(urlInput, "https://example.com/mcp");
await selectAntOption("Authentication", "API Key");
await selectAntOption("Authentication", "API Key");
await waitFor(() => {
expect(screen.getByText("Authentication Value")).toBeInTheDocument();
});
await waitFor(() => {
expect(screen.getByText("Authentication Value")).toBeInTheDocument();
});
// Fill in auth value
const authInput = screen.getByPlaceholderText("Enter token or secret");
await user.type(authInput, "my-secret-key");
// Fill in auth value
const authInput = screen.getByPlaceholderText("Enter token or secret");
await user.type(authInput, "my-secret-key");
vi.mocked(networking.createMCPServer).mockResolvedValue({
server_id: "new-server-1",
server_name: "My_Server",
alias: "My_Server",
url: "https://example.com/mcp",
transport: "http",
auth_type: "api_key",
created_at: "2024-01-01T00:00:00Z",
created_by: "user-1",
updated_at: "2024-01-01T00:00:00Z",
updated_by: "user-1",
});
vi.mocked(networking.createMCPServer).mockResolvedValue({
server_id: "new-server-1",
server_name: "My_Server",
alias: "My_Server",
url: "https://example.com/mcp",
transport: "http",
auth_type: "api_key",
created_at: "2024-01-01T00:00:00Z",
created_by: "user-1",
updated_at: "2024-01-01T00:00:00Z",
updated_by: "user-1",
});
const submitButton = screen.getByRole("button", { name: "Add MCP Server" });
await act(async () => {
fireEvent.click(submitButton);
});
const submitButton = screen.getByRole("button", { name: "Add MCP Server" });
await act(async () => {
fireEvent.click(submitButton);
});
await waitFor(() => {
expect(networking.createMCPServer).toHaveBeenCalledTimes(1);
});
await waitFor(() => {
expect(networking.createMCPServer).toHaveBeenCalledTimes(1);
});
const [token, payload] = vi.mocked(networking.createMCPServer).mock.calls[0];
expect(token).toBe("test-token");
expect(payload.credentials).toEqual({ auth_value: "my-secret-key" });
},
);
const [token, payload] = vi.mocked(networking.createMCPServer).mock.calls[0];
expect(token).toBe("test-token");
expect(payload.credentials).toEqual({ auth_value: "my-secret-key" });
});
it("should not show auth value field when None auth type is selected", async () => {
await selectHttpTransport();
@ -307,50 +295,46 @@ describe("CreateMCPServer", () => {
});
});
it(
"should successfully create a server with no auth",
{ timeout: 15000 },
async () => {
await selectHttpTransport();
it("should successfully create a server with no auth", async () => {
await selectHttpTransport();
const user = userEvent.setup({ delay: null });
const user = userEvent.setup({ delay: null });
const nameInput = getServerNameInput();
await user.type(nameInput, "No_Auth_Server");
const nameInput = getServerNameInput();
await user.type(nameInput, "No_Auth_Server");
const urlInput = screen.getByPlaceholderText("https://your-mcp-server.com");
await user.type(urlInput, "https://example.com/mcp");
const urlInput = screen.getByPlaceholderText("https://your-mcp-server.com");
await user.type(urlInput, "https://example.com/mcp");
await selectAntOption("Authentication", "None");
await selectAntOption("Authentication", "None");
vi.mocked(networking.createMCPServer).mockResolvedValue({
server_id: "new-server-1",
server_name: "No_Auth_Server",
alias: "No_Auth_Server",
url: "https://example.com/mcp",
transport: "http",
auth_type: "none",
created_at: "2024-01-01T00:00:00Z",
created_by: "user-1",
updated_at: "2024-01-01T00:00:00Z",
updated_by: "user-1",
});
vi.mocked(networking.createMCPServer).mockResolvedValue({
server_id: "new-server-1",
server_name: "No_Auth_Server",
alias: "No_Auth_Server",
url: "https://example.com/mcp",
transport: "http",
auth_type: "none",
created_at: "2024-01-01T00:00:00Z",
created_by: "user-1",
updated_at: "2024-01-01T00:00:00Z",
updated_by: "user-1",
});
const submitButton = screen.getByRole("button", { name: "Add MCP Server" });
await act(async () => {
fireEvent.click(submitButton);
});
const submitButton = screen.getByRole("button", { name: "Add MCP Server" });
await act(async () => {
fireEvent.click(submitButton);
});
await waitFor(() => {
expect(networking.createMCPServer).toHaveBeenCalledTimes(1);
});
await waitFor(() => {
expect(networking.createMCPServer).toHaveBeenCalledTimes(1);
});
const [, payload] = vi.mocked(networking.createMCPServer).mock.calls[0];
expect(payload.auth_type).toBe("none");
// No credentials should be sent for "none" auth
expect(payload.credentials).toBeUndefined();
},
);
const [, payload] = vi.mocked(networking.createMCPServer).mock.calls[0];
expect(payload.auth_type).toBe("none");
// No credentials should be sent for "none" auth
expect(payload.credentials).toBeUndefined();
});
});
describe("when OAuth interactive auth is selected", () => {

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@ export default defineConfig({
setupFiles: ["tests/setupTests.ts"],
globals: true,
css: true, // lets you import CSS/modules without extra mocks
testTimeout: 10000,
testTimeout: 30000,
coverage: {
provider: "v8",
reporter: ["text", "lcov"],