flare / flare-ui /src /app /components /test /test.component.ts
ciyidogan's picture
Update flare-ui/src/app/components/test/test.component.ts
6aa3dd7 verified
raw
history blame
11.6 kB
import { Component, inject, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatListModule } from '@angular/material/list';
import { MatChipsModule } from '@angular/material/chips';
import { ApiService } from '../../services/api.service';
import { HttpClient } from '@angular/common/http';
interface TestResult {
name: string;
status: 'PASS' | 'FAIL' | 'RUNNING' | 'SKIPPED';
duration_ms?: number;
error?: string;
details?: string;
}
interface TestCategory {
name: string;
displayName: string;
tests: TestCase[];
selected: boolean;
expanded: boolean;
}
interface TestCase {
name: string;
category: string;
selected: boolean;
testFn: () => Promise<TestResult>;
}
@Component({
selector: 'app-test',
standalone: true,
imports: [
CommonModule,
FormsModule,
MatProgressBarModule,
MatCheckboxModule,
MatButtonModule,
MatIconModule,
MatExpansionModule,
MatListModule,
MatChipsModule
],
templateUrl: './test.component.html',
styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {
private apiService = inject(ApiService);
private http = inject(HttpClient);
running = false;
currentTest: string = '';
testResults: TestResult[] = [];
categories: TestCategory[] = [
{
name: 'auth',
displayName: 'Authentication Tests',
tests: [],
selected: false,
expanded: false
},
{
name: 'api',
displayName: 'API Endpoint Tests',
tests: [],
selected: false,
expanded: false
},
{
name: 'validation',
displayName: 'Validation Tests',
tests: [],
selected: false,
expanded: false
},
{
name: 'integration',
displayName: 'Integration Tests',
tests: [],
selected: false,
expanded: false
}
];
get allSelected(): boolean {
return this.categories.every(c => c.selected);
}
get selectedTests(): TestCase[] {
return this.categories
.filter(c => c.selected)
.flatMap(c => c.tests);
}
get totalTests(): number {
return this.categories.reduce((sum, c) => sum + c.tests.length, 0);
}
get passedTests(): number {
return this.testResults.filter(r => r.status === 'PASS').length;
}
get failedTests(): number {
return this.testResults.filter(r => r.status === 'FAIL').length;
}
get progress(): number {
if (this.testResults.length === 0) return 0;
return (this.testResults.length / this.selectedTests.length) * 100;
}
ngOnInit() {
this.initializeTests();
}
initializeTests() {
// Authentication Tests
this.addTest('auth', 'Login with valid credentials', async () => {
try {
const response = await this.http.post('/api/login', {
username: 'admin',
password: 'admin'
}).toPromise() as any;
return {
name: 'Login with valid credentials',
status: response?.token ? 'PASS' : 'FAIL',
duration_ms: 120
};
} catch (error) {
return {
name: 'Login with valid credentials',
status: 'FAIL',
error: 'Login failed',
duration_ms: 120
};
}
});
this.addTest('auth', 'Login with invalid credentials', async () => {
try {
await this.http.post('/api/login', {
username: 'admin',
password: 'wrong'
}).toPromise();
return {
name: 'Login with invalid credentials',
status: 'FAIL',
error: 'Expected 401 but got success',
duration_ms: 80
};
} catch (error: any) {
return {
name: 'Login with invalid credentials',
status: error.status === 401 ? 'PASS' : 'FAIL',
duration_ms: 80,
details: 'Correctly rejected invalid credentials'
};
}
});
// API Endpoint Tests
this.addTest('api', 'GET /api/environment', async () => {
const start = Date.now();
try {
const response = await this.apiService.getEnvironment().toPromise();
return {
name: 'GET /api/environment',
status: response?.work_mode ? 'PASS' : 'FAIL',
duration_ms: Date.now() - start
};
} catch (error) {
return {
name: 'GET /api/environment',
status: 'FAIL',
error: 'Failed to get environment',
duration_ms: Date.now() - start
};
}
});
this.addTest('api', 'GET /api/projects', async () => {
const start = Date.now();
try {
const response = await this.apiService.getProjects().toPromise();
return {
name: 'GET /api/projects',
status: Array.isArray(response) ? 'PASS' : 'FAIL',
duration_ms: Date.now() - start,
details: `Retrieved ${response?.length || 0} projects`
};
} catch (error) {
return {
name: 'GET /api/projects',
status: 'FAIL',
error: 'Failed to get projects',
duration_ms: Date.now() - start
};
}
});
this.addTest('api', 'GET /api/apis', async () => {
const start = Date.now();
try {
const response = await this.apiService.getAPIs().toPromise();
return {
name: 'GET /api/apis',
status: Array.isArray(response) ? 'PASS' : 'FAIL',
duration_ms: Date.now() - start,
details: `Retrieved ${response?.length || 0} APIs`
};
} catch (error) {
return {
name: 'GET /api/apis',
status: 'FAIL',
error: 'Failed to get APIs',
duration_ms: Date.now() - start
};
}
});
// Integration Tests
this.addTest('integration', 'Create and delete project', async () => {
const start = Date.now();
let projectId: number | undefined;
try {
// Create project
const createResponse = await this.apiService.createProject({
name: `test_project_${Date.now()}`,
caption: 'Test Project'
}).toPromise() as any;
if (!createResponse?.id) {
throw new Error('Project creation failed');
}
projectId = createResponse.id;
// Delete project
await this.apiService.deleteProject(projectId).toPromise();
return {
name: 'Create and delete project',
status: 'PASS',
duration_ms: Date.now() - start,
details: 'Project lifecycle test passed'
};
} catch (error: any) {
// Try to clean up if project was created
if (projectId !== undefined) {
try {
await this.apiService.deleteProject(projectId).toPromise();
} catch {}
}
return {
name: 'Create and delete project',
status: 'FAIL',
error: error.message || 'Test failed',
duration_ms: Date.now() - start
};
}
});
this.addTest('integration', 'API used in intent cannot be deleted', async () => {
const start = Date.now();
try {
// Try to delete an API that's used in intents
await this.apiService.deleteAPI('book_flight_api').toPromise();
return {
name: 'API used in intent cannot be deleted',
status: 'FAIL',
error: 'Expected error but API was deleted',
duration_ms: Date.now() - start
};
} catch (error: any) {
return {
name: 'API used in intent cannot be deleted',
status: error.status === 400 ? 'PASS' : 'FAIL',
duration_ms: Date.now() - start,
details: 'Correctly prevented deletion of API in use'
};
}
});
// Validation Tests
this.addTest('validation', 'Regex validation - valid pattern', async () => {
const start = Date.now();
try {
const response = await this.apiService.validateRegex('^[A-Z]{3}$', 'ABC').toPromise();
return {
name: 'Regex validation - valid pattern',
status: response.valid && response.matches ? 'PASS' : 'FAIL',
duration_ms: Date.now() - start
};
} catch (error) {
return {
name: 'Regex validation - valid pattern',
status: 'FAIL',
error: 'Validation failed',
duration_ms: Date.now() - start
};
}
});
this.addTest('validation', 'Regex validation - invalid pattern', async () => {
const start = Date.now();
try {
const response = await this.apiService.validateRegex('[invalid', 'test').toPromise();
return {
name: 'Regex validation - invalid pattern',
status: !response.valid ? 'PASS' : 'FAIL',
duration_ms: Date.now() - start,
details: 'Correctly identified invalid regex'
};
} catch (error) {
return {
name: 'Regex validation - invalid pattern',
status: 'PASS',
duration_ms: Date.now() - start,
details: 'Correctly rejected invalid regex'
};
}
});
// Update test counts
this.categories.forEach(cat => {
cat.displayName = `${cat.displayName} (${cat.tests.length} tests)`;
});
}
private addTest(category: string, name: string, testFn: () => Promise<TestResult>) {
const cat = this.categories.find(c => c.name === category);
if (cat) {
cat.tests.push({
name,
category,
selected: true,
testFn
});
}
}
toggleAll() {
const newState = !this.allSelected;
this.categories.forEach(c => c.selected = newState);
}
async runAllTests() {
this.categories.forEach(c => c.selected = true);
await this.runTests();
}
async runSelectedTests() {
await this.runTests();
}
async runTests() {
if (this.running) return;
this.running = true;
this.testResults = [];
this.currentTest = '';
const testsToRun = this.selectedTests;
for (const test of testsToRun) {
this.currentTest = test.name;
try {
const result = await test.testFn();
this.testResults.push(result);
} catch (error: any) {
this.testResults.push({
name: test.name,
status: 'FAIL',
error: error.message || 'Unexpected error'
});
}
// Small delay between tests
await new Promise(resolve => setTimeout(resolve, 100));
}
this.running = false;
this.currentTest = '';
}
stopTests() {
this.running = false;
this.currentTest = '';
}
getTestResult(testName: string): TestResult | undefined {
return this.testResults.find(r => r.name === testName);
}
getCategoryResults(category: TestCategory): { passed: number; failed: number; total: number } {
const categoryResults = this.testResults.filter(r =>
category.tests.some(t => t.name === r.name)
);
return {
passed: categoryResults.filter(r => r.status === 'PASS').length,
failed: categoryResults.filter(r => r.status === 'FAIL').length,
total: category.tests.length
};
}
}