Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 26 additions & 14 deletions archon-ui-main/src/components/ui/TestResultDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ const TestSummaryCard: React.FC<TestSummaryCardProps> = ({ results, isLoading })
);
}

if (!results || !results.summary) {
const summary = results?.summary;

if (!summary) {
return (
<div className="bg-white dark:bg-gray-800 rounded-lg p-6 border border-gray-200 dark:border-gray-700 shadow-sm">
<div className="flex flex-col items-center justify-center py-8 text-center">
Expand All @@ -88,11 +90,18 @@ const TestSummaryCard: React.FC<TestSummaryCardProps> = ({ results, isLoading })
);
}

const { summary } = results;
const successRate = summary.total > 0 ? (summary.passed / summary.total) * 100 : 0;
const safeSummary = {
total: summary.total || 0,
passed: summary.passed || 0,
failed: summary.failed || 0,
skipped: summary.skipped || 0,
duration: summary.duration || 0,
};

const successRate = safeSummary.total > 0 ? (safeSummary.passed / safeSummary.total) * 100 : 0;

const getHealthStatus = () => {
if (summary.failed === 0 && summary.passed > 0) return { text: 'All Tests Passing', color: 'text-green-600 dark:text-green-400', bg: 'bg-green-50 dark:bg-green-900/20' };
if (safeSummary.failed === 0 && safeSummary.passed > 0) return { text: 'All Tests Passing', color: 'text-green-600 dark:text-green-400', bg: 'bg-green-50 dark:bg-green-900/20' };
if (successRate >= 80) return { text: 'Mostly Passing', color: 'text-yellow-600 dark:text-yellow-400', bg: 'bg-yellow-50 dark:bg-yellow-900/20' };
return { text: 'Tests Failing', color: 'text-red-600 dark:text-red-400', bg: 'bg-red-50 dark:bg-red-900/20' };
};
Expand Down Expand Up @@ -127,7 +136,7 @@ const TestSummaryCard: React.FC<TestSummaryCardProps> = ({ results, isLoading })
className="text-center p-4 bg-gray-50 dark:bg-gray-700/50 rounded-lg"
>
<div className="text-2xl font-bold text-gray-800 dark:text-white mb-1">
{summary.total}
{safeSummary.total}
</div>
<div className="text-sm text-gray-600 dark:text-gray-400">Total Tests</div>
</motion.div>
Expand All @@ -140,7 +149,7 @@ const TestSummaryCard: React.FC<TestSummaryCardProps> = ({ results, isLoading })
>
<div className="text-2xl font-bold text-green-600 dark:text-green-400 mb-1 flex items-center justify-center gap-1">
<CheckCircle className="w-5 h-5" />
{summary.passed}
{safeSummary.passed}
</div>
<div className="text-sm text-gray-600 dark:text-gray-400">Passed</div>
</motion.div>
Expand All @@ -153,7 +162,7 @@ const TestSummaryCard: React.FC<TestSummaryCardProps> = ({ results, isLoading })
>
<div className="text-2xl font-bold text-red-600 dark:text-red-400 mb-1 flex items-center justify-center gap-1">
<XCircle className="w-5 h-5" />
{summary.failed}
{safeSummary.failed}
</div>
<div className="text-sm text-gray-600 dark:text-gray-400">Failed</div>
</motion.div>
Expand All @@ -166,7 +175,7 @@ const TestSummaryCard: React.FC<TestSummaryCardProps> = ({ results, isLoading })
>
<div className="text-2xl font-bold text-yellow-600 dark:text-yellow-400 mb-1 flex items-center justify-center gap-1">
<Clock className="w-5 h-5" />
{summary.skipped}
{safeSummary.skipped}
</div>
<div className="text-sm text-gray-600 dark:text-gray-400">Skipped</div>
</motion.div>
Expand Down Expand Up @@ -195,7 +204,7 @@ const TestSummaryCard: React.FC<TestSummaryCardProps> = ({ results, isLoading })
<div className="flex items-center justify-between text-sm text-gray-600 dark:text-gray-400">
<div className="flex items-center gap-2">
<Zap className="w-4 h-4" />
<span>Duration: {(summary.duration / 1000).toFixed(2)}s</span>
<span>Duration: {(safeSummary.duration / 1000).toFixed(2)}s</span>
</div>
{results.timestamp && (
<div className="flex items-center gap-2">
Expand All @@ -206,7 +215,7 @@ const TestSummaryCard: React.FC<TestSummaryCardProps> = ({ results, isLoading })
</div>

{/* Failed Tests Alert */}
{summary.failed > 0 && (
{safeSummary.failed > 0 && (
<motion.div
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: 'auto' }}
Expand All @@ -215,7 +224,7 @@ const TestSummaryCard: React.FC<TestSummaryCardProps> = ({ results, isLoading })
<div className="flex items-center gap-2 text-red-700 dark:text-red-400">
<AlertTriangle className="w-4 h-4" />
<span className="text-sm font-medium">
{summary.failed} test{summary.failed > 1 ? 's' : ''} failing - review errors below
{safeSummary.failed} test{safeSummary.failed > 1 ? 's' : ''} failing - review errors below
</span>
</div>
</motion.div>
Expand All @@ -225,7 +234,10 @@ const TestSummaryCard: React.FC<TestSummaryCardProps> = ({ results, isLoading })
};

const FailedTestsList: React.FC<{ results: TestResults }> = ({ results }) => {
const failedSuites = results.suites.filter(suite => suite.failed > 0);
if (!results || !Array.isArray(results.suites) || !results.summary) {
return null;
}
const failedSuites = results.suites.filter(suite => suite && typeof suite.failed === 'number' && suite.failed > 0);

if (failedSuites.length === 0) {
return null;
Expand All @@ -240,7 +252,7 @@ const FailedTestsList: React.FC<{ results: TestResults }> = ({ results }) => {
<div className="flex items-center gap-3 mb-4">
<XCircle className="w-5 h-5 text-red-500" />
<h3 className="text-lg font-semibold text-gray-800 dark:text-white">
Failed Tests ({results.summary.failed})
Failed Tests ({results?.summary?.failed || 0})
</h3>
</div>

Expand Down Expand Up @@ -400,7 +412,7 @@ export const TestResultDashboard: React.FC<TestResultDashboardProps> = ({
</div>

{/* Failed Tests */}
{results && results.summary.failed > 0 && (
{results?.summary?.failed > 0 && results?.suites && (
<FailedTestsList results={results} />
)}
</div>
Expand Down
2 changes: 1 addition & 1 deletion archon-ui-main/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
mkdirSync(testResultsDir, { recursive: true });
}

const testProcess = exec('npx vitest run --coverage --reporter=verbose --reporter=json', {
const testProcess = exec('npx vitest run --coverage --reporter=dot --reporter=json', {
cwd: process.cwd(),
env: {
...process.env,
Expand Down