Skip to content

Commit 5893924

Browse files
committed
feat: show stdout and errors
1 parent 1db6d42 commit 5893924

File tree

4 files changed

+59
-10
lines changed

4 files changed

+59
-10
lines changed

src/app/api/test-details/[id]/route.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ interface TestHistoryEntry {
1010
startedAt: string; // ISO string
1111
status: 'passed' | 'failed' | 'skipped';
1212
duration?: number;
13+
stdout?: string[];
14+
errors?: string[];
1315
}
1416

1517
export interface TestDetailsData {
@@ -59,6 +61,8 @@ export async function GET(
5961
startedAt: run.startedAt.toISOString(),
6062
status: testInstance.status,
6163
duration: testInstance.duration,
64+
stdout: testInstance.stdout,
65+
errors: testInstance.errors,
6266
});
6367
}
6468
}

src/components/test-detail/test-detail-client.tsx

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export default function TestDetailClient({ testId }: TestDetailClientProps) {
3838
const [data, setData] = React.useState<TestDetailsData | null>(null);
3939
const [isLoading, setIsLoading] = React.useState(true);
4040
const [error, setError] = React.useState<string | null>(null);
41+
const [expandedRun, setExpandedRun] = React.useState<string | null>(null);
4142

4243
React.useEffect(() => {
4344
async function loadData() {
@@ -135,14 +136,46 @@ export default function TestDetailClient({ testId }: TestDetailClientProps) {
135136
</TableHeader>
136137
<TableBody>
137138
{data.history.length > 0 ? data.history.map((run) => (
138-
<TableRow key={run.runId}>
139-
<TableCell className="font-medium truncate" title={run.runId}>{run.runId}</TableCell>
139+
<React.Fragment key={run.runId}>
140+
<TableRow>
141+
<TableCell className="font-medium truncate" title={run.runId}>
142+
<button
143+
className="text-left w-full hover:underline focus:outline-none"
144+
onClick={() => setExpandedRun(expandedRun === run.runId ? null : run.runId)}
145+
aria-expanded={expandedRun === run.runId}
146+
aria-controls={`run-details-${run.runId}`}
147+
>
148+
{run.runId}
149+
{((run.stdout && run.stdout.length > 0) || (run.errors && run.errors.length > 0)) && (
150+
<span className="ml-2 text-xs text-blue-400">[details]</span>
151+
)}
152+
</button>
153+
</TableCell>
140154
<TableCell>{format(new Date(run.startedAt), 'PPP p')}</TableCell>
141155
<TableCell>{getStatusBadge(run.status)}</TableCell>
142156
<TableCell className="text-right">
143157
{run.duration !== undefined ? `${run.duration} ms` : 'N/A'}
144158
</TableCell>
145-
</TableRow>
159+
</TableRow>
160+
{expandedRun === run.runId && ((run.stdout && run.stdout.length > 0) || (run.errors && run.errors.length > 0)) && (
161+
<TableRow>
162+
<TableCell colSpan={4} id={`run-details-${run.runId}`} className="bg-muted/40">
163+
{run.stdout && run.stdout.length > 0 && (
164+
<div className="mb-2">
165+
<div className="font-semibold mb-1">Stdout:</div>
166+
<pre className="bg-black text-white rounded p-2 overflow-x-auto text-xs max-h-48">{run.stdout.join('\n')}</pre>
167+
</div>
168+
)}
169+
{run.errors && run.errors.length > 0 && (
170+
<div>
171+
<div className="font-semibold mb-1 text-red-500">Errors:</div>
172+
<pre className="bg-black text-red-200 rounded p-2 overflow-x-auto text-xs max-h-48">{run.errors.join('\n')}</pre>
173+
</div>
174+
)}
175+
</TableCell>
176+
</TableRow>
177+
)}
178+
</React.Fragment>
146179
)) : (
147180
<TableRow>
148181
<TableCell colSpan={4} className="h-24 text-center">

src/lib/s3-data-service.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ interface PlaywrightTest {
2929
results?: Array<{
3030
status?: string;
3131
duration?: number;
32+
stdout?: string[];
33+
errors?: string[];
3234
}>;
3335
}
3436

@@ -92,6 +94,8 @@ export function transformPlaywrightReportToTestRunSummary(report: PlaywrightRepo
9294
project: test.project,
9395
status: status,
9496
duration: mainResult.duration,
97+
stdout: Array.isArray(mainResult.stdout) ? mainResult.stdout : undefined,
98+
errors: Array.isArray(mainResult.errors) ? mainResult.errors : undefined,
9599
});
96100
}
97101
});
@@ -234,13 +238,19 @@ export async function getTestRunSummaries(year: number, month: number): Promise<
234238
runId: data.runId || item.Key,
235239
startedAt: new Date(data.startedAt || data.startTime || new Date().toISOString()),
236240
trigger,
237-
tests: tests.map(test => ({
238-
id: test.id || test.testId || `${test.title}-${test.project}`,
239-
title: test.title,
240-
project: test.project,
241-
status: (test.status || test.results?.[0]?.status || 'skipped') as 'skipped' | 'passed' | 'failed',
242-
duration: test.duration || test.results?.[0]?.duration,
243-
})),
241+
tests: tests.map(test => {
242+
const mainResult = test.results?.[0];
243+
const base = {
244+
id: test.id || test.testId || `${test.title}-${test.project}`,
245+
title: test.title,
246+
project: test.project,
247+
status: (test.status || mainResult?.status || 'skipped') as 'skipped' | 'passed' | 'failed',
248+
duration: test.duration || mainResult?.duration,
249+
stdout: mainResult?.stdout?.map(item => typeof item === 'object' ? JSON.stringify(item) : String(item)),
250+
errors: mainResult?.errors?.map(item => typeof item === 'object' ? JSON.stringify(item) : String(item)),
251+
};
252+
return base;
253+
}),
244254
};
245255
summaries.push(summary);
246256
}

src/types/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ export interface TestRunSummary {
2626
project: string; // value of projectName
2727
status: 'passed' | 'failed' | 'skipped';
2828
duration?: number; // duration from playwright result if available
29+
stdout?: string[];
30+
errors?: string[];
2931
}[];
3032
}
3133

0 commit comments

Comments
 (0)