import { describe, expect, it } from "vitest"; import { parseWithZod } from "@conform-to/zod"; import { billingAlertsSchema } from "~/components/billing/BillingAlertsSection"; import { billingLimitFormSchema, getBillingLimitFormLastSubmission, isBillingLimitFormDirty, } from "~/components/billing/BillingLimitConfigSection"; import { billingLimitRecoveryFormSchema } from "~/components/billing/BillingLimitRecoveryPanel"; import { isBillingLimitSettingsFormSubmission } from "~/routes/_app.orgs.$organizationSlug.settings.billing-limits/billingLimitsRevalidation"; import { getSuggestedRecoveryLimitDollars } from "~/components/billing/billingLimitFormat"; import { getAlertsResetRequested, getEffectiveLimitCentsAfterLimitSave, getResolveSubmitted, getSubmittedResumeMode, isEnforcementActive, } from "~/routes/_app.orgs.$organizationSlug.settings.billing-limits/billingLimitsRoute.server"; import { loader as billingAlertsRedirectLoader } from "~/routes/_app.orgs.$organizationSlug.settings.billing-alerts/route"; function billingLimitsRequest(search = ""): Request { return new Request(`http://localhost:3030/orgs/acme/settings/billing-limits${search}`); } describe("billingLimitsRoute.server", () => { describe("isEnforcementActive", () => { it("returns true in grace", () => { expect( isEnforcementActive({ isConfigured: true, mode: "plan", cancelInProgressRuns: false, limitState: { status: "grace", hitAt: "t", graceEndsAt: "t" }, effectiveAmountCents: 5000, gracePeriodMs: 86_400_000, }) ).toBe(true); }); it("returns true when rejected", () => { expect( isEnforcementActive({ isConfigured: true, mode: "custom", amountCents: 2500, cancelInProgressRuns: false, limitState: { status: "rejected", hitAt: "t", graceEndsAt: "t" }, effectiveAmountCents: 2500, gracePeriodMs: 86_400_000, }) ).toBe(true); }); it("returns false when unconfigured", () => { expect( isEnforcementActive({ isConfigured: false, gracePeriodMs: 86_400_000, }) ).toBe(false); }); it("returns false when configured and ok", () => { expect( isEnforcementActive({ isConfigured: true, mode: "none", cancelInProgressRuns: false, limitState: { status: "ok" }, effectiveAmountCents: null, gracePeriodMs: 86_400_000, }) ).toBe(false); }); }); describe("getAlertsResetRequested", () => { it("returns true when alertsReset=1 is present", () => { expect(getAlertsResetRequested(billingLimitsRequest("?alertsReset=1"))).toBe(true); }); it("returns false when the param is absent", () => { expect(getAlertsResetRequested(billingLimitsRequest())).toBe(false); }); it("returns false for other param values", () => { expect(getAlertsResetRequested(billingLimitsRequest("?alertsReset=true"))).toBe(false); }); }); describe("getResolveSubmitted", () => { it("returns true when resolved=1 is present", () => { expect(getResolveSubmitted(billingLimitsRequest("?resolved=1"))).toBe(true); }); it("returns false when the param is absent", () => { expect(getResolveSubmitted(billingLimitsRequest())).toBe(false); }); }); describe("getSubmittedResumeMode", () => { it("parses resumeMode from the query string", () => { expect(getSubmittedResumeMode(billingLimitsRequest("?resumeMode=new_only"))).toBe("new_only"); }); it("returns null for invalid values", () => { expect(getSubmittedResumeMode(billingLimitsRequest("?resumeMode=invalid"))).toBeNull(); }); }); describe("getSuggestedRecoveryLimitDollars", () => { it("uses max(limit + $50, limit × 1.25, spend × 1.25) rounded up to $50", () => { expect(getSuggestedRecoveryLimitDollars(5_000, 4_500)).toBe(100); expect(getSuggestedRecoveryLimitDollars(50_000, 48_000)).toBe(650); expect(getSuggestedRecoveryLimitDollars(50_000, 60_000)).toBe(750); expect(getSuggestedRecoveryLimitDollars(1_000_000, 950_000)).toBe(12_500); }); it("falls back to spend × 1.25 when there is no effective limit", () => { expect(getSuggestedRecoveryLimitDollars(null, 4_500)).toBe(100); }); }); describe("isBillingLimitSettingsFormSubmission", () => { it("returns true for billing-limit POST", () => { const formData = new FormData(); formData.set("intent", "billing-limit"); expect(isBillingLimitSettingsFormSubmission("post", formData)).toBe(true); }); it("returns true for billing-alerts POST", () => { const formData = new FormData(); formData.set("intent", "billing-alerts"); expect(isBillingLimitSettingsFormSubmission("POST", formData)).toBe(true); }); it("returns true for billing-limit-resolve POST", () => { const formData = new FormData(); formData.set("intent", "billing-limit-resolve"); expect(isBillingLimitSettingsFormSubmission("post", formData)).toBe(true); }); it("returns false for unrelated POST", () => { const formData = new FormData(); formData.set("intent", "other"); expect(isBillingLimitSettingsFormSubmission("post", formData)).toBe(false); }); it("returns false without form data", () => { expect(isBillingLimitSettingsFormSubmission("post", undefined)).toBe(false); }); }); describe("getEffectiveLimitCentsAfterLimitSave", () => { it("uses custom amount in cents for custom mode", () => { expect(getEffectiveLimitCentsAfterLimitSave("custom", 5000, 42.5)).toBe(4250); }); it("uses plan limit cents for plan mode", () => { expect(getEffectiveLimitCentsAfterLimitSave("plan", 5000)).toBe(5000); }); it("uses plan limit cents for none mode", () => { expect(getEffectiveLimitCentsAfterLimitSave("none", 5000)).toBe(5000); }); }); }); describe("billing-alerts redirect route", () => { it("redirects to billing-limits", async () => { const response = await billingAlertsRedirectLoader({ params: { organizationSlug: "acme" }, request: new Request("http://localhost:3030/orgs/acme/settings/billing-alerts"), context: {}, }); expect(response.status).toBe(302); expect(response.headers.get("Location")).toBe("/orgs/acme/settings/billing-limits"); }); }); describe("billing-limits form validation", () => { it("rejects duplicate alert thresholds", () => { const formData = new FormData(); formData.set("intent", "billing-alerts"); formData.append("emails", "a@example.com"); formData.append("alertLevels", "75"); formData.append("alertLevels", "75"); const submission = parseWithZod(formData, { schema: billingAlertsSchema }); expect(submission.error?.alertLevels).toBeTruthy(); }); it("rejects non-numeric alert thresholds", () => { const formData = new FormData(); formData.set("intent", "billing-alerts"); formData.append("emails", "a@example.com"); formData.append("alertLevels", "75"); formData.append("alertLevels", "not-a-number"); const submission = parseWithZod(formData, { schema: billingAlertsSchema }); expect(submission.error?.["alertLevels[1]"]).toBeTruthy(); }); it("accepts a valid billing limit custom submission", () => { const formData = new FormData(); formData.set("intent", "billing-limit"); formData.set("mode", "custom"); formData.set("amount", "100"); formData.set("cancelInProgressRuns", "on"); const submission = parseWithZod(formData, { schema: billingLimitFormSchema }); expect(submission.value).toEqual({ mode: "custom", amount: 100, cancelInProgressRuns: true, }); }); it("parses none mode with cancelInProgressRuns from the form", () => { const formData = new FormData(); formData.set("mode", "none"); formData.set("cancelInProgressRuns", "on"); const submission = parseWithZod(formData, { schema: billingLimitFormSchema }); expect(submission.value?.mode).toBe("none"); expect(submission.value?.cancelInProgressRuns).toBe(true); }); it("accepts a valid billing limit resolve submission", () => { const formData = new FormData(); formData.set("intent", "billing-limit-resolve"); formData.set("action", "increase"); formData.set("newAmount", "1500"); formData.set("resumeMode", "queue"); const submission = parseWithZod(formData, { schema: billingLimitRecoveryFormSchema }); expect(submission.value).toEqual({ action: "increase", newAmount: 1500, resumeMode: "queue", }); }); it("accepts remove resolve with new_only resume mode", () => { const formData = new FormData(); formData.set("action", "remove"); formData.set("resumeMode", "new_only"); const submission = parseWithZod(formData, { schema: billingLimitRecoveryFormSchema }); expect(submission.value).toEqual({ action: "remove", resumeMode: "new_only", }); }); }); describe("isBillingLimitFormDirty", () => { const unconfiguredLimit = { isConfigured: false as const, gracePeriodMs: 86_400_000 }; const configuredPlanLimit = { isConfigured: true as const, mode: "plan" as const, cancelInProgressRuns: false, limitState: { status: "ok" as const }, effectiveAmountCents: 5000, gracePeriodMs: 86_400_000, }; it("is dirty when billing limit has never been saved", () => { expect( isBillingLimitFormDirty({ billingLimit: unconfiguredLimit, mode: "none", customAmount: "", cancelInProgressRuns: false, }) ).toBe(true); }); it("is clean when configured values match saved state", () => { expect( isBillingLimitFormDirty({ billingLimit: configuredPlanLimit, mode: "plan", customAmount: "", cancelInProgressRuns: false, }) ).toBe(false); }); it("is dirty when configured mode changes", () => { expect( isBillingLimitFormDirty({ billingLimit: configuredPlanLimit, mode: "none", customAmount: "", cancelInProgressRuns: false, }) ).toBe(true); }); }); describe("getBillingLimitFormLastSubmission", () => { it("drops amount errors when the selected mode is not custom", () => { const submission = parseWithZod( (() => { const formData = new FormData(); formData.set("mode", "custom"); formData.set("amount", "0"); return formData; })(), { schema: billingLimitFormSchema } ).reply(); expect( getBillingLimitFormLastSubmission(submission, "plan", true)?.error?.amount ).toBeUndefined(); }); it("keeps amount errors while custom mode is selected", () => { const submission = parseWithZod( (() => { const formData = new FormData(); formData.set("mode", "custom"); formData.set("amount", "0"); return formData; })(), { schema: billingLimitFormSchema } ).reply(); expect( getBillingLimitFormLastSubmission(submission, "custom", true)?.error?.amount ).toBeTruthy(); }); it("returns undefined when the form is clean", () => { const submission = parseWithZod( (() => { const formData = new FormData(); formData.set("mode", "custom"); formData.set("amount", "0"); return formData; })(), { schema: billingLimitFormSchema } ).reply(); expect(getBillingLimitFormLastSubmission(submission, "custom", false)).toBeUndefined(); }); });