feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
import { FullConfig, Suite, TestCase, TestResult, Reporter } from '@playwright/test/reporter';
|
||||
import colors from 'ansi-colors';
|
||||
|
||||
interface TestProgress {
|
||||
total: number;
|
||||
passed: number;
|
||||
failed: number;
|
||||
skipped: number;
|
||||
current: string;
|
||||
startTime: number;
|
||||
}
|
||||
|
||||
class TestProgressBar {
|
||||
private progress: TestProgress;
|
||||
private barWidth: number = 40;
|
||||
private lastUpdate: number = 0;
|
||||
|
||||
constructor(total: number) {
|
||||
this.progress = {
|
||||
total,
|
||||
passed: 0,
|
||||
failed: 0,
|
||||
skipped: 0,
|
||||
current: '',
|
||||
startTime: Date.now()
|
||||
};
|
||||
}
|
||||
|
||||
update(testName: string, result?: TestResult) {
|
||||
if (result) {
|
||||
if (result.status === 'passed') this.progress.passed++;
|
||||
else if (result.status === 'failed') this.progress.failed++;
|
||||
else if (result.status === 'skipped') this.progress.skipped++;
|
||||
}
|
||||
this.progress.current = testName;
|
||||
this.render();
|
||||
}
|
||||
|
||||
private render() {
|
||||
const now = Date.now();
|
||||
if (now - this.lastUpdate < 100) return;
|
||||
this.lastUpdate = now;
|
||||
|
||||
const completed = this.progress.passed + this.progress.failed + this.progress.skipped;
|
||||
const percentage = Math.min(100, Math.round((completed / this.progress.total) * 100));
|
||||
const filled = Math.round((this.barWidth * percentage) / 100);
|
||||
const empty = this.barWidth - filled;
|
||||
|
||||
const elapsed = Date.now() - this.progress.startTime;
|
||||
const elapsedSeconds = Math.floor(elapsed / 1000);
|
||||
const avgTime = completed > 0 ? elapsed / completed : 0;
|
||||
const remaining = (this.progress.total - completed) * avgTime;
|
||||
const remainingSeconds = Math.floor(remaining / 1000);
|
||||
|
||||
const bar = colors.cyan('█').repeat(filled) + colors.gray('░').repeat(empty);
|
||||
const statusColor = this.progress.failed > 0 ? colors.red : colors.green;
|
||||
const statusText = statusColor(`✓ ${this.progress.passed} | ✗ ${this.progress.failed} | ⊘ ${this.progress.skipped}`);
|
||||
|
||||
const timeText = colors.gray(`⏱ ${elapsedSeconds}s | ⏳ ~${remainingSeconds}s`);
|
||||
const currentText = colors.yellow(this.progress.current.substring(0, 50));
|
||||
|
||||
process.stdout.write('\r' + ' '.repeat(200));
|
||||
process.stdout.write(`\r[${bar}] ${percentage}% | ${statusText} | ${timeText}`);
|
||||
process.stdout.write(`\n ${colors.blue('▶')} ${currentText}`);
|
||||
}
|
||||
|
||||
finalize() {
|
||||
const elapsed = Date.now() - this.progress.startTime;
|
||||
const elapsedSeconds = (elapsed / 1000).toFixed(2);
|
||||
|
||||
process.stdout.write('\r' + ' '.repeat(200));
|
||||
process.stdout.write('\n');
|
||||
|
||||
const statusColor = this.progress.failed > 0 ? colors.red : colors.green;
|
||||
const statusText = statusColor(
|
||||
`测试完成: ${this.progress.passed} 通过, ${this.progress.failed} 失败, ${this.progress.skipped} 跳过`
|
||||
);
|
||||
|
||||
console.log(colors.bold('\n' + '═'.repeat(60)));
|
||||
console.log(colors.bold(' 测试执行完成'));
|
||||
console.log('═'.repeat(60));
|
||||
console.log(` ${statusText}`);
|
||||
console.log(` ${colors.gray(`总用时: ${elapsedSeconds}秒`)}`);
|
||||
console.log(` ${colors.gray(`总测试数: ${this.progress.total}`)}`);
|
||||
console.log('═'.repeat(60) + '\n');
|
||||
}
|
||||
}
|
||||
|
||||
class ProgressReporter implements Reporter {
|
||||
private progressBar: TestProgressBar | null = null;
|
||||
private totalTests: number = 0;
|
||||
|
||||
onBegin(config: FullConfig, suite: Suite) {
|
||||
this.totalTests = this.countTests(suite);
|
||||
console.log(colors.bold('\n' + '═'.repeat(60)));
|
||||
console.log(colors.bold(' 开始执行测试'));
|
||||
console.log('═'.repeat(60));
|
||||
console.log(` ${colors.blue(`总测试数: ${this.totalTests}`)}`);
|
||||
console.log(` ${colors.gray(`测试套件: ${suite.allTests().length}`)}`);
|
||||
console.log('═'.repeat(60) + '\n');
|
||||
|
||||
this.progressBar = new TestProgressBar(this.totalTests);
|
||||
}
|
||||
|
||||
onTestBegin(test: TestCase) {
|
||||
if (this.progressBar) {
|
||||
this.progressBar.update(test.title);
|
||||
}
|
||||
}
|
||||
|
||||
onTestEnd(test: TestCase, result: TestResult) {
|
||||
if (this.progressBar) {
|
||||
this.progressBar.update(test.title, result);
|
||||
}
|
||||
}
|
||||
|
||||
onEnd() {
|
||||
if (this.progressBar) {
|
||||
this.progressBar.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
private countTests(suite: Suite): number {
|
||||
let count = 0;
|
||||
suite.allTests().forEach(() => count++);
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
export default ProgressReporter;
|
||||
Reference in New Issue
Block a user