Skip to main content
Glama

Convex MCP server

Official
by get-convex
SpendingLimitsForm.test.tsx11.2 kB
import React from "react"; import { render, screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { SpendingLimitsForm, spendingLimitValueToCents, } from "./SpendingLimits"; jest.mock("api/billing", () => ({ useSetSpendingLimit: jest.fn(), })); jest.mock("@sentry/nextjs", () => ({ captureMessage: jest.fn(), })); describe("SpendingLimitsForm", () => { const mockOnSubmit = jest.fn(); const currentSpending = { totalCents: 0, nextBillingPeriodStart: "2025-09-25", }; beforeEach(() => { jest.clearAllMocks(); }); it("should allow setting a zero spend limit", async () => { render( <SpendingLimitsForm defaultValue={{ spendingLimitWarningThresholdUsd: 42, spendingLimitDisableThresholdUsd: null, }} onSubmit={mockOnSubmit} onCancel={jest.fn()} currentSpending={currentSpending} />, ); const spendLimitCheckbox = screen.getByLabelText("Limit usage spending to"); await userEvent.click(spendLimitCheckbox); expect(spendLimitCheckbox).toBeChecked(); const spendLimitInput = screen.getByLabelText("Disable Threshold"); await userEvent.clear(spendLimitInput); await userEvent.type(spendLimitInput, "0"); // The form should be valid and the submit button should be enabled const submitButton = screen.getByRole("button", { name: "Save Spending Limits", }); expect(submitButton).not.toBeDisabled(); // The warning threshold field should still not be visible expect( screen.queryByLabelText("Warn when spending exceeds"), ).not.toBeInTheDocument(); // Click the submit button await userEvent.click(submitButton); // Verify that onSubmit was called with the correct values await waitFor(() => { expect(mockOnSubmit).toHaveBeenCalledWith({ spendingLimitWarningThresholdUsd: null, spendingLimitDisableThresholdUsd: 0, }); }); }); it("should not allow submission when spend limit is not a number", async () => { render( <SpendingLimitsForm defaultValue={{ spendingLimitWarningThresholdUsd: null, spendingLimitDisableThresholdUsd: "", }} onSubmit={mockOnSubmit} onCancel={jest.fn()} currentSpending={currentSpending} />, ); // Find the spend limit input const spendLimitInput = screen.getByLabelText("Disable Threshold"); // Enter a non-numeric value const nonNumericValue = "not a number"; await userEvent.clear(spendLimitInput); await userEvent.type(spendLimitInput, nonNumericValue); // Don’t show errors yet expect( screen.queryByText("Please enter a positive number."), ).not.toBeInTheDocument(); // Blur the input await userEvent.click(document.body); // Show the error expect( screen.getByText("Please enter a positive number."), ).toBeInTheDocument(); // Clicking the submit button should not submit the form and instead still show the error message const submitButton = screen.getByRole("button", { name: "Save Spending Limits", }); await userEvent.click(submitButton); expect( screen.getByText("Please enter a positive number."), ).toBeInTheDocument(); }); it("should not allow submission when spend limit is left empty", async () => { render( <SpendingLimitsForm defaultValue={{ spendingLimitWarningThresholdUsd: null, spendingLimitDisableThresholdUsd: null, }} onSubmit={mockOnSubmit} onCancel={jest.fn()} currentSpending={currentSpending} />, ); // Enable the checkbox const spendLimitCheckbox = screen.getByLabelText("Limit usage spending to"); await userEvent.click(spendLimitCheckbox); expect(spendLimitCheckbox).toBeChecked(); // At this point no error is shown expect( screen.queryByText("Please enter a positive number."), ).not.toBeInTheDocument(); // Click the submit button const submitButton = screen.getByRole("button", { name: "Save Spending Limits", }); await userEvent.click(submitButton); // The form should not be submitted and the error is shown expect( screen.getByText("Please enter a positive number."), ).toBeInTheDocument(); expect(mockOnSubmit).not.toHaveBeenCalled(); }); it("should not allow submission when warning threshold is higher than spend limit", async () => { render( <SpendingLimitsForm defaultValue={{ spendingLimitWarningThresholdUsd: null, spendingLimitDisableThresholdUsd: null, }} onSubmit={mockOnSubmit} onCancel={jest.fn()} currentSpending={currentSpending} />, ); // Enable both checkboxes const spendLimitCheckbox = screen.getByLabelText("Limit usage spending to"); await userEvent.click(spendLimitCheckbox); expect(spendLimitCheckbox).toBeChecked(); const warningThresholdCheckbox = screen.getByLabelText( "Warn when spending exceeds", ); await userEvent.click(warningThresholdCheckbox); expect(warningThresholdCheckbox).toBeChecked(); // Enter two values that don’t match const spendLimitInput = screen.getByLabelText("Disable Threshold"); await userEvent.clear(spendLimitInput); await userEvent.type(spendLimitInput, "100"); const warningThresholdInput = screen.getByLabelText("Warning Threshold"); await userEvent.clear(warningThresholdInput); await userEvent.type(warningThresholdInput, "101"); // Blur the inputs await userEvent.click(document.body); // Error message should be visible expect( screen.getByText( "The warning threshold must be less than the spend limit.", ), ).toBeInTheDocument(); }); it("should not allow submission when spend limit is less than current spending", async () => { render( <SpendingLimitsForm defaultValue={{ spendingLimitWarningThresholdUsd: null, spendingLimitDisableThresholdUsd: "", }} onSubmit={mockOnSubmit} onCancel={jest.fn()} currentSpending={{ ...currentSpending, totalCents: 1000_00 }} />, ); // Find the spend limit input const spendLimitInput = screen.getByLabelText("Disable Threshold"); // Enter a value less than the current spending await userEvent.type(spendLimitInput, "99"); await userEvent.click(document.body); expect( screen.getByText( "The spend limit must be greater than the spending in the current billing cycle ($1,000). You will be able to lower your spending limit at the start of the next billing cycle (September 25, 2025 at midnight UTC).", ), ).toBeInTheDocument(); }); it("allows setting a spend limit that is equal to the current spending", async () => { render( <SpendingLimitsForm defaultValue={{ spendingLimitWarningThresholdUsd: null, spendingLimitDisableThresholdUsd: "", }} onSubmit={mockOnSubmit} onCancel={jest.fn()} currentSpending={currentSpending} />, ); const spendLimitInput = screen.getByLabelText("Disable Threshold"); await userEvent.clear(spendLimitInput); await userEvent.type(spendLimitInput, "0"); await userEvent.click(document.body); const submitButton = screen.getByRole("button", { name: "Save Spending Limits", }); await userEvent.click(submitButton); await waitFor(() => { expect(mockOnSubmit).toHaveBeenCalledWith({ spendingLimitWarningThresholdUsd: null, spendingLimitDisableThresholdUsd: 0, }); }); }); it("does not allow setting a negative spend limit", async () => { render( <SpendingLimitsForm defaultValue={{ spendingLimitWarningThresholdUsd: "", spendingLimitDisableThresholdUsd: null, }} onSubmit={mockOnSubmit} onCancel={jest.fn()} currentSpending={undefined} />, ); const spendLimitInput = screen.getByLabelText("Warning Threshold"); await userEvent.type(spendLimitInput, "-1"); await userEvent.click(document.body); expect( screen.getByText("Please enter a positive number."), ).toBeInTheDocument(); }); it("should erase the existing values when disabling spending limits", async () => { render( <SpendingLimitsForm defaultValue={{ spendingLimitWarningThresholdUsd: 1234, spendingLimitDisableThresholdUsd: 5678, }} onSubmit={mockOnSubmit} onCancel={jest.fn()} currentSpending={currentSpending} />, ); // Disable both spending limits const spendLimitCheckbox = screen.getByLabelText("Limit usage spending to"); await userEvent.click(spendLimitCheckbox); expect(spendLimitCheckbox).not.toBeChecked(); expect(screen.getByLabelText("Disable Threshold")).toBeDisabled(); const warningThresholdCheckbox = screen.getByLabelText( "Warn when spending exceeds", ); await userEvent.click(warningThresholdCheckbox); expect(warningThresholdCheckbox).not.toBeChecked(); expect(screen.getByLabelText("Warning Threshold")).toBeDisabled(); // Submit the form const submitButton = screen.getByRole("button", { name: "Save Spending Limits", }); await userEvent.click(submitButton); await waitFor(() => { expect(mockOnSubmit).toHaveBeenCalledWith({ spendingLimitWarningThresholdUsd: null, spendingLimitDisableThresholdUsd: null, }); }); }); }); describe("spendingLimitValuesToCents", () => { it("should convert number values to cents", () => { const result = spendingLimitValueToCents({ spendingLimitWarningThresholdUsd: 100, spendingLimitDisableThresholdUsd: 200, }); expect(result).toEqual({ warningThresholdCents: 10000, disableThresholdCents: 20000, }); }); it("should handle null values", () => { const result = spendingLimitValueToCents({ spendingLimitWarningThresholdUsd: null, spendingLimitDisableThresholdUsd: null, }); expect(result).toEqual({ warningThresholdCents: null, disableThresholdCents: null, }); }); it("should convert empty strings to null", () => { const { captureMessage } = jest.requireMock("@sentry/nextjs"); const result = spendingLimitValueToCents({ spendingLimitWarningThresholdUsd: "", spendingLimitDisableThresholdUsd: "", }); expect(result).toEqual({ warningThresholdCents: null, disableThresholdCents: null, }); expect(captureMessage).toHaveBeenCalledTimes(2); expect(captureMessage).toHaveBeenCalledWith( "Spending limits form submitted with empty warning threshold", "error", ); expect(captureMessage).toHaveBeenCalledWith( "Spending limits form submitted with empty disable threshold", "error", ); expect(result).toEqual({ warningThresholdCents: null, disableThresholdCents: null, }); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/get-convex/convex-backend'

If you have feedback or need assistance with the MCP directory API, please join our Discord server