feat(load-tests): add K6 load testing suite for critical API paths
K6 scripts for 4 critical paths: - Auth (100 VU): login, register, profile - Listings (500 VU): search with filters, detail view - Search (200 VU): full-text + geo search - Payments (50 VU): create payment, list transactions SLA thresholds: p50<200ms, p95<500ms, p99<1s, error<1%. CI: manual workflow_dispatch with suite selector. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
61
load-tests/lib/config.js
Normal file
61
load-tests/lib/config.js
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Shared K6 configuration and helpers for Goodgo load tests.
|
||||
*/
|
||||
|
||||
export const BASE_URL = __ENV.API_BASE_URL || 'http://localhost:3001';
|
||||
|
||||
/** Standard SLA thresholds — all endpoints must meet these. */
|
||||
export const SLA_THRESHOLDS = {
|
||||
http_req_duration: ['p(50)<200', 'p(95)<500', 'p(99)<1000'],
|
||||
http_req_failed: ['rate<0.01'], // <1% error rate
|
||||
};
|
||||
|
||||
/** Generate a unique phone number for test users. */
|
||||
export function uniquePhone() {
|
||||
const suffix = String(Date.now()).slice(-8);
|
||||
return `09${suffix}`;
|
||||
}
|
||||
|
||||
/** Register a test user and return { accessToken, refreshToken }. */
|
||||
export function registerTestUser(http, suffix) {
|
||||
const phone = suffix || uniquePhone();
|
||||
const payload = JSON.stringify({
|
||||
phone,
|
||||
password: 'LoadTest@1234!',
|
||||
fullName: `K6 User ${phone}`,
|
||||
email: `k6-${phone}@goodgo.test`,
|
||||
});
|
||||
|
||||
const res = http.post(`${BASE_URL}/auth/register`, payload, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
tags: { name: 'setup_register' },
|
||||
});
|
||||
|
||||
if (res.status === 201 || res.status === 200) {
|
||||
return JSON.parse(res.body);
|
||||
}
|
||||
|
||||
// User may already exist — try login
|
||||
const loginRes = http.post(
|
||||
`${BASE_URL}/auth/login`,
|
||||
JSON.stringify({ phone, password: 'LoadTest@1234!' }),
|
||||
{
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
tags: { name: 'setup_login' },
|
||||
},
|
||||
);
|
||||
|
||||
if (loginRes.status === 200 || loginRes.status === 201) {
|
||||
return JSON.parse(loginRes.body);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Build auth headers from an access token. */
|
||||
export function authHeaders(accessToken) {
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user