test: move the create-user soft budget test to the integration tier and type the email test

This commit is contained in:
Jesus Velarde 2026-11-14 16:12:24 -08:00
parent 6812fc2162
commit 96e9472707
3 changed files with 28 additions and 35 deletions

View file

@ -109,3 +109,21 @@ describe("custom User ID invitation", () => {
expect(screen.getByRole("textbox", { name: "User ID", exact: true })).toHaveValue("");
});
});
describe("soft budget", () => {
it.each([
["25.5", { soft_budget: 25.5 }],
["", {}],
])("sends Soft Budget %j as %j on /user/new", async (typed, expected) => {
const user = userEvent.setup();
renderForm(false);
await user.click(screen.getByRole("button", { name: "+ Invite User" }));
fireEvent.change(screen.getByRole("textbox", { name: "User Email" }), { target: { value: "soft@example.test" } });
fireEvent.change(screen.getByRole("spinbutton", { name: /Soft Budget/ }), { target: { value: typed } });
await user.click(screen.getByRole("button", { name: "Invite User", exact: true }));
await waitFor(() => expect(createUser).toHaveBeenCalledTimes(1));
const body = createUser.mock.calls[0][0];
expect(body).toMatchObject({ user_email: "soft@example.test", ...expected });
expect("soft_budget" in body).toBe("soft_budget" in expected);
});
});

View file

@ -1,4 +1,4 @@
import { fireEvent, render, screen, waitFor, within } from "@testing-library/react";
import { render, screen, waitFor, within } from "@testing-library/react";
import userEvent, { PointerEventsCheckLevel } from "@testing-library/user-event";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { describe, it, expect, vi, beforeEach } from "vitest";
@ -311,36 +311,6 @@ describe("CreateUserButton", () => {
expectControlBesideLabel(within(dialog).getByRole("checkbox", { name: "Send invitation email" }));
});
describe("soft budget", () => {
it.each([
["25.5", { soft_budget: 25.5 }],
["", {}],
])("sends soft_budget %j as %j in the create payload", async (typed, expected) => {
const user = userEvent.setup({ pointerEventsCheck: PointerEventsCheckLevel.Never });
mockUserCreateCall.mockResolvedValue({ data: { user_id: "soft-user" } });
mockInvitationCreateCall.mockResolvedValue({
id: "inv-soft",
user_id: "soft-user",
has_user_setup_sso: false,
} as any);
renderWithProviders(
<CreateUserButton {...defaultProps} possibleUIRoles={{ proxy_user: { ui_label: "User", description: "" } }} />,
);
await user.click(await screen.findByRole("button", { name: /\+ invite user/i }));
const dialog = screen.getByRole("dialog", { name: /invite user/i });
fireEvent.change(within(dialog).getByLabelText(/user email/i), { target: { value: "soft@example.com" } });
fireEvent.change(within(dialog).getByLabelText(/soft budget/i), { target: { value: typed } });
await user.click(within(dialog).getByRole("button", { name: /invite user/i }));
await waitFor(() => expect(mockUserCreateCall).toHaveBeenCalledTimes(1));
const payload = mockUserCreateCall.mock.calls[0][2];
expect(payload).toMatchObject({ user_email: "soft@example.com", ...expected });
expect("soft_budget" in payload).toBe("soft_budget" in expected);
});
});
describe("organizations", () => {
it("should send organizations list in POST body when organizations are selected", async () => {
const { useOrganizations } = await import("@/app/(dashboard)/hooks/organizations/useOrganizations");

View file

@ -1539,9 +1539,14 @@ async def test_expiry_email_contains_alias_utc_expiry_and_dashboard_link_without
],
)
async def test_soft_budget_alert_email_names_what_crossed_the_budget(
base_email_logger, mock_send_email, mock_lookup_user_email, event_group, owner_line, other_line
):
event = WebhookEvent(
base_email_logger: BaseEmailLogger,
mock_send_email: mock.MagicMock,
mock_lookup_user_email: mock.MagicMock,
event_group: Litellm_EntityType,
owner_line: str,
other_line: str,
) -> None:
event: Final = WebhookEvent(
user_id="test_user",
user_email="test@example.com",
token="hashed-token",
@ -1555,6 +1560,6 @@ async def test_soft_budget_alert_email_names_what_crossed_the_budget(
with mock.patch.dict(os.environ, {"PROXY_BASE_URL": "http://test.com"}):
await base_email_logger.send_soft_budget_alert_email(event)
html_body = mock_send_email.call_args[1]["html_body"]
html_body: Final[str] = mock_send_email.call_args[1]["html_body"]
assert owner_line in html_body
assert other_line not in html_body