diff --git a/ui/litellm-dashboard/src/components/view_logs/SpendLogsSettingsModal/SpendLogsSettingsModal.test.tsx b/ui/litellm-dashboard/src/components/view_logs/SpendLogsSettingsModal/SpendLogsSettingsModal.test.tsx
new file mode 100644
index 0000000000..b244736540
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/view_logs/SpendLogsSettingsModal/SpendLogsSettingsModal.test.tsx
@@ -0,0 +1,348 @@
+import { render, screen, waitFor } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { beforeEach, describe, expect, it, vi, Mock } from "vitest";
+import SpendLogsSettingsModal from "./SpendLogsSettingsModal";
+import { useStoreRequestInSpendLogs } from "@/app/(dashboard)/hooks/storeRequestInSpendLogs/useStoreRequestInSpendLogs";
+import NotificationsManager from "@/components/molecules/notifications_manager";
+import { parseErrorMessage } from "@/components/shared/errorUtils";
+import { renderWithProviders } from "../../../../tests/test-utils";
+
+vi.mock("@/app/(dashboard)/hooks/storeRequestInSpendLogs/useStoreRequestInSpendLogs");
+vi.mock("@/components/molecules/notifications_manager", () => ({
+ default: {
+ success: vi.fn(),
+ fromBackend: vi.fn(),
+ },
+}));
+vi.mock("@/components/shared/errorUtils", () => ({
+ parseErrorMessage: vi.fn(),
+}));
+
+const mockUseStoreRequestInSpendLogs = vi.mocked(useStoreRequestInSpendLogs);
+const mockNotificationsManager = vi.mocked(NotificationsManager);
+const mockParseErrorMessage = vi.mocked(parseErrorMessage);
+
+describe("SpendLogsSettingsModal", () => {
+ const mockOnCancel = vi.fn();
+ const mockOnSuccess = vi.fn();
+ const mockMutateAsync = vi.fn();
+
+ const defaultProps = {
+ isVisible: true,
+ onCancel: mockOnCancel,
+ onSuccess: mockOnSuccess,
+ };
+
+ beforeEach(() => {
+ vi.clearAllMocks();
+ mockUseStoreRequestInSpendLogs.mockReturnValue({
+ mutateAsync: mockMutateAsync,
+ isPending: false,
+ } as any);
+ mockParseErrorMessage.mockImplementation((error: any) => error?.message || String(error));
+ });
+
+ it("should render the modal", () => {
+ renderWithProviders();
+ expect(screen.getByRole("dialog")).toBeInTheDocument();
+ expect(screen.getByText("Spend Logs Settings")).toBeInTheDocument();
+ });
+
+ it("should render form fields with initial values", () => {
+ renderWithProviders();
+
+ expect(screen.getByText("Store Prompts in Spend Logs")).toBeInTheDocument();
+ expect(screen.getByLabelText("Maximum Spend Logs Retention Period (Optional)")).toBeInTheDocument();
+ expect(screen.getByPlaceholderText("e.g., 7d, 30d")).toBeInTheDocument();
+ });
+
+ it("should render cancel and save buttons", () => {
+ renderWithProviders();
+
+ expect(screen.getByRole("button", { name: "Cancel" })).toBeInTheDocument();
+ expect(screen.getByRole("button", { name: "Save Settings" })).toBeInTheDocument();
+ });
+
+ it("should call onCancel when cancel button is clicked", async () => {
+ const user = userEvent.setup();
+ renderWithProviders();
+
+ const cancelButton = screen.getByRole("button", { name: "Cancel" });
+ await user.click(cancelButton);
+
+ expect(mockOnCancel).toHaveBeenCalledTimes(1);
+ });
+
+ it("should call onCancel when modal close button is clicked", async () => {
+ const user = userEvent.setup();
+ renderWithProviders();
+
+ const closeButton = screen.getByRole("button", { name: /close/i });
+ await user.click(closeButton);
+
+ expect(mockOnCancel).toHaveBeenCalledTimes(1);
+ });
+
+ it("should toggle store prompts switch", async () => {
+ const user = userEvent.setup();
+ renderWithProviders();
+
+ const switchElement = screen.getByRole("switch");
+ expect(switchElement).not.toBeChecked();
+
+ await user.click(switchElement);
+
+ await waitFor(() => {
+ expect(switchElement).toBeChecked();
+ });
+ });
+
+ it("should update retention period input", async () => {
+ const user = userEvent.setup();
+ renderWithProviders();
+
+ const retentionInput = screen.getByPlaceholderText("e.g., 7d, 30d");
+ await user.type(retentionInput, "30d");
+
+ expect(retentionInput).toHaveValue("30d");
+ });
+
+ it("should submit form with store prompts enabled and retention period", async () => {
+ const user = userEvent.setup();
+ mockMutateAsync.mockImplementation(async (params, options) => {
+ await Promise.resolve();
+ options?.onSuccess?.();
+ return { message: "Success" };
+ });
+
+ renderWithProviders();
+
+ const switchElement = screen.getByRole("switch");
+ await user.click(switchElement);
+
+ const retentionInput = screen.getByPlaceholderText("e.g., 7d, 30d");
+ await user.type(retentionInput, "30d");
+
+ const saveButton = screen.getByRole("button", { name: "Save Settings" });
+ await user.click(saveButton);
+
+ await waitFor(() => {
+ expect(mockMutateAsync).toHaveBeenCalledWith(
+ {
+ store_prompts_in_spend_logs: true,
+ maximum_spend_logs_retention_period: "30d",
+ },
+ expect.any(Object)
+ );
+ });
+ });
+
+ it("should submit form with store prompts disabled and no retention period", async () => {
+ const user = userEvent.setup();
+ mockMutateAsync.mockImplementation(async (params, options) => {
+ await Promise.resolve();
+ options?.onSuccess?.();
+ return { message: "Success" };
+ });
+
+ renderWithProviders();
+
+ const saveButton = screen.getByRole("button", { name: "Save Settings" });
+ await user.click(saveButton);
+
+ await waitFor(() => {
+ expect(mockMutateAsync).toHaveBeenCalledWith(
+ {
+ store_prompts_in_spend_logs: false,
+ maximum_spend_logs_retention_period: undefined,
+ },
+ expect.any(Object)
+ );
+ });
+ });
+
+ it("should show success notification and call onSuccess on successful submission", async () => {
+ const user = userEvent.setup();
+ mockMutateAsync.mockImplementation(async (params, options) => {
+ await Promise.resolve();
+ options?.onSuccess?.();
+ return { message: "Success" };
+ });
+
+ renderWithProviders();
+
+ const saveButton = screen.getByRole("button", { name: "Save Settings" });
+ await user.click(saveButton);
+
+ await waitFor(() => {
+ expect(mockNotificationsManager.success).toHaveBeenCalledWith("Spend logs settings updated successfully");
+ expect(mockOnSuccess).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ it("should show error notification when submission fails", async () => {
+ const user = userEvent.setup();
+ const error = new Error("Network error");
+ mockMutateAsync.mockRejectedValue(error);
+ mockParseErrorMessage.mockReturnValue("Network error");
+
+ renderWithProviders();
+
+ const saveButton = screen.getByRole("button", { name: "Save Settings" });
+ await user.click(saveButton);
+
+ await waitFor(() => {
+ expect(mockNotificationsManager.fromBackend).toHaveBeenCalledWith("Failed to save spend logs settings: Network error");
+ });
+ });
+
+ it("should show error notification from onError callback", async () => {
+ const user = userEvent.setup();
+ const error = new Error("Backend error");
+ mockMutateAsync.mockImplementation((params, options) => {
+ options?.onError?.(error);
+ return Promise.reject(error);
+ });
+ mockParseErrorMessage.mockReturnValue("Backend error");
+
+ renderWithProviders();
+
+ const saveButton = screen.getByRole("button", { name: "Save Settings" });
+ await user.click(saveButton);
+
+ await waitFor(() => {
+ expect(mockNotificationsManager.fromBackend).toHaveBeenCalledWith("Failed to save spend logs settings: Backend error");
+ });
+ });
+
+ it("should disable cancel button when pending", () => {
+ mockUseStoreRequestInSpendLogs.mockReturnValue({
+ mutateAsync: mockMutateAsync,
+ isPending: true,
+ } as any);
+
+ renderWithProviders();
+
+ const cancelButton = screen.getByRole("button", { name: "Cancel" });
+ expect(cancelButton).toBeDisabled();
+ });
+
+ it("should show loading state on save button when pending", () => {
+ mockUseStoreRequestInSpendLogs.mockReturnValue({
+ mutateAsync: mockMutateAsync,
+ isPending: true,
+ } as any);
+
+ renderWithProviders();
+
+ const saveButton = screen.getByRole("button", { name: /Saving/i });
+ expect(saveButton).toBeInTheDocument();
+ expect(saveButton.className).toContain("ant-btn-loading");
+ });
+
+ it("should call onCancel when cancel button is clicked after modifying form", async () => {
+ const user = userEvent.setup();
+ renderWithProviders();
+
+ const switchElement = screen.getByRole("switch");
+ await user.click(switchElement);
+
+ const retentionInput = screen.getByPlaceholderText("e.g., 7d, 30d");
+ await user.type(retentionInput, "30d");
+
+ expect(switchElement).toBeChecked();
+ expect(retentionInput).toHaveValue("30d");
+
+ const cancelButton = screen.getByRole("button", { name: "Cancel" });
+ await user.click(cancelButton);
+
+ expect(mockOnCancel).toHaveBeenCalledTimes(1);
+ });
+
+ it("should reset form fields after successful submission", async () => {
+ const user = userEvent.setup();
+ mockMutateAsync.mockImplementation(async (params, options) => {
+ await Promise.resolve();
+ options?.onSuccess?.();
+ return { message: "Success" };
+ });
+
+ const { rerender } = renderWithProviders();
+
+ const switchElement = screen.getByRole("switch");
+ await user.click(switchElement);
+
+ const retentionInput = screen.getByPlaceholderText("e.g., 7d, 30d");
+ await user.type(retentionInput, "30d");
+
+ expect(switchElement).toBeChecked();
+ expect(retentionInput).toHaveValue("30d");
+
+ const saveButton = screen.getByRole("button", { name: "Save Settings" });
+ await user.click(saveButton);
+
+ await waitFor(() => {
+ expect(mockNotificationsManager.success).toHaveBeenCalled();
+ });
+
+ rerender();
+
+ await waitFor(() => {
+ const updatedSwitchElement = screen.getByRole("switch");
+ const updatedRetentionInput = screen.getByPlaceholderText("e.g., 7d, 30d");
+ expect(updatedSwitchElement).not.toBeChecked();
+ expect(updatedRetentionInput).toHaveValue("");
+ });
+ });
+
+ it("should not call onSuccess when it is not provided", async () => {
+ const user = userEvent.setup();
+ mockMutateAsync.mockImplementation(async (params, options) => {
+ await Promise.resolve();
+ options?.onSuccess?.();
+ return { message: "Success" };
+ });
+
+ renderWithProviders();
+
+ const saveButton = screen.getByRole("button", { name: "Save Settings" });
+ await user.click(saveButton);
+
+ await waitFor(() => {
+ expect(mockNotificationsManager.success).toHaveBeenCalled();
+ });
+ });
+
+ it("should not render modal when isVisible is false", () => {
+ renderWithProviders();
+
+ expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
+ });
+
+ it("should submit form with only store prompts enabled and no retention period", async () => {
+ const user = userEvent.setup();
+ mockMutateAsync.mockImplementation(async (params, options) => {
+ await Promise.resolve();
+ options?.onSuccess?.();
+ return { message: "Success" };
+ });
+
+ renderWithProviders();
+
+ const switchElement = screen.getByRole("switch");
+ await user.click(switchElement);
+
+ const saveButton = screen.getByRole("button", { name: "Save Settings" });
+ await user.click(saveButton);
+
+ await waitFor(() => {
+ expect(mockMutateAsync).toHaveBeenCalledWith(
+ {
+ store_prompts_in_spend_logs: true,
+ maximum_spend_logs_retention_period: undefined,
+ },
+ expect.any(Object)
+ );
+ });
+ });
+});