b1987dc090
## Summary Adds Billing Limits to the webapp. Customers can set a monthly spend cap. When usage crosses the limit, billable environments enter a grace period. If the limit is not resolved before grace expires, new triggers are rejected until the organization increases or removes the limit.
79 lines
2.3 KiB
TypeScript
79 lines
2.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { BillingLimitHitWebhookBodySchema } from "~/services/billingLimit.schemas";
|
|
import {
|
|
type BillingLimitHitDeps,
|
|
processBillingLimitHit,
|
|
} from "~/v3/services/billingLimit/billingLimitHit.server";
|
|
|
|
describe("billingLimitHit", () => {
|
|
it("busts caches, seeds reconcile, and enqueues grace converge", async () => {
|
|
const calls: string[] = [];
|
|
|
|
const deps: BillingLimitHitDeps = {
|
|
bustCaches: (organizationId) => {
|
|
calls.push(`bust:${organizationId}`);
|
|
},
|
|
seedReconcileQueue: async (organizationId) => {
|
|
calls.push(`seed:${organizationId}`);
|
|
},
|
|
enqueueConverge: async (organizationId, targetState) => {
|
|
calls.push(`converge:${organizationId}:${targetState}`);
|
|
},
|
|
enqueueCancelInProgressRuns: async () => {
|
|
calls.push("cancel");
|
|
},
|
|
};
|
|
|
|
await processBillingLimitHit(
|
|
{
|
|
organizationId: "org_123",
|
|
hitAt: "2026-06-16T12:00:00.000Z",
|
|
cancelInProgressRuns: false,
|
|
},
|
|
deps
|
|
);
|
|
|
|
expect(calls).toEqual(["bust:org_123", "seed:org_123", "converge:org_123:grace"]);
|
|
});
|
|
|
|
it("enqueues in-progress cancel when cancelInProgressRuns is true", async () => {
|
|
const cancelCalls: Array<{ organizationId: string; hitAt: string }> = [];
|
|
|
|
const deps: BillingLimitHitDeps = {
|
|
bustCaches: () => {},
|
|
seedReconcileQueue: async () => {},
|
|
enqueueConverge: async () => {},
|
|
enqueueCancelInProgressRuns: async (organizationId, hitAt) => {
|
|
cancelCalls.push({ organizationId, hitAt });
|
|
},
|
|
};
|
|
|
|
await processBillingLimitHit(
|
|
{
|
|
organizationId: "org_123",
|
|
hitAt: "2026-06-16T12:00:00.000Z",
|
|
cancelInProgressRuns: true,
|
|
},
|
|
deps
|
|
);
|
|
|
|
expect(cancelCalls).toEqual([{ organizationId: "org_123", hitAt: "2026-06-16T12:00:00.000Z" }]);
|
|
});
|
|
});
|
|
|
|
describe("BillingLimitHitWebhookBodySchema", () => {
|
|
it("parses the hit webhook body", () => {
|
|
expect(
|
|
BillingLimitHitWebhookBodySchema.parse({
|
|
hitAt: "2026-06-16T12:00:00.000Z",
|
|
cancelInProgressRuns: true,
|
|
limitState: "grace",
|
|
})
|
|
).toEqual({
|
|
hitAt: "2026-06-16T12:00:00.000Z",
|
|
cancelInProgressRuns: true,
|
|
limitState: "grace",
|
|
});
|
|
});
|
|
});
|