diff --git a/src/components/admin/IntegrationTestRunner.tsx b/src/components/admin/IntegrationTestRunner.tsx index e4149e2b..43264161 100644 --- a/src/components/admin/IntegrationTestRunner.tsx +++ b/src/components/admin/IntegrationTestRunner.tsx @@ -18,6 +18,7 @@ import { IntegrationTestRunner as TestRunner, allTestSuites, type TestResult, fo import { Play, Square, Download, ChevronDown, CheckCircle2, XCircle, Clock, SkipForward, Copy, ClipboardX } from 'lucide-react'; import { toast } from 'sonner'; import { handleError } from '@/lib/errorHandler'; +import { CleanupReport } from '@/components/ui/cleanup-report'; export function IntegrationTestRunner() { const superuserGuard = useSuperuserGuard(); @@ -252,6 +253,11 @@ export function IntegrationTestRunner() { + {/* Cleanup Report */} + {!isRunning && summary.cleanup && ( + + )} + {/* Results */} {results.length > 0 && ( diff --git a/src/components/ui/cleanup-report.tsx b/src/components/ui/cleanup-report.tsx new file mode 100644 index 00000000..a3cda48b --- /dev/null +++ b/src/components/ui/cleanup-report.tsx @@ -0,0 +1,221 @@ +/** + * Cleanup Verification Report Component + * + * Displays detailed results of test data cleanup after integration tests complete. + * Shows tables cleaned, records deleted, errors, and verification status. + */ + +import { CheckCircle2, XCircle, AlertCircle, Database, Trash2, Clock } from 'lucide-react'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { Badge } from '@/components/ui/badge'; +import { Progress } from '@/components/ui/progress'; +import type { CleanupSummary } from '@/lib/integrationTests/testCleanup'; + +interface CleanupReportProps { + summary: CleanupSummary; + className?: string; +} + +export function CleanupReport({ summary, className = '' }: CleanupReportProps) { + const successCount = summary.results.filter(r => !r.error).length; + const errorCount = summary.results.filter(r => r.error).length; + const successRate = summary.results.length > 0 + ? (successCount / summary.results.length) * 100 + : 0; + + return ( + + + + + Test Data Cleanup Report + + + + + {/* Summary Stats */} +
+
+

Total Deleted

+

+ {summary.totalDeleted.toLocaleString()} +

+
+ +
+

Tables Cleaned

+

+ {successCount}/{summary.results.length} +

+
+ +
+

Duration

+

+ + {(summary.totalDuration / 1000).toFixed(1)}s +

+
+ +
+

Status

+ + {summary.success ? ( + + + Complete + + ) : ( + + + Failed + + )} + +
+
+ + {/* Success Rate Progress */} +
+
+ Success Rate + {successRate.toFixed(1)}% +
+ +
+ + {/* Table-by-Table Results */} +
+

+ + Cleanup Details +

+ +
+ {summary.results.map((result, index) => ( +
+
+ {result.error ? ( + + ) : result.deleted > 0 ? ( + + ) : ( + + )} + +
+

+ {result.table} +

+ {result.error && ( +

+ {result.error} +

+ )} +
+
+ +
+ 0 ? "default" : "secondary"} + className="font-mono" + > + {result.deleted} deleted + + + {result.duration}ms + +
+
+ ))} +
+
+ + {/* Error Summary (if any) */} + {errorCount > 0 && ( +
+
+ +
+

+ {errorCount} {errorCount === 1 ? 'table' : 'tables'} failed to clean +

+

+ Check error messages above for details. Test data may remain in database. +

+
+
+
+ )} + + {/* Success Message */} + {summary.success && summary.totalDeleted > 0 && ( +
+
+ +
+

+ Cleanup completed successfully +

+

+ All test data has been removed from the database. +

+
+
+
+ )} + + {/* No Data Message */} + {summary.success && summary.totalDeleted === 0 && ( +
+
+ +
+

+ No test data found +

+

+ Database is already clean or no test data was created during this run. +

+
+
+
+ )} +
+
+ ); +} + +/** + * Compact version for inline display in test results + */ +export function CleanupReportCompact({ summary }: CleanupReportProps) { + return ( +
+ + +
+

+ Cleanup: {summary.totalDeleted} records deleted +

+

+ {summary.results.filter(r => !r.error).length}/{summary.results.length} tables cleaned + {' • '} + {(summary.totalDuration / 1000).toFixed(1)}s +

+
+ + {summary.success ? ( + + ) : ( + + )} +
+ ); +}