99 lines
2.9 KiB
JavaScript
99 lines
2.9 KiB
JavaScript
import http from 'k6/http';
|
|
import { check, sleep, Trend } from 'k6';
|
|
import { Rate } from 'k6/metrics';
|
|
|
|
export let options = {
|
|
stages: [
|
|
{ duration: '1m', target: 20 }, // warm-up
|
|
{ duration: '3m', target: 50 }, // peak load
|
|
{ duration: '1m', target: 0 }, // ramp down
|
|
],
|
|
thresholds: {
|
|
http_req_duration: [
|
|
{ threshold: 'p(95)<800', abortOnFail: true },
|
|
{ threshold: 'p(99)<2000', abortOnFail: false },
|
|
],
|
|
'api success rate': ['rate>0.99'],
|
|
},
|
|
noConnectionReuse: false,
|
|
maxRedirects: 5,
|
|
};
|
|
|
|
const BASE_URL = __ENV.BASE_URL || 'http://localhost:8000';
|
|
const ADMIN_TOKEN = __ENV.ADMIN_TOKEN || ''; // optional
|
|
|
|
// Custom metrics
|
|
const loginTrend = new Trend('login_duration');
|
|
const registerTrend = new Trend('register_duration');
|
|
const jobsTrend = new Trend('jobs_list_duration');
|
|
const leadsTrend = new Trend('leads_list_duration');
|
|
|
|
// Helper: get auth headers
|
|
function authHeaders() {
|
|
return ADMIN_TOKEN ? { Authorization: `Bearer ${ADMIN_TOKEN}` } : {};
|
|
}
|
|
|
|
export default function () {
|
|
// 1. Login flow (simulate admin)
|
|
let loginRes = http.post(
|
|
`${BASE_URL}/api/auth/login`,
|
|
JSON.stringify({
|
|
email: 'admin@example.com',
|
|
password: 'test123',
|
|
loginTarget: 'admin',
|
|
}),
|
|
{
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
Accept: 'application/json',
|
|
'x-portal-target': 'admin',
|
|
},
|
|
}
|
|
);
|
|
loginTrend.add(loginRes.timings.duration);
|
|
let success = check(loginRes, {
|
|
'login 200': (r) => r.status === 200,
|
|
'login has token': (r) => {
|
|
const t = r.json('token');
|
|
return t !== undefined && t !== null;
|
|
},
|
|
});
|
|
|
|
if (success) {
|
|
const body = loginRes.json();
|
|
const token = body.token;
|
|
const headers = { ...authHeaders(), Authorization: `Bearer ${token}` };
|
|
|
|
// 2. List companies
|
|
let res = http.get(`${BASE_URL}/api/admin/companies`, { headers });
|
|
check(res, { 'companies 200': (r) => r.status === 200 });
|
|
jobsTrend.add(res.timings.duration);
|
|
|
|
// 3. List jobs (via companies service)
|
|
res = http.get(`${BASE_URL}/api/admin/companies/jobs`, { headers });
|
|
check(res, { 'jobs 200': (r) => r.status === 200 });
|
|
leadsTrend.add(res.timings.duration);
|
|
|
|
// 4. Get single company detail
|
|
if (res.json().length > 0) {
|
|
const firstJob = res.json()[0];
|
|
if (firstJob.id) {
|
|
http.get(`${BASE_URL}/api/admin/companies/jobs/${firstJob.id}`, { headers });
|
|
}
|
|
}
|
|
|
|
// 5. List leads
|
|
res = http.get(`${BASE_URL}/api/admin/leads`, { headers });
|
|
check(res, { 'leads 200': (r) => r.status === 200 });
|
|
leadsTrend.add(res.timings.duration);
|
|
}
|
|
|
|
sleep(2);
|
|
}
|
|
|
|
// Summarize metrics at end
|
|
export function teardown() {
|
|
console.log(`Login avg: ${loginTrend.avg.toFixed(2)}ms`);
|
|
console.log(`Jobs list avg: ${jobsTrend.avg.toFixed(2)}ms`);
|
|
console.log(`Leads list avg: ${leadsTrend.avg.toFixed(2)}ms`);
|
|
}
|