Skip to content

Commit 3de1c69

Browse files
committed
Replay diagnosis methods and streamline the report action
- Each diagnosis row can be replayed individually, updating its result and the copied report. - The report controls collapse to a single Copy report button in the action row, dropping the empty bordered panel.
1 parent b6f2cc6 commit 3de1c69

4 files changed

Lines changed: 56 additions & 42 deletions

File tree

playground/src/app/globals.css

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,20 +1552,9 @@ button {
15521552
cursor: not-allowed;
15531553
}
15541554

1555-
.autotest__report {
1556-
margin-top: 28px;
1557-
border: 1px solid var(--rule);
1558-
border-radius: var(--radius-lg);
1559-
overflow: hidden;
1560-
}
1561-
.autotest__report-head {
1562-
display: flex;
1563-
align-items: center;
1564-
justify-content: space-between;
1565-
padding: 10px 14px;
1566-
border-bottom: 1px solid var(--rule);
1567-
}
15681555
.autotest__report-copy {
1556+
margin-left: auto;
1557+
align-self: center;
15691558
padding: 6px 14px;
15701559
font-family: var(--font-mono), monospace;
15711560
font-size: 11px;
@@ -1574,26 +1563,14 @@ button {
15741563
color: var(--ink-3);
15751564
background: transparent;
15761565
border: 1px solid var(--rule-strong);
1566+
border-radius: var(--radius);
15771567
cursor: pointer;
15781568
transition: background 120ms ease, color 120ms ease;
15791569
}
15801570
.autotest__report-copy:hover {
15811571
background: var(--bg-tint);
15821572
color: var(--ink);
15831573
}
1584-
.autotest__report-body {
1585-
margin: 0;
1586-
padding: 14px;
1587-
font-family: var(--font-mono), monospace;
1588-
font-size: 12px;
1589-
line-height: 1.55;
1590-
color: var(--console-ink);
1591-
background: var(--console-bg);
1592-
white-space: pre-wrap;
1593-
word-break: break-word;
1594-
max-height: 360px;
1595-
overflow-y: auto;
1596-
}
15971574

15981575
.diag__callout {
15991576
margin: 12px 0 0;

playground/src/app/page.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
type TestEntry,
2121
DIAGNOSIS_ID,
2222
runDiagnosis,
23+
runSingleTest,
2324
} from "@/src/lib/auto-test";
2425
import packageJson from "../../package.json";
2526

@@ -268,6 +269,16 @@ export default function PlaygroundPage() {
268269
abortRef.current?.abort();
269270
}, []);
270271

272+
const handleRetryDiagnosis = useCallback(
273+
async (serviceName: string, methodName: string) => {
274+
if (isTestRunning) return;
275+
await runSingleTest(services, serviceName, methodName, (id, entry) => {
276+
setTestResults((prev) => ({ ...prev, [id]: entry }));
277+
});
278+
},
279+
[isTestRunning],
280+
);
281+
271282
const hasView = selection !== null;
272283
const isDiagnosis = selection?.service === DIAGNOSIS_ID;
273284

@@ -295,6 +306,7 @@ export default function PlaygroundPage() {
295306
isRunning={isTestRunning}
296307
onRun={handleRunDiagnosis}
297308
onStop={handleStopTests}
309+
onRetry={handleRetryDiagnosis}
298310
onBack={handleBack}
299311
/>
300312
) : selection ? (

playground/src/components/DiagnosisView.tsx

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ const STATUS_LABEL: Record<TestStatus, string> = {
1313

1414
interface Row {
1515
id: string;
16+
service: string;
17+
method: string;
1618
status: TestStatus;
1719
output?: string;
1820
}
@@ -23,13 +25,15 @@ export function DiagnosisView({
2325
isRunning,
2426
onRun,
2527
onStop,
28+
onRetry,
2629
onBack,
2730
}: {
2831
services: ServiceInfo[];
2932
testResults: Record<string, TestEntry>;
3033
isRunning: boolean;
3134
onRun: () => void;
3235
onStop: () => void;
36+
onRetry: (service: string, method: string) => void;
3337
onBack: () => void;
3438
}) {
3539
const [copied, setCopied] = useState(false);
@@ -43,6 +47,8 @@ export function DiagnosisView({
4347
const entry = testResults[id];
4448
out.push({
4549
id,
50+
service: svc.name,
51+
method: m.name,
4652
status: entry?.status ?? "idle",
4753
output: entry?.output,
4854
});
@@ -129,24 +135,17 @@ export function DiagnosisView({
129135
{passCount} success · {failCount} failed
130136
</span>
131137
)}
138+
{hasResults && !isRunning && (
139+
<button
140+
type="button"
141+
className="autotest__report-copy"
142+
onClick={handleCopyReport}
143+
>
144+
{copied ? "Copied ✓" : "Copy report"}
145+
</button>
146+
)}
132147
</div>
133148

134-
{hasResults && !isRunning && (
135-
<div className="autotest__report">
136-
<div className="autotest__report-head">
137-
<span className="panel__label">Report</span>
138-
<button
139-
type="button"
140-
className="autotest__report-copy"
141-
onClick={handleCopyReport}
142-
>
143-
{copied ? "Copied ✓" : "Copy report"}
144-
</button>
145-
</div>
146-
<pre className="autotest__report-body">{reportMarkdown}</pre>
147-
</div>
148-
)}
149-
150149
{hasResults && (
151150
<div className="diag__log">
152151
{rows.map((r) => {
@@ -181,6 +180,19 @@ export function DiagnosisView({
181180
{r.status === "fail" ? "Error" : "Response"}
182181
</div>
183182
<pre className="autotest__detail-body">{r.output}</pre>
183+
<button
184+
type="button"
185+
className="autotest__retry"
186+
disabled={isRunning}
187+
title={
188+
isRunning
189+
? "Wait for the diagnosis run to finish before replaying"
190+
: "Re-run this method"
191+
}
192+
onClick={() => onRetry(r.service, r.method)}
193+
>
194+
▶ Replay
195+
</button>
184196
</div>
185197
)}
186198
</div>

playground/src/lib/auto-test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,19 @@ async function runSubscription(
194194
});
195195
}
196196

197+
// Re-run a single method, e.g. to replay a failed diagnosis row.
198+
export async function runSingleTest(
199+
services: ServiceInfo[],
200+
serviceName: string,
201+
methodName: string,
202+
onUpdate: (id: string, entry: TestEntry) => void,
203+
): Promise<void> {
204+
const svc = services.find((s: ServiceInfo) => s.name === serviceName);
205+
const method = svc?.methods.find((m: MethodInfo) => m.name === methodName);
206+
if (!svc || !method) return;
207+
await runOne({ serviceName, method, onUpdate, excludeSet: new Set() });
208+
}
209+
197210
async function runAutoTests(
198211
services: ServiceInfo[],
199212
onUpdate: (id: string, entry: TestEntry) => void,

0 commit comments

Comments
 (0)