Files
admin/scripts/perf-scenarios.js
T
Oleksandr Bezdieniezhnykh c7b297de83
ci/woodpecker/push/01-test Pipeline failed
ci/woodpecker/push/02-build-push unknown status
refactor: remove deploy.cmd and update Dockerfile for health checks
- Deleted the deploy.cmd script as it was no longer needed.
- Updated Dockerfile to include curl for health checks and added a non-root user for improved security.
- Modified health check command to use curl for better reliability.
- Adjusted docker-compose.test.yml to reflect changes in health check configuration.
- Cleaned up appsettings.json and removed unused configuration properties.
- Removed Resource entity and related requests from the codebase as part of the architectural shift.
- Updated documentation to reflect the removal of hardware binding and related endpoints.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 08:47:21 +03:00

129 lines
3.9 KiB
JavaScript

import http from 'k6/http';
import { check, sleep } from 'k6';
const BASE_URL = __ENV.BASE_URL || 'http://localhost:8080';
const ADMIN_EMAIL = __ENV.ADMIN_EMAIL || 'admin@azaion.com';
const ADMIN_PASSWORD = __ENV.ADMIN_PASSWORD || 'Admin1234';
export const options = {
scenarios: {
nft_perf_01_login: {
executor: 'constant-vus',
vus: 10,
duration: '30s',
exec: 'login',
tags: { scenario: 'nft_perf_01_login' },
},
nft_perf_04_user_list: {
executor: 'constant-vus',
vus: 10,
duration: '30s',
exec: 'userList',
tags: { scenario: 'nft_perf_04_user_list' },
startTime: '35s',
},
},
thresholds: {
'http_req_duration{scenario:nft_perf_01_login}': ['p(95)<500'],
'http_req_duration{scenario:nft_perf_04_user_list}': ['p(95)<1000'],
'http_req_failed{scenario:nft_perf_01_login}': ['rate<0.01'],
'http_req_failed{scenario:nft_perf_04_user_list}': ['rate<0.01'],
},
};
// setup() runs once before all VUs. Pre-fetch a JWT so the user-list scenario
// measures only the listing path, not login latency.
export function setup() {
const res = http.post(
`${BASE_URL}/login`,
JSON.stringify({ Email: ADMIN_EMAIL, Password: ADMIN_PASSWORD }),
{ headers: { 'Content-Type': 'application/json' } }
);
if (res.status !== 200) {
throw new Error(`setup: login failed (status ${res.status}): ${res.body}`);
}
const body = JSON.parse(res.body);
const token = body.token || body.Token;
if (!token) {
throw new Error(`setup: login response missing Token: ${res.body}`);
}
return { token };
}
export function login() {
const res = http.post(
`${BASE_URL}/login`,
JSON.stringify({ Email: ADMIN_EMAIL, Password: ADMIN_PASSWORD }),
{
headers: { 'Content-Type': 'application/json' },
tags: { scenario: 'nft_perf_01_login' },
}
);
check(res, {
'login status 200': (r) => r.status === 200,
'login returned token': (r) => {
try {
const body = JSON.parse(r.body);
return !!(body.token || body.Token);
} catch {
return false;
}
},
});
sleep(0.1);
}
export function userList(data) {
const res = http.get(`${BASE_URL}/users`, {
headers: { Authorization: `Bearer ${data.token}` },
tags: { scenario: 'nft_perf_04_user_list' },
});
check(res, {
'user list status 200': (r) => r.status === 200,
'user list returned >= 500 users': (r) => {
try {
const arr = JSON.parse(r.body);
return Array.isArray(arr) && arr.length >= 500;
} catch {
return false;
}
},
});
sleep(0.1);
}
export function handleSummary(data) {
return {
'e2e/test-results/perf-summary.json': JSON.stringify(data, null, 2),
stdout: textSummary(data),
};
}
function textSummary(data) {
const lines = [];
lines.push('');
lines.push('=== PERF SUMMARY ===');
for (const [name, metric] of Object.entries(data.metrics)) {
if (!name.startsWith('http_req_duration') && !name.startsWith('http_req_failed')) continue;
const vals = metric.values || {};
const parts = [];
if (vals['p(50)'] !== undefined) parts.push(`p50=${vals['p(50)'].toFixed(1)}ms`);
if (vals['p(95)'] !== undefined) parts.push(`p95=${vals['p(95)'].toFixed(1)}ms`);
if (vals['p(99)'] !== undefined) parts.push(`p99=${vals['p(99)'].toFixed(1)}ms`);
if (vals.rate !== undefined) parts.push(`rate=${(vals.rate * 100).toFixed(2)}%`);
if (vals.count !== undefined) parts.push(`count=${vals.count}`);
lines.push(` ${name}: ${parts.join(' · ')}`);
}
if (data.root_group && data.root_group.checks) {
const checks = data.root_group.checks;
if (checks.length > 0) {
lines.push('--- checks ---');
for (const c of checks) {
lines.push(` ${c.name}: ${c.passes} pass / ${c.fails} fail`);
}
}
}
lines.push('====================');
return lines.join('\n') + '\n';
}