121 lines
4.5 KiB
TypeScript
121 lines
4.5 KiB
TypeScript
#!/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);
|
||
});
|