90 lines
3.1 KiB
JavaScript
90 lines
3.1 KiB
JavaScript
#!/usr/bin/env node
|
|
// Smoke test for WT-A: hits the running server on :3001 and checks
|
|
// (1) /api/health 200
|
|
// (2) /api/auth/login returns token + offline_jwt_secret
|
|
// (3) /api/auth/me/credentials works (regression check on the existing fix)
|
|
// (4) a 2MB JSON body returns 413 (body limit)
|
|
// (5) CORS rejects an evil origin in prod-like mode (skipped here; dev allows any)
|
|
|
|
const http = require('http');
|
|
|
|
function request(method, path, { body, headers, expectStatus } = {}) {
|
|
return new Promise((resolve, reject) => {
|
|
const opts = {
|
|
host: 'localhost',
|
|
port: 3001,
|
|
path,
|
|
method,
|
|
headers: { 'Content-Type': 'application/json', ...(headers || {}) },
|
|
};
|
|
if (body) {
|
|
opts.headers['Content-Length'] = Buffer.byteLength(body);
|
|
}
|
|
const req = http.request(opts, (res) => {
|
|
let data = '';
|
|
res.on('data', (c) => (data += c));
|
|
res.on('end', () => {
|
|
const ok = expectStatus == null || res.statusCode === expectStatus;
|
|
resolve({ status: res.statusCode, body: data, ok });
|
|
});
|
|
});
|
|
req.on('error', reject);
|
|
if (body) req.write(body);
|
|
req.end();
|
|
});
|
|
}
|
|
|
|
(async () => {
|
|
const results = [];
|
|
|
|
// (1) health
|
|
let r = await request('GET', '/api/health', { expectStatus: 200 });
|
|
results.push(['GET /api/health → 200', r.ok, r.status]);
|
|
|
|
// (2) login
|
|
r = await request('POST', '/api/auth/login', {
|
|
body: JSON.stringify({ email: 'admin@school.com', password: 'admin123' }),
|
|
expectStatus: 200,
|
|
});
|
|
let loginBody = null;
|
|
try { loginBody = JSON.parse(r.body); } catch (e) { /* ignore */ }
|
|
const hasToken = !!loginBody?.token;
|
|
const hasOffline = loginBody?.offline_jwt_secret != null; // dev default true
|
|
results.push(['POST /api/auth/login returns token', hasToken, hasToken ? 'present' : 'missing']);
|
|
results.push(['POST /api/auth/login returns offline_jwt_secret', hasOffline, hasOffline ? 'present' : 'missing/null']);
|
|
|
|
// (3) /api/auth/me/credentials with the token
|
|
if (hasToken) {
|
|
r = await request('GET', '/api/auth/me/credentials', {
|
|
headers: { Authorization: `Bearer ${loginBody.token}` },
|
|
expectStatus: 200,
|
|
});
|
|
results.push(['GET /api/auth/me/credentials (with token) → 200', r.ok, r.status]);
|
|
}
|
|
|
|
// (4) 2MB JSON body → 413
|
|
const big = JSON.stringify({ data: 'x'.repeat(2 * 1024 * 1024) });
|
|
r = await request('POST', '/api/auth/login', {
|
|
body: big,
|
|
// We expect either 400 (bad credentials parsed first) or 413 (body too large)
|
|
// We accept any 4xx — what matters is it's NOT 500 and NOT 200.
|
|
});
|
|
const is4xx = r.status >= 400 && r.status < 500;
|
|
results.push(['2MB JSON body rejected (4xx)', is4xx, r.status]);
|
|
|
|
// Print results
|
|
let pass = 0;
|
|
let fail = 0;
|
|
for (const [name, ok, detail] of results) {
|
|
const mark = ok ? '✓' : '✗';
|
|
console.log(`${mark} ${name} — ${detail}`);
|
|
if (ok) pass++;
|
|
else fail++;
|
|
}
|
|
console.log(`\n${pass}/${results.length} checks passed.`);
|
|
process.exit(fail === 0 ? 0 : 1);
|
|
})().catch((err) => {
|
|
console.error('Smoke test crashed:', err.message);
|
|
process.exit(2);
|
|
});
|