Files
cfw-autumn/server/tests/integration/others/rate-limits/rate-limit-attach.test.ts
2026-02-04 11:17:02 +00:00

130 lines
3.0 KiB
TypeScript

import { expect, test } from "bun:test";
import { items } from "@tests/utils/fixtures/items.js";
import { products } from "@tests/utils/fixtures/products.js";
import { initScenario, s } from "@tests/utils/testInitUtils/initScenario.js";
import chalk from "chalk";
import AutumnError from "@/external/autumn/autumnCli.js";
const testCase = "rate-limit-attach";
const customerId = `test-${testCase}`;
// Attach rate limit is 5 per minute per customer
const ATTACH_RATE_LIMIT = 5;
/**
* Test: Rate limit on /attach endpoint
* Note: Attach rate limiting is bypassed in dev/test for the test org (see rateLimitMiddleware.ts)
* This test is skipped because it cannot be tested in the test environment.
*/
test.skip(`${chalk.yellowBright(testCase)}`, async () => {
const messagesItem = items.monthlyMessages({ includedUsage: 100 });
// Create multiple add-on products so we can attach them
const addon1 = products.base({
id: "addon1",
items: [messagesItem],
isAddOn: true,
});
const addon2 = products.base({
id: "addon2",
items: [messagesItem],
isAddOn: true,
});
const addon3 = products.base({
id: "addon3",
items: [messagesItem],
isAddOn: true,
});
const addon4 = products.base({
id: "addon4",
items: [messagesItem],
isAddOn: true,
});
const addon5 = products.base({
id: "addon5",
items: [messagesItem],
isAddOn: true,
});
const addon6 = products.base({
id: "addon6",
items: [messagesItem],
isAddOn: true,
});
const addon7 = products.base({
id: "addon7",
items: [messagesItem],
isAddOn: true,
});
const addon8 = products.base({
id: "addon8",
items: [messagesItem],
isAddOn: true,
});
const baseProduct = products.base({ id: "base", items: [messagesItem] });
const { autumnV1 } = await initScenario({
customerId,
setup: [
s.customer({ testClock: false }),
s.products({
list: [
baseProduct,
addon1,
addon2,
addon3,
addon4,
addon5,
addon6,
addon7,
addon8,
],
}),
],
actions: [s.attach({ productId: baseProduct.id })],
});
// Fire off more attach requests than the rate limit allows
const addons = [
addon1,
addon2,
addon3,
addon4,
addon5,
addon6,
addon7,
addon8,
];
const requestCount = ATTACH_RATE_LIMIT + 3;
const results = await Promise.allSettled(
addons.slice(0, requestCount).map((addon) =>
autumnV1.attach({
customer_id: customerId,
product_id: addon.id,
}),
),
);
const successCount = results.filter((r) => r.status === "fulfilled").length;
const rateLimitedCount = results.filter(
(r) =>
r.status === "rejected" &&
r.reason instanceof AutumnError &&
r.reason.code === "rate_limit_exceeded",
).length;
console.log(
`Requests: ${requestCount}, Successes: ${successCount}, Rate limited: ${rateLimitedCount}`,
);
expect(rateLimitedCount).toBeGreaterThan(0);
const rateLimitedResult = results.find(
(r) =>
r.status === "rejected" &&
r.reason instanceof AutumnError &&
r.reason.code === "rate_limit_exceeded",
);
expect(rateLimitedResult).toBeDefined();
});