flare / flare-ui /src /app /components /test /test.component.ts
ciyidogan's picture
Upload 22 files
ac91331 verified
raw
history blame
9.51 kB
import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ApiService } from '../../services/api.service';
interface TestResult {
name: string;
status: 'PASS' | 'FAIL' | 'RUNNING';
duration_ms?: number;
error?: string;
}
interface TestRun {
test_type: string;
start_time: string;
tests: TestResult[];
summary: {
total: number;
passed: number;
failed: number;
duration_ms: number;
};
}
@Component({
selector: 'app-test',
standalone: true,
imports: [CommonModule, FormsModule],
template: `
<div class="test-container">
<h2>System Tests</h2>
<div class="test-controls">
<button class="btn btn-primary" (click)="runAllTests()" [disabled]="running">
Run All Tests
</button>
<button class="btn btn-secondary" (click)="runSelectedTests()" [disabled]="running || selectedTests.length === 0">
Run Selected
</button>
<button class="btn btn-danger" (click)="stopTests()" [disabled]="!running">
Stop
</button>
</div>
<div class="test-categories">
<div class="category">
<label>
<input type="checkbox" [(ngModel)]="allSelected" (change)="toggleAll()">
<strong>All Tests</strong>
</label>
</div>
<div class="category">
<label>
<input type="checkbox" [(ngModel)]="categories.ui" (change)="updateSelection()">
UI Tests (15 tests)
</label>
<div class="sub-tests" *ngIf="categories.ui">
<label><input type="checkbox"> Login Flow</label>
<label><input type="checkbox"> Project CRUD</label>
<label><input type="checkbox"> Version Management</label>
</div>
</div>
<div class="category">
<label>
<input type="checkbox" [(ngModel)]="categories.backend" (change)="updateSelection()">
Backend Tests (22 tests)
</label>
<div class="sub-tests" *ngIf="categories.backend">
<label><input type="checkbox"> Authentication</label>
<label><input type="checkbox"> API Endpoints</label>
<label><input type="checkbox"> Race Conditions</label>
</div>
</div>
<div class="category">
<label>
<input type="checkbox" [(ngModel)]="categories.integration" (change)="updateSelection()">
Integration Tests (18 tests)
</label>
</div>
<div class="category">
<label>
<input type="checkbox" [(ngModel)]="categories.spark" (change)="updateSelection()">
Spark Tests (8 tests)
</label>
</div>
</div>
@if (currentRun) {
<div class="test-results">
<h3>Test Results:</h3>
<div class="results-list">
@for (test of currentRun.tests; track test.name) {
<div class="test-result" [class.pass]="test.status === 'PASS'" [class.fail]="test.status === 'FAIL'">
@if (test.status === 'PASS') {
<span class="status">βœ“</span>
} @else if (test.status === 'FAIL') {
<span class="status">βœ—</span>
} @else {
<span class="status spinner"></span>
}
<span class="name">{{ test.name }}</span>
@if (test.duration_ms) {
<span class="duration">{{ test.duration_ms }}ms</span>
}
@if (test.error) {
<div class="error">{{ test.error }}</div>
}
</div>
}
</div>
@if (!running && currentRun.summary) {
<div class="test-summary">
<div class="progress-bar">
<div
class="progress-fill"
[style.width.%]="(currentRun.summary.passed / currentRun.summary.total) * 100"
[class.success]="currentRun.summary.failed === 0"
[class.warning]="currentRun.summary.failed > 0"
></div>
</div>
<div class="summary-text">
Progress: {{ currentRun.summary.passed + currentRun.summary.failed }}/{{ currentRun.summary.total }}
({{ ((currentRun.summary.passed / currentRun.summary.total) * 100).toFixed(0) }}%)
</div>
<div class="summary-stats">
Passed: {{ currentRun.summary.passed }} |
Failed: {{ currentRun.summary.failed }} |
Total time: {{ (currentRun.summary.duration_ms / 1000).toFixed(1) }}s
</div>
</div>
}
</div>
}
@if (!currentRun && !running) {
<div class="empty-state">
<p>No test results yet. Click "Run All Tests" to start.</p>
</div>
}
</div>
`,
styles: [`
.test-container {
h2 {
margin-bottom: 1.5rem;
}
}
.test-controls {
display: flex;
gap: 0.5rem;
margin-bottom: 1.5rem;
}
.test-categories {
background: white;
border: 1px solid #dee2e6;
border-radius: 0.25rem;
padding: 1rem;
margin-bottom: 1.5rem;
.category {
margin-bottom: 0.5rem;
label {
display: flex;
align-items: center;
gap: 0.5rem;
cursor: pointer;
input[type="checkbox"] {
cursor: pointer;
}
}
}
.sub-tests {
margin-left: 1.5rem;
margin-top: 0.5rem;
label {
display: block;
margin-bottom: 0.25rem;
font-weight: normal;
color: #6c757d;
}
}
}
.test-results {
background: white;
border: 1px solid #dee2e6;
border-radius: 0.25rem;
padding: 1rem;
h3 {
margin-top: 0;
margin-bottom: 1rem;
}
.results-list {
max-height: 400px;
overflow-y: auto;
margin-bottom: 1rem;
}
.test-result {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem;
border-bottom: 1px solid #f0f0f0;
&.pass .status { color: #28a745; }
&.fail .status { color: #dc3545; }
.status {
width: 20px;
text-align: center;
}
.name {
flex: 1;
}
.duration {
color: #6c757d;
font-size: 0.875rem;
}
.error {
width: 100%;
margin-top: 0.5rem;
padding: 0.5rem;
background-color: #f8d7da;
color: #721c24;
border-radius: 0.25rem;
font-size: 0.875rem;
}
}
}
.test-summary {
border-top: 1px solid #dee2e6;
padding-top: 1rem;
.progress-bar {
height: 20px;
background-color: #e9ecef;
border-radius: 0.25rem;
overflow: hidden;
margin-bottom: 0.5rem;
.progress-fill {
height: 100%;
transition: width 0.3s ease;
&.success { background-color: #28a745; }
&.warning { background-color: #ffc107; }
}
}
.summary-text, .summary-stats {
text-align: center;
color: #6c757d;
margin-bottom: 0.5rem;
}
}
.empty-state {
text-align: center;
padding: 3rem;
background-color: white;
border-radius: 0.25rem;
p {
color: #6c757d;
}
}
`]
})
export class TestComponent {
private apiService = inject(ApiService);
running = false;
allSelected = false;
categories = {
ui: false,
backend: false,
integration: false,
spark: false
};
selectedTests: string[] = [];
currentRun: TestRun | null = null;
toggleAll() {
this.categories.ui = this.allSelected;
this.categories.backend = this.allSelected;
this.categories.integration = this.allSelected;
this.categories.spark = this.allSelected;
this.updateSelection();
}
updateSelection() {
this.selectedTests = [];
if (this.categories.ui) this.selectedTests.push('ui');
if (this.categories.backend) this.selectedTests.push('backend');
if (this.categories.integration) this.selectedTests.push('integration');
if (this.categories.spark) this.selectedTests.push('spark');
this.allSelected = this.selectedTests.length === 4;
}
runAllTests() {
this.running = true;
this.apiService.runTests('all').subscribe({
next: (result) => {
this.currentRun = result;
this.running = false;
},
error: (err) => {
console.error('Test run failed:', err);
this.running = false;
}
});
}
runSelectedTests() {
// TODO: Implement selected tests
console.log('Running selected tests:', this.selectedTests);
this.runAllTests(); // For now, just run all
}
stopTests() {
this.running = false;
// TODO: Implement stop functionality
}
}