dev1/backend/tests/regression.mjs

143 lines
4.4 KiB
JavaScript

// Run: node backend/tests/regression.mjs
import assert from 'node:assert/strict';
import crypto from 'node:crypto';
const BASE = process.env.BASE || 'https://dev1.aptivaai.com';
// basic helpers
const j = (o)=>JSON.stringify(o);
const rand = () => Math.random().toString(36).slice(2,10);
const email = `qa+${Date.now()}@aptivaai.com`;
const username = `qa_${rand()}`;
const password = `Aa1!${rand()}Z`;
let cookie = ''; // session cookie set by server1
async function req(path, {method='GET', headers={}, body, stream=false}={}) {
const h = {
'Content-Type': 'application/json',
...(cookie ? { Cookie: cookie } : {}),
...headers
};
const res = await fetch(`${BASE}${path}`, { method, headers: h, body: body ? j(body): undefined });
if (!stream) {
const txt = await res.text();
let json; try { json = JSON.parse(txt); } catch { json = txt; }
return { res, json, txt };
}
return { res }; // caller handles stream via res.body
}
function captureSetCookie(headers) {
const sc = headers.get('set-cookie');
if (sc) cookie = sc.split(';')[0];
}
(async () => {
console.log('→ register');
{
const { res, json } = await req('/api/register', {
method: 'POST',
body: {
username, password,
firstname: 'QA', lastname: 'Bot',
email, zipcode: '30024', state: 'GA', area: 'Atlanta',
career_situation: 'planning'
}
});
assert.equal(res.status, 201, 'register should 201');
captureSetCookie(res.headers);
assert.ok(cookie, 'session cookie set');
}
console.log('→ signin');
{
const { res, json } = await req('/api/signin', {
method:'POST',
body:{ username, password }
});
assert.equal(res.status, 200, 'signin should 200');
captureSetCookie(res.headers);
}
console.log('→ user profile fetch');
{
const { res } = await req('/api/user-profile');
assert.equal(res.status, 200, 'profile fetch 200');
}
console.log('→ support thread + SSE stream');
// create thread
let threadId;
{
const { res, json } = await req('/api/chat/threads', { method:'POST', body:{ title:'QA run' } });
assert.equal(res.status, 200, 'create thread 200');
threadId = json.id; assert.ok(threadId, 'thread id');
}
// start stream
{
const { res } = await req(`/api/chat/threads/${threadId}/stream`, {
method:'POST',
headers: { Accept: 'text/event-stream' },
body: { prompt:'hello there', pageContext:'CareerExplorer', snapshot:null },
stream:true
});
assert.equal(res.ok, true, 'stream start ok');
const reader = res.body.getReader();
let got = false; let lines = 0;
while (true) {
const { value, done } = await reader.read();
if (done) break;
if (value) {
const chunk = new TextDecoder().decode(value);
lines += (chunk.match(/\n/g)||[]).length;
if (chunk.trim()) got = true;
}
if (lines > 5) break; // we saw a few lines; good enough
}
assert.ok(got, 'got streaming content');
}
console.log('→ premium: create career_profile + milestone (server3)');
// create scenario
let career_profile_id;
{
const { res, json } = await req('/api/premium/career-profile', {
method:'POST',
body: {
scenario_title: 'QA Scenario',
career_name: 'Software Developer',
status: 'planned'
}
});
assert.equal(res.status, 200, 'career-profile upsert 200');
career_profile_id = json.career_profile_id;
assert.ok(career_profile_id, 'have career_profile_id');
}
// create milestone
let milestoneId;
{
const { res, json } = await req('/api/premium/milestone', {
method:'POST',
body: {
title: 'QA Milestone',
description: 'Ensure CRUD works',
date: new Date(Date.now()+86400000).toISOString().slice(0,10),
career_profile_id: career_profile_id
}
});
assert.equal(res.status, 201, 'milestone create 201');
milestoneId = (Array.isArray(json) ? json[0]?.id : json?.id);
assert.ok(milestoneId, 'milestone id');
}
// list milestones
{
const { res, json } = await req(`/api/premium/milestones?careerProfileId=${career_profile_id}`);
assert.equal(res.status, 200, 'milestones list 200');
const found = (json.milestones||[]).some(m => m.id === milestoneId);
assert.ok(found, 'created milestone present');
}
console.log('✓ REGRESSION PASSED');
})().catch(e => { console.error('✖ regression failed:', e?.message || e); process.exit(1); });