- TestCase 新增 startedAt / completedAt 字段 - 流转到"执行中"时记录 startedAt - 流转到"通过/失败/阻塞"时记录 completedAt - 回退到执行中时清除 completedAt - 测试耗时 = startedAt → completedAt 工作日 × 8h - 列表行显示耗时,详情抽屉显示开始/完成/耗时 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
73 lines
2.4 KiB
TypeScript
73 lines
2.4 KiB
TypeScript
import type { Priority } from './derive';
|
|
|
|
export type TestCaseStatus = 'pending' | 'running' | 'passed' | 'failed' | 'blocked';
|
|
|
|
export interface TestCase {
|
|
id: string;
|
|
caseNo: string;
|
|
versionId: string;
|
|
requirementId?: string;
|
|
title: string;
|
|
description?: string;
|
|
priority: Priority;
|
|
assigneeId?: string;
|
|
status: TestCaseStatus;
|
|
startedAt?: string;
|
|
completedAt?: string;
|
|
executedAt?: string;
|
|
executedBy?: string;
|
|
failReason?: string;
|
|
blockReason?: string;
|
|
createdBy: string;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
export const TEST_CASE_STATUS_LABEL: Record<TestCaseStatus, string> = {
|
|
pending: '待执行',
|
|
running: '执行中',
|
|
passed: '通过',
|
|
failed: '失败',
|
|
blocked: '阻塞',
|
|
};
|
|
|
|
export const TEST_CASE_STATUS_COLOR: Record<TestCaseStatus, string> = {
|
|
pending: 'bg-zinc-100 text-zinc-600',
|
|
running: 'bg-blue-50 text-blue-600',
|
|
passed: 'bg-emerald-50 text-emerald-600',
|
|
failed: 'bg-red-50 text-red-600',
|
|
blocked: 'bg-orange-50 text-orange-600',
|
|
};
|
|
|
|
export const TC_ALLOWED_TRANSITIONS: Record<TestCaseStatus, TestCaseStatus[]> = {
|
|
pending: ['running'],
|
|
running: ['passed', 'failed', 'blocked'],
|
|
passed: ['running'],
|
|
failed: ['running'],
|
|
blocked: ['running'],
|
|
};
|
|
|
|
export function canTcTransition(from: TestCaseStatus, to: TestCaseStatus): boolean {
|
|
return TC_ALLOWED_TRANSITIONS[from].includes(to);
|
|
}
|
|
|
|
export function generateCaseNo(existingCases: TestCase[]): string {
|
|
const maxNum = existingCases.reduce((max, c) => {
|
|
const num = parseInt(c.caseNo.replace('TC-', ''), 10);
|
|
return isNaN(num) ? max : Math.max(max, num);
|
|
}, 0);
|
|
return `TC-${String(maxNum + 1).padStart(3, '0')}`;
|
|
}
|
|
|
|
export function calcTestProgress(cases: TestCase[]): { total: number; executed: number; passed: number; failed: number; blocked: number; passRate: number; completionRate: number } {
|
|
const total = cases.length;
|
|
if (total === 0) return { total: 0, executed: 0, passed: 0, failed: 0, blocked: 0, passRate: 0, completionRate: 0 };
|
|
const passed = cases.filter((c) => c.status === 'passed').length;
|
|
const failed = cases.filter((c) => c.status === 'failed').length;
|
|
const blocked = cases.filter((c) => c.status === 'blocked').length;
|
|
const executed = passed + failed + blocked;
|
|
const passRate = (passed + failed) > 0 ? Math.round((passed / (passed + failed)) * 100) : 0;
|
|
const completionRate = Math.round((executed / total) * 100);
|
|
return { total, executed, passed, failed, blocked, passRate, completionRate };
|
|
}
|