Files
filezzy-staging/backend/scripts/test-guest-limits-api.ts
2026-02-04 14:16:04 +01:00

121 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env npx ts-node
/**
* Simple API test: guest limits consistency.
* Verifies GET /user/limits (no auth) and GET /config/pricing return the same guest ops limit.
*
* Run: npm run api:test:guest-limits
* Or: npx ts-node scripts/test-guest-limits-api.ts
* Requires: backend running on API_URL (default http://localhost:4000)
*
* Manual curl (bash): curl -s http://localhost:4000/api/v1/user/limits
* Manual curl (bash): curl -s http://localhost:4000/api/v1/config/pricing
* PowerShell: Invoke-RestMethod -Uri http://localhost:4000/api/v1/user/limits
* PowerShell: (Invoke-RestMethod -Uri http://localhost:4000/api/v1/config/pricing).limits.guest
*/
import dotenv from 'dotenv';
import path from 'path';
import axios from 'axios';
dotenv.config({ path: path.join(__dirname, '../.env') });
const BASE_URL = process.env.API_URL || process.env.API_BASE_URL || 'http://localhost:4000';
async function main() {
console.log('Testing guest limits API (single source of truth)\n');
console.log('Base URL:', BASE_URL);
// 1. GET /api/v1/user/limits (no auth = guest)
console.log('\n1. GET /api/v1/user/limits (no Authorization = guest)');
let limitsRes;
try {
limitsRes = await axios.get(`${BASE_URL}/api/v1/user/limits`, {
validateStatus: () => true,
timeout: 5000,
});
} catch (err: unknown) {
const msg = err instanceof Error ? err.message : String(err);
console.error(' FAIL request error:', msg);
process.exit(1);
}
if (limitsRes.status !== 200) {
console.error(' FAIL status:', limitsRes.status, limitsRes.data);
process.exit(1);
}
const limitsBody = limitsRes.data?.data ?? limitsRes.data;
const tier = limitsBody?.tier;
const opsLimitFromLimits = limitsBody?.opsLimit ?? null;
const opsUsedToday = limitsBody?.opsUsedToday ?? null;
console.log(' tier:', tier);
console.log(' opsLimit:', opsLimitFromLimits);
console.log(' opsUsedToday:', opsUsedToday);
if (tier !== 'GUEST') {
console.error(' FAIL expected tier GUEST for unauthenticated request, got:', tier);
process.exit(1);
}
// 2. GET /api/v1/config/pricing
console.log('\n2. GET /api/v1/config/pricing');
let configRes;
try {
configRes = await axios.get(`${BASE_URL}/api/v1/config/pricing`, {
validateStatus: () => true,
timeout: 5000,
});
} catch (err: unknown) {
const msg = err instanceof Error ? err.message : String(err);
console.error(' FAIL request error:', msg);
process.exit(1);
}
if (configRes.status !== 200) {
console.error(' FAIL status:', configRes.status, configRes.data);
process.exit(1);
}
const configBody = configRes.data?.data ?? configRes.data;
const guestMaxOpsFromConfig = configBody?.limits?.guest?.maxOpsPerDay ?? null;
const freeMaxOpsFromConfig = configBody?.limits?.free?.maxOpsPerDay ?? null;
const dayPassMaxOpsFromConfig = configBody?.limits?.dayPass?.maxOpsPer24h ?? null;
console.log(' limits.guest.maxOpsPerDay:', guestMaxOpsFromConfig);
console.log(' limits.free.maxOpsPerDay:', freeMaxOpsFromConfig);
console.log(' limits.dayPass.maxOpsPer24h:', dayPassMaxOpsFromConfig);
// 3. Assert guest: user/limits and config match (single source of truth)
console.log('\n3. Guest consistency check');
if (opsLimitFromLimits !== guestMaxOpsFromConfig) {
console.error(
' FAIL mismatch: user/limits.opsLimit =',
opsLimitFromLimits,
', config.limits.guest.maxOpsPerDay =',
guestMaxOpsFromConfig
);
process.exit(1);
}
console.log(' OK user/limits.opsLimit === config.limits.guest.maxOpsPerDay ===', opsLimitFromLimits);
// 4. Assert config has free and dayPass limits (for CTA and fallbacks)
console.log('\n4. Config pricing: free and dayPass limits present');
if (typeof freeMaxOpsFromConfig !== 'number' || freeMaxOpsFromConfig < 0) {
console.error(' FAIL config.limits.free.maxOpsPerDay must be a non-negative number, got:', freeMaxOpsFromConfig);
process.exit(1);
}
if (typeof dayPassMaxOpsFromConfig !== 'number' || dayPassMaxOpsFromConfig < 0) {
console.error(' FAIL config.limits.dayPass.maxOpsPer24h must be a non-negative number, got:', dayPassMaxOpsFromConfig);
process.exit(1);
}
console.log(' OK free.maxOpsPerDay =', freeMaxOpsFromConfig, ', dayPass.maxOpsPer24h =', dayPassMaxOpsFromConfig);
console.log('\n✅ All limits API checks passed (guest, free, dayPass from config).');
}
main().catch((err) => {
console.error(err.message || err);
process.exit(1);
});