mirror of
https://github.com/azaion/admin.git
synced 2026-06-21 08:31:09 +00:00
c7b297de83
- 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>
129 lines
3.9 KiB
JavaScript
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';
|
|
}
|