/** * Load test: GET marketplace/products, GET marketplace/orders * Usage: k6 run loadtests/backend/marketplace.js */ import http from 'k6/http'; import { check, sleep } from 'k6'; import { Rate } from 'k6/metrics'; import { randomString } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js'; const errorRate = new Rate('errors'); const API_ORIGIN = __ENV.API_ORIGIN || __ENV.BASE_URL || 'http://localhost:8080'; const TEST_EMAIL_PREFIX = __ENV.TEST_EMAIL_PREFIX || 'user+market'; const TEST_EMAIL_DOMAIN = __ENV.TEST_EMAIL_DOMAIN || 'example.com'; const TEST_PASSWORD_PREFIX = __ENV.TEST_PASSWORD_PREFIX || 'V3za!market-'; function generateTestUser() { const rand = randomString(8); const pwd = `${TEST_PASSWORD_PREFIX}${rand}`; return { email: `${TEST_EMAIL_PREFIX}${rand}@${TEST_EMAIL_DOMAIN}`, password: pwd, password_confirmation: pwd, username: `mk${rand}`, }; } export const options = { scenarios: { marketplace: { executor: 'ramping-vus', stages: [ { duration: '30s', target: 5 }, { duration: '1m', target: 5 }, { duration: '30s', target: 0 }, ], }, }, thresholds: { http_req_duration: ['p(95)<500', 'p(99)<1000'], errors: ['rate<0.1'], }, }; export function setup() { const users = []; const baseURL = `${API_ORIGIN}/api/v1/auth`; for (let i = 0; i < 10; i++) { const user = generateTestUser(); const registerRes = http.post(`${baseURL}/register`, JSON.stringify(user), { headers: { 'Content-Type': 'application/json' }, }); if (registerRes.status === 201) { const loginRes = http.post(`${baseURL}/login`, JSON.stringify({ email: user.email, password: user.password }), { headers: { 'Content-Type': 'application/json' }, }); if (loginRes.status === 200) { try { const body = JSON.parse(loginRes.body); const token = body.data?.token?.access_token; if (token) users.push({ ...user, token }); } catch (e) {} } } } return { users }; } export default function (data) { const { users } = data; const baseURL = `${API_ORIGIN}/api/v1/marketplace`; const productsRes = http.get(`${baseURL}/products`); const productsOk = check(productsRes, { 'products returns 200': (r) => r.status === 200, }); errorRate.add(!productsOk); sleep(0.5); if (users.length > 0 && Math.random() < 0.5) { const user = users[Math.floor(Math.random() * users.length)]; const ordersRes = http.get(`${baseURL}/orders`, { headers: { Authorization: `Bearer ${user.token}` }, }); check(ordersRes, { 'orders returns 200 or 401': (r) => r.status === 200 || r.status === 401, }); } sleep(1); }