branch: main
rate_limit.spec.ts
6054 bytesRaw
import { describe, test, expect } from "vitest";
import { mf, mfUrl } from "./mf";
describe("rate limit", () => {
test("basic rate limit check", async () => {
const resp = await mf.dispatchFetch(`${mfUrl}rate-limit/check`);
expect(resp.status).toBe(200);
const data = await resp.json() as { success: boolean };
expect(data).toHaveProperty("success");
expect(data.success).toBe(true);
});
test("rate limit with custom key", async () => {
const key = "test-key-123";
const resp = await mf.dispatchFetch(`${mfUrl}rate-limit/key/${key}`);
expect(resp.status).toBe(200);
const data = await resp.json() as { success: boolean; key: string };
expect(data).toHaveProperty("success");
expect(data).toHaveProperty("key");
expect(data.key).toBe(key);
expect(data.success).toBe(true);
});
test("different keys have independent limits", async () => {
// Test that different keys have separate rate limits
const key1 = "user-1";
const key2 = "user-2";
const resp1 = await mf.dispatchFetch(`${mfUrl}rate-limit/key/${key1}`);
const resp2 = await mf.dispatchFetch(`${mfUrl}rate-limit/key/${key2}`);
expect(resp1.status).toBe(200);
expect(resp2.status).toBe(200);
const data1 = await resp1.json() as { success: boolean; key: string };
const data2 = await resp2.json() as { success: boolean; key: string };
expect(data1.success).toBe(true);
expect(data2.success).toBe(true);
expect(data1.key).toBe(key1);
expect(data2.key).toBe(key2);
});
test("bulk rate limit test", async () => {
const resp = await mf.dispatchFetch(`${mfUrl}rate-limit/bulk-test`);
expect(resp.status).toBe(200);
const data = await resp.json() as { results: Array<{ index: number; key: string; success: boolean }> };
expect(data).toHaveProperty("results");
expect(Array.isArray(data.results)).toBe(true);
expect(data.results.length).toBe(15);
// Check that results have the expected structure
data.results.forEach((result, index: number) => {
expect(result).toHaveProperty("index");
expect(result).toHaveProperty("key");
expect(result).toHaveProperty("success");
expect(result.index).toBe(index);
expect(typeof result.success).toBe("boolean");
});
// We're using 3 different keys (bulk-test-0, bulk-test-1, bulk-test-2)
// with a limit of 10 per 60 seconds. Each key is used 5 times (15 requests / 3 keys).
// All requests should succeed since each key stays under the limit of 10.
// Group results by key
const resultsByKey: Record<string, Array<{ index: number; key: string; success: boolean }>> = {};
data.results.forEach((result) => {
if (!resultsByKey[result.key]) {
resultsByKey[result.key] = [];
}
resultsByKey[result.key].push(result);
});
// Should have exactly 3 keys
expect(Object.keys(resultsByKey).length).toBe(3);
// Each key should have 5 requests, all successful (under limit of 10)
Object.entries(resultsByKey).forEach(([key, results]) => {
expect(results.length).toBe(5);
results.forEach((result) => {
expect(result.success).toBe(true);
});
});
});
test("rate limit reset with unique keys", async () => {
const resp = await mf.dispatchFetch(`${mfUrl}rate-limit/reset`);
expect(resp.status).toBe(200);
const data = await resp.json() as Record<string, boolean>;
// Should have 12 request results
expect(Object.keys(data).length).toBe(12);
// Check that we have the expected keys
for (let i = 1; i <= 12; i++) {
expect(data).toHaveProperty(`request_${i}`);
expect(typeof data[`request_${i}`]).toBe("boolean");
}
// With a limit of 10 per 60 seconds, the first 10 requests MUST succeed
// and requests 11 and 12 MUST fail
for (let i = 1; i <= 10; i++) {
expect(data[`request_${i}`]).toBe(true);
}
// Requests 11 and 12 must be rate limited
expect(data["request_11"]).toBe(false);
expect(data["request_12"]).toBe(false);
});
test("multiple rapid requests with same key", async () => {
// Generate a unique key for this test
const testKey = `rapid-test-${Date.now()}`;
// Make multiple rapid requests with the same key
const promises = [];
for (let i = 0; i < 5; i++) {
promises.push(mf.dispatchFetch(`${mfUrl}rate-limit/key/${testKey}`));
}
const responses = await Promise.all(promises);
// All responses should be successful (200 status)
responses.forEach(resp => {
expect(resp.status).toBe(200);
});
// Parse the responses
const results = await Promise.all(responses.map(r => r.json())) as Array<{ success: boolean; key: string }>;
// All should have the same key
results.forEach(data => {
expect(data.key).toBe(testKey);
expect(data).toHaveProperty("success");
});
// With limit of 10, all 5 requests should succeed
results.forEach((data) => {
expect(data.success).toBe(true);
});
});
test("sequential requests enforce rate limit", async () => {
// Generate a unique key for this test to avoid interference
const testKey = `sequential-test-${Date.now()}`;
// Make 15 sequential requests with the same key
// With a limit of 10 per 60 seconds, first 10 should succeed, rest should fail
const results: Array<{ success: boolean; key: string }> = [];
for (let i = 0; i < 15; i++) {
const resp = await mf.dispatchFetch(`${mfUrl}rate-limit/key/${testKey}`);
expect(resp.status).toBe(200);
const data = await resp.json() as { success: boolean; key: string };
results.push(data);
}
// Verify first 10 requests succeed
for (let i = 0; i < 10; i++) {
expect(results[i].success).toBe(true);
expect(results[i].key).toBe(testKey);
}
// Verify requests 11-15 are rate limited
for (let i = 10; i < 15; i++) {
expect(results[i].success).toBe(false);
expect(results[i].key).toBe(testKey);
}
});
});