test(unit): expand unit tests and fix stress test robustness
- Add comprehensive useFocusTrap tests (edge cases, disabled elements, empty containers) - Add useSwipeGesture tests (haptic feedback, touch events, disabled state, effect deps) - Enhance animations.test.tsx with Framer Motion mock and component tests - Fix stress-test.js body.length undefined error when requests fail - Fix home-content-v14.tsx for consistency - Clean up generated performance test summary files
This commit is contained in:
@@ -24,27 +24,31 @@ export const options = {
|
||||
|
||||
const BASE_URL = __ENV.BASE_URL || 'http://localhost:3000';
|
||||
|
||||
const pages = [
|
||||
'/',
|
||||
'/about',
|
||||
'/services',
|
||||
'/products',
|
||||
'/news',
|
||||
'/contact',
|
||||
];
|
||||
|
||||
export default function () {
|
||||
// 80% 访问首页、20% 访问关于页面
|
||||
// 注:/api/contact 依赖外部邮件服务并存在 IP 限流,/api/health 未实现,
|
||||
// 因此本脚本仅验证本地营销页面的承载能力。
|
||||
const rand = Math.random();
|
||||
const page = pages[Math.floor(Math.random() * pages.length)];
|
||||
const res = http.get(`${BASE_URL}${page}`, {
|
||||
tags: { name: page },
|
||||
});
|
||||
|
||||
let res;
|
||||
|
||||
if (rand < 0.8) {
|
||||
res = http.get(`${BASE_URL}/`, {
|
||||
tags: { name: 'home' },
|
||||
});
|
||||
} else {
|
||||
res = http.get(`${BASE_URL}/about`, {
|
||||
tags: { name: 'about' },
|
||||
});
|
||||
// 记录非200响应的详细信息以便诊断混合渲染模式下的异常
|
||||
if (res.status !== 200) {
|
||||
const bodyLength = res.body ? res.body.length : 0;
|
||||
console.warn(`[WARN] ${page} returned status ${res.status} (body length: ${bodyLength})`);
|
||||
}
|
||||
|
||||
const success = check(res, {
|
||||
'status is 200': (r) => r.status === 200,
|
||||
'response time < 2000ms': (r) => r.timings.duration < 2000,
|
||||
'body is not empty': (r) => r.body && r.body.length > 0,
|
||||
});
|
||||
|
||||
errorRate.add(!success);
|
||||
@@ -54,7 +58,62 @@ export default function () {
|
||||
}
|
||||
|
||||
export function handleSummary(data) {
|
||||
const metrics = data.metrics;
|
||||
const httpReqs = metrics?.http_reqs?.values || {};
|
||||
const httpDuration = metrics?.http_req_duration?.values || {};
|
||||
const httpFailed = metrics?.http_req_failed?.values || {};
|
||||
|
||||
// 构建按页面分组的统计(利用 k6 按 name 标签自动聚合的子指标)
|
||||
const perPage = {};
|
||||
for (const page of pages) {
|
||||
const pageDur = metrics?.[`http_req_duration{name:${page}}`]?.values;
|
||||
const pageFail = metrics?.[`http_req_failed{name:${page}}`]?.values;
|
||||
perPage[page] = {
|
||||
avg_response_time: pageDur?.avg ?? null,
|
||||
p95_response_time: pageDur?.['p(95)'] ?? null,
|
||||
p99_response_time: pageDur?.['p(99)'] ?? null,
|
||||
max_response_time: pageDur?.max ?? null,
|
||||
error_rate: pageFail?.rate ?? null,
|
||||
total_requests: pageFail ? (pageFail.fails + pageFail.passes) : null,
|
||||
error_count: pageFail?.fails ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
const summary = {
|
||||
type: 'stress-test',
|
||||
stages: [
|
||||
{ duration: '1m', target: 50, desc: 'Ramp up to 50 users' },
|
||||
{ duration: '2m', target: 100, desc: 'Ramp up to 100 users' },
|
||||
{ duration: '3m', target: 200, desc: 'Ramp up to 200 users' },
|
||||
{ duration: '5m', target: 300, desc: 'Peak load at 300 users' },
|
||||
{ duration: '2m', target: 100, desc: 'Scale down to 100 users' },
|
||||
{ duration: '1m', target: 0, desc: 'Scale down to 0' },
|
||||
],
|
||||
thresholds: {
|
||||
http_req_duration: ['p(95)<2000ms', 'p(99)<3000ms'],
|
||||
http_req_failed: ['rate<0.05'],
|
||||
errors: ['rate<0.05'],
|
||||
},
|
||||
results: {
|
||||
overall: {
|
||||
total_requests: httpReqs.count || 0,
|
||||
error_rate: httpFailed.rate || 0,
|
||||
avg_response_time: httpDuration.avg || 0,
|
||||
p95_response_time: httpDuration['p(95)'] || 0,
|
||||
p99_response_time: httpDuration['p(99)'] || 0,
|
||||
max_response_time: httpDuration.max || 0,
|
||||
},
|
||||
per_page: perPage,
|
||||
pages_tested: pages,
|
||||
},
|
||||
checks_passed: data.root_group?.checks?.map((c) => ({
|
||||
name: c.name,
|
||||
passes: c.passes,
|
||||
fails: c.fails,
|
||||
})),
|
||||
};
|
||||
|
||||
return {
|
||||
'performance/stress-test-summary.json': JSON.stringify(data, null, 2),
|
||||
'performance/stress-test-summary.json': JSON.stringify(summary, null, 2),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user