@flanksource/clicky-ui 0.3.47 → 0.3.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -0
- package/dist/comments/CommentSidePanel.cjs +10 -4
- package/dist/comments/CommentSidePanel.cjs.map +1 -1
- package/dist/comments/CommentSidePanel.d.ts +2 -0
- package/dist/comments/CommentSidePanel.d.ts.map +1 -1
- package/dist/comments/CommentSidePanel.js +10 -4
- package/dist/comments/CommentSidePanel.js.map +1 -1
- package/dist/comments/CommentThread.cjs +2 -0
- package/dist/comments/CommentThread.cjs.map +1 -1
- package/dist/comments/CommentThread.d.ts +2 -1
- package/dist/comments/CommentThread.d.ts.map +1 -1
- package/dist/comments/CommentThread.js +2 -0
- package/dist/comments/CommentThread.js.map +1 -1
- package/dist/comments/CommentThreadList.cjs +3 -0
- package/dist/comments/CommentThreadList.cjs.map +1 -1
- package/dist/comments/CommentThreadList.d.ts +3 -1
- package/dist/comments/CommentThreadList.d.ts.map +1 -1
- package/dist/comments/CommentThreadList.js +3 -0
- package/dist/comments/CommentThreadList.js.map +1 -1
- package/dist/data/CodeLine.cjs +4 -2
- package/dist/data/CodeLine.cjs.map +1 -1
- package/dist/data/CodeLine.d.ts.map +1 -1
- package/dist/data/CodeLine.js +4 -2
- package/dist/data/CodeLine.js.map +1 -1
- package/dist/data/DataTable.cjs +18 -8
- package/dist/data/DataTable.cjs.map +1 -1
- package/dist/data/DataTable.d.ts +4 -0
- package/dist/data/DataTable.d.ts.map +1 -1
- package/dist/data/DataTable.js +18 -8
- package/dist/data/DataTable.js.map +1 -1
- package/dist/data/SymbolBadge.cjs +61 -0
- package/dist/data/SymbolBadge.cjs.map +1 -0
- package/dist/data/SymbolBadge.d.ts +21 -0
- package/dist/data/SymbolBadge.d.ts.map +1 -0
- package/dist/data/SymbolBadge.js +61 -0
- package/dist/data/SymbolBadge.js.map +1 -0
- package/dist/data/TaskManager.cjs +183 -159
- package/dist/data/TaskManager.cjs.map +1 -1
- package/dist/data/TaskManager.d.ts +3 -1
- package/dist/data/TaskManager.d.ts.map +1 -1
- package/dist/data/TaskManager.js +185 -161
- package/dist/data/TaskManager.js.map +1 -1
- package/dist/data/TaskManagerButton.cjs +1 -0
- package/dist/data/TaskManagerButton.cjs.map +1 -1
- package/dist/data/TaskManagerButton.js +1 -0
- package/dist/data/TaskManagerButton.js.map +1 -1
- package/dist/data/TaskProgress.cjs +13 -7
- package/dist/data/TaskProgress.cjs.map +1 -1
- package/dist/data/TaskProgress.d.ts +3 -1
- package/dist/data/TaskProgress.d.ts.map +1 -1
- package/dist/data/TaskProgress.js +13 -7
- package/dist/data/TaskProgress.js.map +1 -1
- package/dist/data/test-runner/TestDetailPanel.cjs +26 -12
- package/dist/data/test-runner/TestDetailPanel.cjs.map +1 -1
- package/dist/data/test-runner/TestDetailPanel.d.ts.map +1 -1
- package/dist/data/test-runner/TestDetailPanel.js +27 -13
- package/dist/data/test-runner/TestDetailPanel.js.map +1 -1
- package/dist/data/test-runner/TestRunner.cjs +6 -0
- package/dist/data/test-runner/TestRunner.cjs.map +1 -1
- package/dist/data/test-runner/TestRunner.d.ts +3 -1
- package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunner.js +6 -0
- package/dist/data/test-runner/TestRunner.js.map +1 -1
- package/dist/data/test-runner/TestTreeNode.cjs +2 -1
- package/dist/data/test-runner/TestTreeNode.cjs.map +1 -1
- package/dist/data/test-runner/TestTreeNode.d.ts.map +1 -1
- package/dist/data/test-runner/TestTreeNode.js +2 -1
- package/dist/data/test-runner/TestTreeNode.js.map +1 -1
- package/dist/data/test-runner/adapter.cjs +4 -0
- package/dist/data/test-runner/adapter.cjs.map +1 -1
- package/dist/data/test-runner/adapter.d.ts +9 -0
- package/dist/data/test-runner/adapter.d.ts.map +1 -1
- package/dist/data/test-runner/adapter.js +4 -0
- package/dist/data/test-runner/adapter.js.map +1 -1
- package/dist/data/test-runner/context.cjs.map +1 -1
- package/dist/data/test-runner/context.d.ts +2 -0
- package/dist/data/test-runner/context.d.ts.map +1 -1
- package/dist/data/test-runner/context.js.map +1 -1
- package/dist/data/test-runner/index.d.ts +2 -2
- package/dist/data/test-runner/index.d.ts.map +1 -1
- package/dist/data/test-runner/marks.cjs +42 -1
- package/dist/data/test-runner/marks.cjs.map +1 -1
- package/dist/data/test-runner/marks.d.ts +10 -0
- package/dist/data/test-runner/marks.d.ts.map +1 -1
- package/dist/data/test-runner/marks.js +42 -1
- package/dist/data/test-runner/marks.js.map +1 -1
- package/dist/data/traces/ProcessTraceTree.cjs +93 -0
- package/dist/data/traces/ProcessTraceTree.cjs.map +1 -0
- package/dist/data/traces/ProcessTraceTree.d.ts +24 -0
- package/dist/data/traces/ProcessTraceTree.d.ts.map +1 -0
- package/dist/data/traces/ProcessTraceTree.js +93 -0
- package/dist/data/traces/ProcessTraceTree.js.map +1 -0
- package/dist/data/traces/Sparkline.cjs +23 -0
- package/dist/data/traces/Sparkline.cjs.map +1 -0
- package/dist/data/traces/Sparkline.d.ts +13 -0
- package/dist/data/traces/Sparkline.d.ts.map +1 -0
- package/dist/data/traces/Sparkline.js +23 -0
- package/dist/data/traces/Sparkline.js.map +1 -0
- package/dist/data/traces/SqlTraceTable.cjs +104 -0
- package/dist/data/traces/SqlTraceTable.cjs.map +1 -0
- package/dist/data/traces/SqlTraceTable.d.ts +19 -0
- package/dist/data/traces/SqlTraceTable.d.ts.map +1 -0
- package/dist/data/traces/SqlTraceTable.js +104 -0
- package/dist/data/traces/SqlTraceTable.js.map +1 -0
- package/dist/data/traces/TerminalCastPlayer.cjs +162 -0
- package/dist/data/traces/TerminalCastPlayer.cjs.map +1 -0
- package/dist/data/traces/TerminalCastPlayer.d.ts +21 -0
- package/dist/data/traces/TerminalCastPlayer.d.ts.map +1 -0
- package/dist/data/traces/TerminalCastPlayer.js +162 -0
- package/dist/data/traces/TerminalCastPlayer.js.map +1 -0
- package/dist/data/traces/TraceHarView.cjs +15 -0
- package/dist/data/traces/TraceHarView.cjs.map +1 -0
- package/dist/data/traces/TraceHarView.d.ts +13 -0
- package/dist/data/traces/TraceHarView.d.ts.map +1 -0
- package/dist/data/traces/TraceHarView.js +15 -0
- package/dist/data/traces/TraceHarView.js.map +1 -0
- package/dist/data/traces/TraceView.cjs +54 -0
- package/dist/data/traces/TraceView.cjs.map +1 -0
- package/dist/data/traces/TraceView.d.ts +18 -0
- package/dist/data/traces/TraceView.d.ts.map +1 -0
- package/dist/data/traces/TraceView.js +54 -0
- package/dist/data/traces/TraceView.js.map +1 -0
- package/dist/data/traces/cast.cjs +81 -0
- package/dist/data/traces/cast.cjs.map +1 -0
- package/dist/data/traces/cast.d.ts +9 -0
- package/dist/data/traces/cast.d.ts.map +1 -0
- package/dist/data/traces/cast.js +81 -0
- package/dist/data/traces/cast.js.map +1 -0
- package/dist/data/traces/fixtures.d.ts +8 -0
- package/dist/data/traces/fixtures.d.ts.map +1 -0
- package/dist/data/traces/har-adapter.cjs +83 -0
- package/dist/data/traces/har-adapter.cjs.map +1 -0
- package/dist/data/traces/har-adapter.d.ts +13 -0
- package/dist/data/traces/har-adapter.d.ts.map +1 -0
- package/dist/data/traces/har-adapter.js +83 -0
- package/dist/data/traces/har-adapter.js.map +1 -0
- package/dist/data/traces/index.d.ts +12 -0
- package/dist/data/traces/index.d.ts.map +1 -0
- package/dist/data/traces/process-tree.cjs +53 -0
- package/dist/data/traces/process-tree.cjs.map +1 -0
- package/dist/data/traces/process-tree.d.ts +21 -0
- package/dist/data/traces/process-tree.d.ts.map +1 -0
- package/dist/data/traces/process-tree.js +53 -0
- package/dist/data/traces/process-tree.js.map +1 -0
- package/dist/data/traces/sql-trace.cjs +39 -0
- package/dist/data/traces/sql-trace.cjs.map +1 -0
- package/dist/data/traces/sql-trace.d.ts +31 -0
- package/dist/data/traces/sql-trace.d.ts.map +1 -0
- package/dist/data/traces/sql-trace.js +39 -0
- package/dist/data/traces/sql-trace.js.map +1 -0
- package/dist/data/traces/terminal-screen.cjs +270 -0
- package/dist/data/traces/terminal-screen.cjs.map +1 -0
- package/dist/data/traces/terminal-screen.d.ts +45 -0
- package/dist/data/traces/terminal-screen.d.ts.map +1 -0
- package/dist/data/traces/terminal-screen.js +270 -0
- package/dist/data/traces/terminal-screen.js.map +1 -0
- package/dist/data/traces/terminal-timeline.cjs +48 -0
- package/dist/data/traces/terminal-timeline.cjs.map +1 -0
- package/dist/data/traces/terminal-timeline.d.ts +26 -0
- package/dist/data/traces/terminal-timeline.d.ts.map +1 -0
- package/dist/data/traces/terminal-timeline.js +48 -0
- package/dist/data/traces/terminal-timeline.js.map +1 -0
- package/dist/data/traces/types.d.ts +139 -0
- package/dist/data/traces/types.d.ts.map +1 -0
- package/dist/data/verification/VerificationResults.cjs +4 -0
- package/dist/data/verification/VerificationResults.cjs.map +1 -1
- package/dist/data/verification/VerificationResults.d.ts +3 -1
- package/dist/data/verification/VerificationResults.d.ts.map +1 -1
- package/dist/data/verification/VerificationResults.js +4 -0
- package/dist/data/verification/VerificationResults.js.map +1 -1
- package/dist/data/verification/adapterViews.cjs +12 -3
- package/dist/data/verification/adapterViews.cjs.map +1 -1
- package/dist/data/verification/adapterViews.d.ts +4 -1
- package/dist/data/verification/adapterViews.d.ts.map +1 -1
- package/dist/data/verification/adapterViews.js +12 -3
- package/dist/data/verification/adapterViews.js.map +1 -1
- package/dist/data/verification/adapters.cjs +53 -10
- package/dist/data/verification/adapters.cjs.map +1 -1
- package/dist/data/verification/adapters.d.ts +7 -1
- package/dist/data/verification/adapters.d.ts.map +1 -1
- package/dist/data/verification/adapters.js +53 -10
- package/dist/data/verification/adapters.js.map +1 -1
- package/dist/data/verification/index.d.ts +4 -2
- package/dist/data/verification/index.d.ts.map +1 -1
- package/dist/data/verification/stepKind.cjs +217 -0
- package/dist/data/verification/stepKind.cjs.map +1 -0
- package/dist/data/verification/stepKind.d.ts +87 -0
- package/dist/data/verification/stepKind.d.ts.map +1 -0
- package/dist/data/verification/stepKind.js +217 -0
- package/dist/data/verification/stepKind.js.map +1 -0
- package/dist/data/verification/stepKindViews.cjs +111 -0
- package/dist/data/verification/stepKindViews.cjs.map +1 -0
- package/dist/data/verification/stepKindViews.d.ts +18 -0
- package/dist/data/verification/stepKindViews.d.ts.map +1 -0
- package/dist/data/verification/stepKindViews.js +111 -0
- package/dist/data/verification/stepKindViews.js.map +1 -0
- package/dist/data/verification/verifyReportTests.cjs +1 -0
- package/dist/data/verification/verifyReportTests.cjs.map +1 -1
- package/dist/data/verification/verifyReportTests.d.ts +2 -1
- package/dist/data/verification/verifyReportTests.d.ts.map +1 -1
- package/dist/data/verification/verifyReportTests.js +1 -0
- package/dist/data/verification/verifyReportTests.js.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.cjs.map +1 -1
- package/dist/data/version-info.js +3 -3
- package/dist/data/version-info.js.map +1 -1
- package/dist/data.cjs +36 -0
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +2 -0
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +38 -2
- package/dist/data.js.map +1 -1
- package/dist/index.cjs +38 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +40 -2
- package/dist/index.js.map +1 -1
- package/dist/rpc/FilterForm.cjs +9 -0
- package/dist/rpc/FilterForm.cjs.map +1 -1
- package/dist/rpc/FilterForm.d.ts +5 -1
- package/dist/rpc/FilterForm.d.ts.map +1 -1
- package/dist/rpc/FilterForm.js +9 -0
- package/dist/rpc/FilterForm.js.map +1 -1
- package/dist/rpc/OperationArgsForm.cjs +153 -0
- package/dist/rpc/OperationArgsForm.cjs.map +1 -0
- package/dist/rpc/OperationArgsForm.d.ts +16 -0
- package/dist/rpc/OperationArgsForm.d.ts.map +1 -0
- package/dist/rpc/OperationArgsForm.js +153 -0
- package/dist/rpc/OperationArgsForm.js.map +1 -0
- package/dist/rpc/OperationScheduleDialog.cjs +61 -17
- package/dist/rpc/OperationScheduleDialog.cjs.map +1 -1
- package/dist/rpc/OperationScheduleDialog.d.ts +3 -0
- package/dist/rpc/OperationScheduleDialog.d.ts.map +1 -1
- package/dist/rpc/OperationScheduleDialog.js +62 -18
- package/dist/rpc/OperationScheduleDialog.js.map +1 -1
- package/dist/rpc/OperationSchedules.cjs +6 -1
- package/dist/rpc/OperationSchedules.cjs.map +1 -1
- package/dist/rpc/OperationSchedules.d.ts.map +1 -1
- package/dist/rpc/OperationSchedules.js +6 -1
- package/dist/rpc/OperationSchedules.js.map +1 -1
- package/dist/rpc/operation-schedule-model.cjs +0 -7
- package/dist/rpc/operation-schedule-model.cjs.map +1 -1
- package/dist/rpc/operation-schedule-model.d.ts +0 -2
- package/dist/rpc/operation-schedule-model.d.ts.map +1 -1
- package/dist/rpc/operation-schedule-model.js +0 -7
- package/dist/rpc/operation-schedule-model.js.map +1 -1
- package/dist/rpc/operation-schedule-types.d.ts +6 -1
- package/dist/rpc/operation-schedule-types.d.ts.map +1 -1
- package/dist/rpc.cjs +2 -0
- package/dist/rpc.cjs.map +1 -1
- package/dist/rpc.d.ts +1 -0
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +2 -0
- package/dist/rpc.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const terminalScreen = require("./terminal-screen.cjs");
|
|
4
|
+
const KINDS = ["o", "r", "snapshot", "exit"];
|
|
5
|
+
const DEFAULT_SIZE = { width: 80, height: 24 };
|
|
6
|
+
function buildTimeline(events) {
|
|
7
|
+
var _a;
|
|
8
|
+
events.forEach((event, index) => {
|
|
9
|
+
if (!KINDS.includes(event.kind)) throw new Error(`terminal event ${index} has unknown kind "${event.kind}"`);
|
|
10
|
+
});
|
|
11
|
+
const ordered = events.map((event, index) => ({ event, index })).sort((a, b) => a.event.offset - b.event.offset || a.index - b.index).map(({ event }) => event);
|
|
12
|
+
const first = ordered[0];
|
|
13
|
+
if (first && !(first.width > 0 && first.height > 0)) {
|
|
14
|
+
throw new Error(`terminal events carry no terminal size (first row is ${first.width}x${first.height})`);
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
steps: ordered.filter((event) => event.kind === "o" || event.kind === "r"),
|
|
18
|
+
settled: (_a = ordered.findLast((event) => event.kind === "snapshot")) == null ? void 0 : _a.data,
|
|
19
|
+
exit: ordered.findLast((event) => event.kind === "exit"),
|
|
20
|
+
duration: ordered.reduce((latest, event) => Math.max(latest, event.offset), 0),
|
|
21
|
+
width: (first == null ? void 0 : first.width) ?? DEFAULT_SIZE.width,
|
|
22
|
+
height: (first == null ? void 0 : first.height) ?? DEFAULT_SIZE.height
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function stepCountAt(steps, position) {
|
|
26
|
+
let low = 0;
|
|
27
|
+
let high = steps.length;
|
|
28
|
+
while (low < high) {
|
|
29
|
+
const mid = low + high >>> 1;
|
|
30
|
+
if (steps[mid].offset <= position) low = mid + 1;
|
|
31
|
+
else high = mid;
|
|
32
|
+
}
|
|
33
|
+
return low;
|
|
34
|
+
}
|
|
35
|
+
function replayTo(replay, timeline, count) {
|
|
36
|
+
const reuse = replay !== void 0 && replay.applied <= count;
|
|
37
|
+
const screen = reuse ? replay.screen : terminalScreen.createScreen(timeline.width, timeline.height);
|
|
38
|
+
for (let i = reuse ? replay.applied : 0; i < count; i++) {
|
|
39
|
+
const step = timeline.steps[i];
|
|
40
|
+
if (step.kind === "r") terminalScreen.resizeScreen(screen, step.width, step.height);
|
|
41
|
+
else terminalScreen.writeScreen(screen, step.data);
|
|
42
|
+
}
|
|
43
|
+
return reuse && replay.applied === count ? replay : { screen, applied: count };
|
|
44
|
+
}
|
|
45
|
+
exports.buildTimeline = buildTimeline;
|
|
46
|
+
exports.replayTo = replayTo;
|
|
47
|
+
exports.stepCountAt = stepCountAt;
|
|
48
|
+
//# sourceMappingURL=terminal-timeline.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-timeline.cjs","sources":["../../../src/data/traces/terminal-timeline.ts"],"sourcesContent":["import { createScreen, resizeScreen, writeScreen, type TerminalScreen } from \"./terminal-screen\";\nimport type { TerminalEvent, TerminalEventKind } from \"./types\";\n\nconst KINDS: readonly TerminalEventKind[] = [\"o\", \"r\", \"snapshot\", \"exit\"];\nconst DEFAULT_SIZE = { width: 80, height: 24 };\n\nexport type TerminalTimeline = {\n /** Output and resize events in playback order. */\n steps: TerminalEvent[];\n /** The screen of the last snapshot, when the capture settled one. */\n settled: string | undefined;\n exit: TerminalEvent | undefined;\n /** Seconds from the first byte to the last event. */\n duration: number;\n /** The terminal size at the start of the session. */\n width: number;\n height: number;\n};\n\n/** Orders a session's rows and splits them into what playback, the settled screen and the badge need. */\nexport function buildTimeline(events: TerminalEvent[]): TerminalTimeline {\n events.forEach((event, index) => {\n if (!KINDS.includes(event.kind)) throw new Error(`terminal event ${index} has unknown kind \"${event.kind}\"`);\n });\n const ordered = events\n .map((event, index) => ({ event, index }))\n .sort((a, b) => a.event.offset - b.event.offset || a.index - b.index)\n .map(({ event }) => event);\n\n const first = ordered[0];\n if (first && !(first.width > 0 && first.height > 0)) {\n throw new Error(`terminal events carry no terminal size (first row is ${first.width}x${first.height})`);\n }\n return {\n steps: ordered.filter((event) => event.kind === \"o\" || event.kind === \"r\"),\n settled: ordered.findLast((event) => event.kind === \"snapshot\")?.data,\n exit: ordered.findLast((event) => event.kind === \"exit\"),\n duration: ordered.reduce((latest, event) => Math.max(latest, event.offset), 0),\n width: first?.width ?? DEFAULT_SIZE.width,\n height: first?.height ?? DEFAULT_SIZE.height,\n };\n}\n\n/** How many steps have happened by `position` seconds (steps are sorted by offset). */\nexport function stepCountAt(steps: TerminalEvent[], position: number): number {\n let low = 0;\n let high = steps.length;\n while (low < high) {\n const mid = (low + high) >>> 1;\n if (steps[mid]!.offset <= position) low = mid + 1;\n else high = mid;\n }\n return low;\n}\n\n/** A screen and how many steps of its timeline it has applied, so playback only feeds the new ones. */\nexport type ScreenReplay = { screen: TerminalScreen; applied: number };\n\n/** Brings the replay to exactly `count` applied steps, continuing when moving forward and rebuilding when moving back. */\nexport function replayTo(replay: ScreenReplay | undefined, timeline: TerminalTimeline, count: number): ScreenReplay {\n const reuse = replay !== undefined && replay.applied <= count;\n const screen = reuse ? replay.screen : createScreen(timeline.width, timeline.height);\n for (let i = reuse ? replay.applied : 0; i < count; i++) {\n const step = timeline.steps[i]!;\n if (step.kind === \"r\") resizeScreen(screen, step.width, step.height);\n else writeScreen(screen, step.data);\n }\n return reuse && replay.applied === count ? replay : { screen, applied: count };\n}\n"],"names":["createScreen","resizeScreen","writeScreen"],"mappings":";;;AAGA,MAAM,QAAsC,CAAC,KAAK,KAAK,YAAY,MAAM;AACzE,MAAM,eAAe,EAAE,OAAO,IAAI,QAAQ,GAAA;AAgBnC,SAAS,cAAc,QAA2C;;AACvE,SAAO,QAAQ,CAAC,OAAO,UAAU;AAC/B,QAAI,CAAC,MAAM,SAAS,MAAM,IAAI,EAAG,OAAM,IAAI,MAAM,kBAAkB,KAAK,sBAAsB,MAAM,IAAI,GAAG;AAAA,EAC7G,CAAC;AACD,QAAM,UAAU,OACb,IAAI,CAAC,OAAO,WAAW,EAAE,OAAO,MAAA,EAAQ,EACxC,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,SAAS,EAAE,MAAM,UAAU,EAAE,QAAQ,EAAE,KAAK,EACnE,IAAI,CAAC,EAAE,MAAA,MAAY,KAAK;AAE3B,QAAM,QAAQ,QAAQ,CAAC;AACvB,MAAI,SAAS,EAAE,MAAM,QAAQ,KAAK,MAAM,SAAS,IAAI;AACnD,UAAM,IAAI,MAAM,wDAAwD,MAAM,KAAK,IAAI,MAAM,MAAM,GAAG;AAAA,EACxG;AACA,SAAO;AAAA,IACL,OAAO,QAAQ,OAAO,CAAC,UAAU,MAAM,SAAS,OAAO,MAAM,SAAS,GAAG;AAAA,IACzE,UAAS,aAAQ,SAAS,CAAC,UAAU,MAAM,SAAS,UAAU,MAArD,mBAAwD;AAAA,IACjE,MAAM,QAAQ,SAAS,CAAC,UAAU,MAAM,SAAS,MAAM;AAAA,IACvD,UAAU,QAAQ,OAAO,CAAC,QAAQ,UAAU,KAAK,IAAI,QAAQ,MAAM,MAAM,GAAG,CAAC;AAAA,IAC7E,QAAO,+BAAO,UAAS,aAAa;AAAA,IACpC,SAAQ,+BAAO,WAAU,aAAa;AAAA,EAAA;AAE1C;AAGO,SAAS,YAAY,OAAwB,UAA0B;AAC5E,MAAI,MAAM;AACV,MAAI,OAAO,MAAM;AACjB,SAAO,MAAM,MAAM;AACjB,UAAM,MAAO,MAAM,SAAU;AAC7B,QAAI,MAAM,GAAG,EAAG,UAAU,gBAAgB,MAAM;AAAA,QAC3C,QAAO;AAAA,EACd;AACA,SAAO;AACT;AAMO,SAAS,SAAS,QAAkC,UAA4B,OAA6B;AAClH,QAAM,QAAQ,WAAW,UAAa,OAAO,WAAW;AACxD,QAAM,SAAS,QAAQ,OAAO,SAASA,eAAAA,aAAa,SAAS,OAAO,SAAS,MAAM;AACnF,WAAS,IAAI,QAAQ,OAAO,UAAU,GAAG,IAAI,OAAO,KAAK;AACvD,UAAM,OAAO,SAAS,MAAM,CAAC;AAC7B,QAAI,KAAK,SAAS,IAAKC,gBAAAA,aAAa,QAAQ,KAAK,OAAO,KAAK,MAAM;AAAA,QAC9DC,4BAAY,QAAQ,KAAK,IAAI;AAAA,EACpC;AACA,SAAO,SAAS,OAAO,YAAY,QAAQ,SAAS,EAAE,QAAQ,SAAS,MAAA;AACzE;;;;"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { TerminalScreen } from './terminal-screen.js';
|
|
2
|
+
import { TerminalEvent } from './types.js';
|
|
3
|
+
export type TerminalTimeline = {
|
|
4
|
+
/** Output and resize events in playback order. */
|
|
5
|
+
steps: TerminalEvent[];
|
|
6
|
+
/** The screen of the last snapshot, when the capture settled one. */
|
|
7
|
+
settled: string | undefined;
|
|
8
|
+
exit: TerminalEvent | undefined;
|
|
9
|
+
/** Seconds from the first byte to the last event. */
|
|
10
|
+
duration: number;
|
|
11
|
+
/** The terminal size at the start of the session. */
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
};
|
|
15
|
+
/** Orders a session's rows and splits them into what playback, the settled screen and the badge need. */
|
|
16
|
+
export declare function buildTimeline(events: TerminalEvent[]): TerminalTimeline;
|
|
17
|
+
/** How many steps have happened by `position` seconds (steps are sorted by offset). */
|
|
18
|
+
export declare function stepCountAt(steps: TerminalEvent[], position: number): number;
|
|
19
|
+
/** A screen and how many steps of its timeline it has applied, so playback only feeds the new ones. */
|
|
20
|
+
export type ScreenReplay = {
|
|
21
|
+
screen: TerminalScreen;
|
|
22
|
+
applied: number;
|
|
23
|
+
};
|
|
24
|
+
/** Brings the replay to exactly `count` applied steps, continuing when moving forward and rebuilding when moving back. */
|
|
25
|
+
export declare function replayTo(replay: ScreenReplay | undefined, timeline: TerminalTimeline, count: number): ScreenReplay;
|
|
26
|
+
//# sourceMappingURL=terminal-timeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-timeline.d.ts","sourceRoot":"","sources":["../../../src/data/traces/terminal-timeline.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACjG,OAAO,KAAK,EAAE,aAAa,EAAqB,MAAM,SAAS,CAAC;AAKhE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,kDAAkD;IAClD,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,qEAAqE;IACrE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,IAAI,EAAE,aAAa,GAAG,SAAS,CAAC;IAChC,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,yGAAyG;AACzG,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,gBAAgB,CAqBvE;AAED,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAS5E;AAED,uGAAuG;AACvG,MAAM,MAAM,YAAY,GAAG;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE,0HAA0H;AAC1H,wBAAgB,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,EAAE,QAAQ,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CASlH"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { createScreen, resizeScreen, writeScreen } from "./terminal-screen.js";
|
|
2
|
+
const KINDS = ["o", "r", "snapshot", "exit"];
|
|
3
|
+
const DEFAULT_SIZE = { width: 80, height: 24 };
|
|
4
|
+
function buildTimeline(events) {
|
|
5
|
+
var _a;
|
|
6
|
+
events.forEach((event, index) => {
|
|
7
|
+
if (!KINDS.includes(event.kind)) throw new Error(`terminal event ${index} has unknown kind "${event.kind}"`);
|
|
8
|
+
});
|
|
9
|
+
const ordered = events.map((event, index) => ({ event, index })).sort((a, b) => a.event.offset - b.event.offset || a.index - b.index).map(({ event }) => event);
|
|
10
|
+
const first = ordered[0];
|
|
11
|
+
if (first && !(first.width > 0 && first.height > 0)) {
|
|
12
|
+
throw new Error(`terminal events carry no terminal size (first row is ${first.width}x${first.height})`);
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
steps: ordered.filter((event) => event.kind === "o" || event.kind === "r"),
|
|
16
|
+
settled: (_a = ordered.findLast((event) => event.kind === "snapshot")) == null ? void 0 : _a.data,
|
|
17
|
+
exit: ordered.findLast((event) => event.kind === "exit"),
|
|
18
|
+
duration: ordered.reduce((latest, event) => Math.max(latest, event.offset), 0),
|
|
19
|
+
width: (first == null ? void 0 : first.width) ?? DEFAULT_SIZE.width,
|
|
20
|
+
height: (first == null ? void 0 : first.height) ?? DEFAULT_SIZE.height
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function stepCountAt(steps, position) {
|
|
24
|
+
let low = 0;
|
|
25
|
+
let high = steps.length;
|
|
26
|
+
while (low < high) {
|
|
27
|
+
const mid = low + high >>> 1;
|
|
28
|
+
if (steps[mid].offset <= position) low = mid + 1;
|
|
29
|
+
else high = mid;
|
|
30
|
+
}
|
|
31
|
+
return low;
|
|
32
|
+
}
|
|
33
|
+
function replayTo(replay, timeline, count) {
|
|
34
|
+
const reuse = replay !== void 0 && replay.applied <= count;
|
|
35
|
+
const screen = reuse ? replay.screen : createScreen(timeline.width, timeline.height);
|
|
36
|
+
for (let i = reuse ? replay.applied : 0; i < count; i++) {
|
|
37
|
+
const step = timeline.steps[i];
|
|
38
|
+
if (step.kind === "r") resizeScreen(screen, step.width, step.height);
|
|
39
|
+
else writeScreen(screen, step.data);
|
|
40
|
+
}
|
|
41
|
+
return reuse && replay.applied === count ? replay : { screen, applied: count };
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
buildTimeline,
|
|
45
|
+
replayTo,
|
|
46
|
+
stepCountAt
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=terminal-timeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-timeline.js","sources":["../../../src/data/traces/terminal-timeline.ts"],"sourcesContent":["import { createScreen, resizeScreen, writeScreen, type TerminalScreen } from \"./terminal-screen\";\nimport type { TerminalEvent, TerminalEventKind } from \"./types\";\n\nconst KINDS: readonly TerminalEventKind[] = [\"o\", \"r\", \"snapshot\", \"exit\"];\nconst DEFAULT_SIZE = { width: 80, height: 24 };\n\nexport type TerminalTimeline = {\n /** Output and resize events in playback order. */\n steps: TerminalEvent[];\n /** The screen of the last snapshot, when the capture settled one. */\n settled: string | undefined;\n exit: TerminalEvent | undefined;\n /** Seconds from the first byte to the last event. */\n duration: number;\n /** The terminal size at the start of the session. */\n width: number;\n height: number;\n};\n\n/** Orders a session's rows and splits them into what playback, the settled screen and the badge need. */\nexport function buildTimeline(events: TerminalEvent[]): TerminalTimeline {\n events.forEach((event, index) => {\n if (!KINDS.includes(event.kind)) throw new Error(`terminal event ${index} has unknown kind \"${event.kind}\"`);\n });\n const ordered = events\n .map((event, index) => ({ event, index }))\n .sort((a, b) => a.event.offset - b.event.offset || a.index - b.index)\n .map(({ event }) => event);\n\n const first = ordered[0];\n if (first && !(first.width > 0 && first.height > 0)) {\n throw new Error(`terminal events carry no terminal size (first row is ${first.width}x${first.height})`);\n }\n return {\n steps: ordered.filter((event) => event.kind === \"o\" || event.kind === \"r\"),\n settled: ordered.findLast((event) => event.kind === \"snapshot\")?.data,\n exit: ordered.findLast((event) => event.kind === \"exit\"),\n duration: ordered.reduce((latest, event) => Math.max(latest, event.offset), 0),\n width: first?.width ?? DEFAULT_SIZE.width,\n height: first?.height ?? DEFAULT_SIZE.height,\n };\n}\n\n/** How many steps have happened by `position` seconds (steps are sorted by offset). */\nexport function stepCountAt(steps: TerminalEvent[], position: number): number {\n let low = 0;\n let high = steps.length;\n while (low < high) {\n const mid = (low + high) >>> 1;\n if (steps[mid]!.offset <= position) low = mid + 1;\n else high = mid;\n }\n return low;\n}\n\n/** A screen and how many steps of its timeline it has applied, so playback only feeds the new ones. */\nexport type ScreenReplay = { screen: TerminalScreen; applied: number };\n\n/** Brings the replay to exactly `count` applied steps, continuing when moving forward and rebuilding when moving back. */\nexport function replayTo(replay: ScreenReplay | undefined, timeline: TerminalTimeline, count: number): ScreenReplay {\n const reuse = replay !== undefined && replay.applied <= count;\n const screen = reuse ? replay.screen : createScreen(timeline.width, timeline.height);\n for (let i = reuse ? replay.applied : 0; i < count; i++) {\n const step = timeline.steps[i]!;\n if (step.kind === \"r\") resizeScreen(screen, step.width, step.height);\n else writeScreen(screen, step.data);\n }\n return reuse && replay.applied === count ? replay : { screen, applied: count };\n}\n"],"names":[],"mappings":";AAGA,MAAM,QAAsC,CAAC,KAAK,KAAK,YAAY,MAAM;AACzE,MAAM,eAAe,EAAE,OAAO,IAAI,QAAQ,GAAA;AAgBnC,SAAS,cAAc,QAA2C;;AACvE,SAAO,QAAQ,CAAC,OAAO,UAAU;AAC/B,QAAI,CAAC,MAAM,SAAS,MAAM,IAAI,EAAG,OAAM,IAAI,MAAM,kBAAkB,KAAK,sBAAsB,MAAM,IAAI,GAAG;AAAA,EAC7G,CAAC;AACD,QAAM,UAAU,OACb,IAAI,CAAC,OAAO,WAAW,EAAE,OAAO,MAAA,EAAQ,EACxC,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,SAAS,EAAE,MAAM,UAAU,EAAE,QAAQ,EAAE,KAAK,EACnE,IAAI,CAAC,EAAE,MAAA,MAAY,KAAK;AAE3B,QAAM,QAAQ,QAAQ,CAAC;AACvB,MAAI,SAAS,EAAE,MAAM,QAAQ,KAAK,MAAM,SAAS,IAAI;AACnD,UAAM,IAAI,MAAM,wDAAwD,MAAM,KAAK,IAAI,MAAM,MAAM,GAAG;AAAA,EACxG;AACA,SAAO;AAAA,IACL,OAAO,QAAQ,OAAO,CAAC,UAAU,MAAM,SAAS,OAAO,MAAM,SAAS,GAAG;AAAA,IACzE,UAAS,aAAQ,SAAS,CAAC,UAAU,MAAM,SAAS,UAAU,MAArD,mBAAwD;AAAA,IACjE,MAAM,QAAQ,SAAS,CAAC,UAAU,MAAM,SAAS,MAAM;AAAA,IACvD,UAAU,QAAQ,OAAO,CAAC,QAAQ,UAAU,KAAK,IAAI,QAAQ,MAAM,MAAM,GAAG,CAAC;AAAA,IAC7E,QAAO,+BAAO,UAAS,aAAa;AAAA,IACpC,SAAQ,+BAAO,WAAU,aAAa;AAAA,EAAA;AAE1C;AAGO,SAAS,YAAY,OAAwB,UAA0B;AAC5E,MAAI,MAAM;AACV,MAAI,OAAO,MAAM;AACjB,SAAO,MAAM,MAAM;AACjB,UAAM,MAAO,MAAM,SAAU;AAC7B,QAAI,MAAM,GAAG,EAAG,UAAU,gBAAgB,MAAM;AAAA,QAC3C,QAAO;AAAA,EACd;AACA,SAAO;AACT;AAMO,SAAS,SAAS,QAAkC,UAA4B,OAA6B;AAClH,QAAM,QAAQ,WAAW,UAAa,OAAO,WAAW;AACxD,QAAM,SAAS,QAAQ,OAAO,SAAS,aAAa,SAAS,OAAO,SAAS,MAAM;AACnF,WAAS,IAAI,QAAQ,OAAO,UAAU,GAAG,IAAI,OAAO,KAAK;AACvD,UAAM,OAAO,SAAS,MAAM,CAAC;AAC7B,QAAI,KAAK,SAAS,IAAK,cAAa,QAAQ,KAAK,OAAO,KAAK,MAAM;AAAA,QAC9D,aAAY,QAAQ,KAAK,IAAI;AAAA,EACpC;AACA,SAAO,SAAS,OAAO,YAAY,QAAQ,SAAS,EAAE,QAAQ,SAAS,MAAA;AACzE;"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { HARHeader } from '../har/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Row shapes of the commons-db trace kinds, as their record streams store them
|
|
4
|
+
* (camelCase JSON). Declared as `type` aliases so they satisfy DataTable's
|
|
5
|
+
* `Record<string, unknown>` row constraint.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* A request or response body as a trace stream stores it. The http kind parses
|
|
9
|
+
* JSON bodies (`WithJSONProcessor`) so they are masked and filtered as
|
|
10
|
+
* structure; a row read straight from the store therefore holds such a body as
|
|
11
|
+
* an object or array, and as text again only when read back through the Go API.
|
|
12
|
+
*/
|
|
13
|
+
export type TraceBodyText = string | Record<string, unknown> | unknown[];
|
|
14
|
+
export type HttpExchangeRequest = {
|
|
15
|
+
method: string;
|
|
16
|
+
url: string;
|
|
17
|
+
httpVersion?: string;
|
|
18
|
+
headers?: HARHeader[] | null;
|
|
19
|
+
queryString?: HARHeader[] | null;
|
|
20
|
+
postData?: {
|
|
21
|
+
mimeType?: string;
|
|
22
|
+
text?: TraceBodyText | null;
|
|
23
|
+
} | null;
|
|
24
|
+
headersSize?: number;
|
|
25
|
+
bodySize?: number;
|
|
26
|
+
};
|
|
27
|
+
export type HttpExchangeResponse = {
|
|
28
|
+
status: number;
|
|
29
|
+
statusText?: string;
|
|
30
|
+
httpVersion?: string;
|
|
31
|
+
headers?: HARHeader[] | null;
|
|
32
|
+
content?: {
|
|
33
|
+
size?: number;
|
|
34
|
+
mimeType?: string;
|
|
35
|
+
text?: TraceBodyText | null;
|
|
36
|
+
truncated?: boolean;
|
|
37
|
+
} | null;
|
|
38
|
+
redirectURL?: string;
|
|
39
|
+
headersSize?: number;
|
|
40
|
+
bodySize?: number;
|
|
41
|
+
};
|
|
42
|
+
/** One `http` / `http_proxy` record: an outbound request and its response. */
|
|
43
|
+
export type HttpExchangeRow = {
|
|
44
|
+
startedAt: string;
|
|
45
|
+
feature?: string;
|
|
46
|
+
method: string;
|
|
47
|
+
host: string;
|
|
48
|
+
url: string;
|
|
49
|
+
status: number;
|
|
50
|
+
durationMs: number;
|
|
51
|
+
request: HttpExchangeRequest;
|
|
52
|
+
response: HttpExchangeResponse;
|
|
53
|
+
error?: string;
|
|
54
|
+
/** Per-phase milliseconds; a phase the capture did not measure is -1. */
|
|
55
|
+
timings?: {
|
|
56
|
+
send?: number;
|
|
57
|
+
wait?: number;
|
|
58
|
+
receive?: number;
|
|
59
|
+
};
|
|
60
|
+
serverIPAddress?: string;
|
|
61
|
+
/** A CONNECT tunnel relayed without decrypting it: only the byte counts are known. */
|
|
62
|
+
tunnelled?: boolean;
|
|
63
|
+
bytesIn?: number;
|
|
64
|
+
bytesOut?: number;
|
|
65
|
+
/** `base64` when the response content is not UTF-8 text. */
|
|
66
|
+
encoding?: string;
|
|
67
|
+
comment?: string;
|
|
68
|
+
/** Paths of the values the capture cut, such as `response.content.text`. */
|
|
69
|
+
truncated?: string[];
|
|
70
|
+
};
|
|
71
|
+
/** One `pg_proxy` / `sql_statements` record. */
|
|
72
|
+
export type SqlStatementRow = {
|
|
73
|
+
startedAt: string;
|
|
74
|
+
connection: string;
|
|
75
|
+
driver: string;
|
|
76
|
+
op: string;
|
|
77
|
+
tables: string[];
|
|
78
|
+
sql: string;
|
|
79
|
+
/** Keys statements that differ only by their values. */
|
|
80
|
+
repeatKey: string;
|
|
81
|
+
args?: unknown[];
|
|
82
|
+
durationMs: number;
|
|
83
|
+
/** Rows returned, or -1 when the driver could not tell. */
|
|
84
|
+
rows: number;
|
|
85
|
+
error?: string;
|
|
86
|
+
truncated?: string[];
|
|
87
|
+
};
|
|
88
|
+
export type TerminalEventKind = "o" | "r" | "snapshot" | "exit";
|
|
89
|
+
/** One `terminal` record: output, a resize, the settled screen, or the end of the session. */
|
|
90
|
+
export type TerminalEvent = {
|
|
91
|
+
/** Wall-clock time of the event. Absent on events parsed from a downloaded cast. */
|
|
92
|
+
at?: string;
|
|
93
|
+
/** Seconds since the first byte, the clock a cast plays on. */
|
|
94
|
+
offset: number;
|
|
95
|
+
kind: TerminalEventKind;
|
|
96
|
+
/** The output of an `o` event, and the screen of a `snapshot`. */
|
|
97
|
+
data: string;
|
|
98
|
+
width: number;
|
|
99
|
+
height: number;
|
|
100
|
+
exitCode?: number;
|
|
101
|
+
/** On the `exit` row: output events were not recorded (size caps or a full buffer). */
|
|
102
|
+
truncated?: boolean;
|
|
103
|
+
/** On the `exit` row: the command line the terminal ran. */
|
|
104
|
+
command?: string;
|
|
105
|
+
};
|
|
106
|
+
/** One `process_tree` record: a process as last seen. */
|
|
107
|
+
export type ProcessNodeRow = {
|
|
108
|
+
key: string;
|
|
109
|
+
parentKey?: string;
|
|
110
|
+
pid: number;
|
|
111
|
+
ppid: number;
|
|
112
|
+
name: string;
|
|
113
|
+
command: string;
|
|
114
|
+
cwd?: string;
|
|
115
|
+
status: string;
|
|
116
|
+
isRoot?: boolean;
|
|
117
|
+
startedAt: string;
|
|
118
|
+
exitedAt?: string | null;
|
|
119
|
+
lastSeenAt: string;
|
|
120
|
+
cpuPercent: number;
|
|
121
|
+
rssBytes: number;
|
|
122
|
+
peakCpuPercent: number;
|
|
123
|
+
peakRssBytes: number;
|
|
124
|
+
stack?: string;
|
|
125
|
+
stackError?: string;
|
|
126
|
+
};
|
|
127
|
+
/** One `process_samples` record: a process's usage at one tick. */
|
|
128
|
+
export type ProcessSampleRow = {
|
|
129
|
+
sampledAt: string;
|
|
130
|
+
tick: number;
|
|
131
|
+
key: string;
|
|
132
|
+
pid: number;
|
|
133
|
+
cpuPercent: number;
|
|
134
|
+
memoryPercent: number;
|
|
135
|
+
rssBytes: number;
|
|
136
|
+
};
|
|
137
|
+
/** A record of a kind `TraceView` has no dedicated viewer for. */
|
|
138
|
+
export type TraceRow = Record<string, unknown>;
|
|
139
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/data/traces/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,6 +31,8 @@ function VerificationResults({
|
|
|
31
31
|
emptyText = "No verification has run yet",
|
|
32
32
|
selected: controlledSelected,
|
|
33
33
|
onSelect: controlledOnSelect,
|
|
34
|
+
activeAttempt,
|
|
35
|
+
onAttemptChange,
|
|
34
36
|
filters: controlledFilters,
|
|
35
37
|
onFiltersChange: controlledOnFiltersChange
|
|
36
38
|
}) {
|
|
@@ -89,6 +91,8 @@ function VerificationResults({
|
|
|
89
91
|
title,
|
|
90
92
|
adapters: adapters2,
|
|
91
93
|
onSelect: setSelected,
|
|
94
|
+
...activeAttempt !== void 0 ? { activeAttempt } : {},
|
|
95
|
+
...onAttemptChange ? { onAttemptChange } : {},
|
|
92
96
|
onFiltersChange: setFilters,
|
|
93
97
|
onExpandAllChange: setExpandAll
|
|
94
98
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VerificationResults.cjs","sources":["../../../src/data/verification/VerificationResults.tsx"],"sourcesContent":["// Props-only VerificationResults: renders a captain VerifyReport through the\n// shared TestRunner, so both the captain webapp and gavel pr/ui can drop it in\n// without forking a data-fetching or routing dependency. Ported from gavel's\n// VerificationFixtureResults.tsx.\n\nimport { useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport {\n emptyTestFilters,\n filterTests,\n TestRunner,\n type Test,\n type TestFilters,\n type TestNodeAdapterRegistry,\n} from \"../test-runner\";\nimport { verificationAdapters } from \"./adapters\";\nimport { verifyReportTests } from \"./verifyReportTests\";\nimport type { VerifyReport } from \"./verify-report\";\n\nexport type VerificationResultsProps = {\n report: VerifyReport | null;\n /** Overrides the run-complete state. Defaults to `report.state !== \"running\"`. */\n done?: boolean;\n /** Header title, passed through to TestRunner. Defaults to no title. */\n title?: ReactNode | null;\n className?: string;\n adapters?: TestNodeAdapterRegistry;\n emptyText?: string;\n /**\n * Controlled selection — omit to let the component own selection state\n * (keyed by a stable task_id/name so the same row stays selected across a\n * re-created report of the same shape, e.g. after a live-update refresh).\n * Pass both this and `onSelect` for a host that persists selection at the\n * route level.\n */\n selected?: Test | null;\n onSelect?: (node: Test | null) => void;\n /** Controlled status/framework filters — omit to let the component own filter state. */\n filters?: TestFilters;\n onFiltersChange?: (next: TestFilters) => void;\n};\n\nconst DEFAULT_ADAPTERS = verificationAdapters();\n\n/**\n * A node's identity across a re-created forest: its own `task_id` when\n * present, else its name. Object identity can't be used — `verifyReportTests`\n * builds a brand-new `Test[]` from every report, so the previously-selected\n * object never appears in a fresh forest even when the underlying node is\n * unchanged.\n */\nfunction selectionKey(node: Test): string {\n return node.task_id ?? node.name;\n}\n\nfunction findBySelectionKey(nodes: Test[], key: string): Test | null {\n for (const node of nodes) {\n if (selectionKey(node) === key) return node;\n if (node.children) {\n const found = findBySelectionKey(node.children, key);\n if (found) return found;\n }\n }\n return null;\n}\n\nexport function VerificationResults({\n report,\n done,\n title = null,\n className,\n adapters = DEFAULT_ADAPTERS,\n emptyText = \"No verification has run yet\",\n selected: controlledSelected,\n onSelect: controlledOnSelect,\n filters: controlledFilters,\n onFiltersChange: controlledOnFiltersChange,\n}: VerificationResultsProps) {\n const tests = useMemo(() => (report ? verifyReportTests(report) : []), [report]);\n\n const [selectedKey, setSelectedKey] = useState<string | null>(null);\n const [internalFilters, setInternalFilters] = useState<TestFilters>(() => emptyTestFilters());\n const [expandAll, setExpandAll] = useState<boolean | null>(null);\n\n const filtersControlled = controlledFilters !== undefined;\n const filters = filtersControlled ? controlledFilters : internalFilters;\n const setFilters = (next: TestFilters) => {\n if (filtersControlled) controlledOnFiltersChange?.(next);\n else setInternalFilters(next);\n };\n\n const selectionControlled = controlledSelected !== undefined;\n const uncontrolledSelected = useMemo(\n () => (selectedKey ? findBySelectionKey(tests, selectedKey) : null),\n [tests, selectedKey],\n );\n const selected = selectionControlled ? controlledSelected : uncontrolledSelected;\n const setSelected = (node: Test | null) => {\n if (selectionControlled) controlledOnSelect?.(node);\n else setSelectedKey(node ? selectionKey(node) : null);\n };\n\n const visible = useMemo(\n () => filterTests(tests, filters.status, filters.framework),\n [tests, filters],\n );\n\n const startTime = report?.started_at ? Date.parse(report.started_at) : undefined;\n const endTime = report?.finished_at ? Date.parse(report.finished_at) : undefined;\n\n // A cmd/AI verifier's reason and feedback are the only place its verdict\n // survives once its nodes are empty (e.g. an error before any check ran), so\n // they're shown above the runner whenever present — not only in that empty\n // case — since a partial pass can carry a reason alongside real test nodes.\n const verdict =\n report && (report.reason || report.feedback) ? (\n <div className=\"shrink-0 space-y-2 border-b border-border px-3 py-2\">\n {report.reason && <p className=\"text-xs text-foreground\">{report.reason}</p>}\n {report.feedback && (\n <pre className=\"max-h-40 overflow-auto whitespace-pre-wrap rounded bg-muted p-2 font-mono text-[11px]\">\n {report.feedback}\n </pre>\n )}\n </div>\n ) : null;\n\n if (!report || tests.length === 0) {\n return (\n <div className={cn(\"flex flex-col\", className)}>\n {verdict}\n {!verdict && <p className=\"px-3 py-4 text-xs text-muted-foreground\">{emptyText}</p>}\n </div>\n );\n }\n\n return (\n <div className={cn(\"flex h-[30rem] min-h-80 flex-col\", className)}>\n {verdict}\n <TestRunner\n className=\"min-h-0 flex-1\"\n tests={visible}\n allTests={tests}\n selected={selected}\n filters={filters}\n expandAll={expandAll}\n done={done ?? report.state !== \"running\"}\n status={{ running: report.state === \"running\" }}\n {...(report.state === \"running\" ? { statusText: \"Running verification…\" } : {})}\n {...(startTime !== undefined ? { startTime } : {})}\n {...(endTime !== undefined ? { endTime } : {})}\n title={title}\n adapters={adapters}\n onSelect={setSelected}\n onFiltersChange={setFilters}\n onExpandAllChange={setExpandAll}\n />\n </div>\n );\n}\n"],"names":["verificationAdapters","adapters","useMemo","verifyReportTests","useState","emptyTestFilters","filterTests","jsxs","jsx","cn","TestRunner"],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"VerificationResults.cjs","sources":["../../../src/data/verification/VerificationResults.tsx"],"sourcesContent":["// Props-only VerificationResults: renders a captain VerifyReport through the\n// shared TestRunner, so both the captain webapp and gavel pr/ui can drop it in\n// without forking a data-fetching or routing dependency. Ported from gavel's\n// VerificationFixtureResults.tsx.\n\nimport { useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport {\n emptyTestFilters,\n filterTests,\n TestRunner,\n type Test,\n type TestFilters,\n type TestNodeAdapterRegistry,\n} from \"../test-runner\";\nimport { verificationAdapters } from \"./adapters\";\nimport { verifyReportTests } from \"./verifyReportTests\";\nimport type { VerifyReport } from \"./verify-report\";\n\nexport type VerificationResultsProps = {\n report: VerifyReport | null;\n /** Overrides the run-complete state. Defaults to `report.state !== \"running\"`. */\n done?: boolean;\n /** Header title, passed through to TestRunner. Defaults to no title. */\n title?: ReactNode | null;\n className?: string;\n adapters?: TestNodeAdapterRegistry;\n emptyText?: string;\n /**\n * Controlled selection — omit to let the component own selection state\n * (keyed by a stable task_id/name so the same row stays selected across a\n * re-created report of the same shape, e.g. after a live-update refresh).\n * Pass both this and `onSelect` for a host that persists selection at the\n * route level.\n */\n selected?: Test | null;\n onSelect?: (node: Test | null) => void;\n activeAttempt?: number;\n onAttemptChange?: (attempt: number) => void;\n /** Controlled status/framework filters — omit to let the component own filter state. */\n filters?: TestFilters;\n onFiltersChange?: (next: TestFilters) => void;\n};\n\nconst DEFAULT_ADAPTERS = verificationAdapters();\n\n/**\n * A node's identity across a re-created forest: its own `task_id` when\n * present, else its name. Object identity can't be used — `verifyReportTests`\n * builds a brand-new `Test[]` from every report, so the previously-selected\n * object never appears in a fresh forest even when the underlying node is\n * unchanged.\n */\nfunction selectionKey(node: Test): string {\n return node.task_id ?? node.name;\n}\n\nfunction findBySelectionKey(nodes: Test[], key: string): Test | null {\n for (const node of nodes) {\n if (selectionKey(node) === key) return node;\n if (node.children) {\n const found = findBySelectionKey(node.children, key);\n if (found) return found;\n }\n }\n return null;\n}\n\nexport function VerificationResults({\n report,\n done,\n title = null,\n className,\n adapters = DEFAULT_ADAPTERS,\n emptyText = \"No verification has run yet\",\n selected: controlledSelected,\n onSelect: controlledOnSelect,\n activeAttempt,\n onAttemptChange,\n filters: controlledFilters,\n onFiltersChange: controlledOnFiltersChange,\n}: VerificationResultsProps) {\n const tests = useMemo(() => (report ? verifyReportTests(report) : []), [report]);\n\n const [selectedKey, setSelectedKey] = useState<string | null>(null);\n const [internalFilters, setInternalFilters] = useState<TestFilters>(() => emptyTestFilters());\n const [expandAll, setExpandAll] = useState<boolean | null>(null);\n\n const filtersControlled = controlledFilters !== undefined;\n const filters = filtersControlled ? controlledFilters : internalFilters;\n const setFilters = (next: TestFilters) => {\n if (filtersControlled) controlledOnFiltersChange?.(next);\n else setInternalFilters(next);\n };\n\n const selectionControlled = controlledSelected !== undefined;\n const uncontrolledSelected = useMemo(\n () => (selectedKey ? findBySelectionKey(tests, selectedKey) : null),\n [tests, selectedKey],\n );\n const selected = selectionControlled ? controlledSelected : uncontrolledSelected;\n const setSelected = (node: Test | null) => {\n if (selectionControlled) controlledOnSelect?.(node);\n else setSelectedKey(node ? selectionKey(node) : null);\n };\n\n const visible = useMemo(\n () => filterTests(tests, filters.status, filters.framework),\n [tests, filters],\n );\n\n const startTime = report?.started_at ? Date.parse(report.started_at) : undefined;\n const endTime = report?.finished_at ? Date.parse(report.finished_at) : undefined;\n\n // A cmd/AI verifier's reason and feedback are the only place its verdict\n // survives once its nodes are empty (e.g. an error before any check ran), so\n // they're shown above the runner whenever present — not only in that empty\n // case — since a partial pass can carry a reason alongside real test nodes.\n const verdict =\n report && (report.reason || report.feedback) ? (\n <div className=\"shrink-0 space-y-2 border-b border-border px-3 py-2\">\n {report.reason && <p className=\"text-xs text-foreground\">{report.reason}</p>}\n {report.feedback && (\n <pre className=\"max-h-40 overflow-auto whitespace-pre-wrap rounded bg-muted p-2 font-mono text-[11px]\">\n {report.feedback}\n </pre>\n )}\n </div>\n ) : null;\n\n if (!report || tests.length === 0) {\n return (\n <div className={cn(\"flex flex-col\", className)}>\n {verdict}\n {!verdict && <p className=\"px-3 py-4 text-xs text-muted-foreground\">{emptyText}</p>}\n </div>\n );\n }\n\n return (\n <div className={cn(\"flex h-[30rem] min-h-80 flex-col\", className)}>\n {verdict}\n <TestRunner\n className=\"min-h-0 flex-1\"\n tests={visible}\n allTests={tests}\n selected={selected}\n filters={filters}\n expandAll={expandAll}\n done={done ?? report.state !== \"running\"}\n status={{ running: report.state === \"running\" }}\n {...(report.state === \"running\" ? { statusText: \"Running verification…\" } : {})}\n {...(startTime !== undefined ? { startTime } : {})}\n {...(endTime !== undefined ? { endTime } : {})}\n title={title}\n adapters={adapters}\n onSelect={setSelected}\n {...(activeAttempt !== undefined ? { activeAttempt } : {})}\n {...(onAttemptChange ? { onAttemptChange } : {})}\n onFiltersChange={setFilters}\n onExpandAllChange={setExpandAll}\n />\n </div>\n );\n}\n"],"names":["verificationAdapters","adapters","useMemo","verifyReportTests","useState","emptyTestFilters","filterTests","jsxs","jsx","cn","TestRunner"],"mappings":"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"}
|
|
@@ -19,9 +19,11 @@ export type VerificationResultsProps = {
|
|
|
19
19
|
*/
|
|
20
20
|
selected?: Test | null;
|
|
21
21
|
onSelect?: (node: Test | null) => void;
|
|
22
|
+
activeAttempt?: number;
|
|
23
|
+
onAttemptChange?: (attempt: number) => void;
|
|
22
24
|
/** Controlled status/framework filters — omit to let the component own filter state. */
|
|
23
25
|
filters?: TestFilters;
|
|
24
26
|
onFiltersChange?: (next: TestFilters) => void;
|
|
25
27
|
};
|
|
26
|
-
export declare function VerificationResults({ report, done, title, className, adapters, emptyText, selected: controlledSelected, onSelect: controlledOnSelect, filters: controlledFilters, onFiltersChange: controlledOnFiltersChange, }: VerificationResultsProps): import("react").JSX.Element;
|
|
28
|
+
export declare function VerificationResults({ report, done, title, className, adapters, emptyText, selected: controlledSelected, onSelect: controlledOnSelect, activeAttempt, onAttemptChange, filters: controlledFilters, onFiltersChange: controlledOnFiltersChange, }: VerificationResultsProps): import("react").JSX.Element;
|
|
27
29
|
//# sourceMappingURL=VerificationResults.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VerificationResults.d.ts","sourceRoot":"","sources":["../../../src/data/verification/VerificationResults.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE1D,OAAO,EAIL,KAAK,IAAI,EACT,KAAK,WAAW,EAChB,KAAK,uBAAuB,EAC7B,MAAM,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,kFAAkF;IAClF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,wEAAwE;IACxE,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,uBAAuB,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;IACvC,wFAAwF;IACxF,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;CAC/C,CAAC;AA0BF,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,IAAI,EACJ,KAAY,EACZ,SAAS,EACT,QAA2B,EAC3B,SAAyC,EACzC,QAAQ,EAAE,kBAAkB,EAC5B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,iBAAiB,EAC1B,eAAe,EAAE,yBAAyB,GAC3C,EAAE,wBAAwB,+
|
|
1
|
+
{"version":3,"file":"VerificationResults.d.ts","sourceRoot":"","sources":["../../../src/data/verification/VerificationResults.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE1D,OAAO,EAIL,KAAK,IAAI,EACT,KAAK,WAAW,EAChB,KAAK,uBAAuB,EAC7B,MAAM,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,kFAAkF;IAClF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,wEAAwE;IACxE,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,uBAAuB,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,wFAAwF;IACxF,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;CAC/C,CAAC;AA0BF,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,IAAI,EACJ,KAAY,EACZ,SAAS,EACT,QAA2B,EAC3B,SAAyC,EACzC,QAAQ,EAAE,kBAAkB,EAC5B,QAAQ,EAAE,kBAAkB,EAC5B,aAAa,EACb,eAAe,EACf,OAAO,EAAE,iBAAiB,EAC1B,eAAe,EAAE,yBAAyB,GAC3C,EAAE,wBAAwB,+BAmF1B"}
|
|
@@ -29,6 +29,8 @@ function VerificationResults({
|
|
|
29
29
|
emptyText = "No verification has run yet",
|
|
30
30
|
selected: controlledSelected,
|
|
31
31
|
onSelect: controlledOnSelect,
|
|
32
|
+
activeAttempt,
|
|
33
|
+
onAttemptChange,
|
|
32
34
|
filters: controlledFilters,
|
|
33
35
|
onFiltersChange: controlledOnFiltersChange
|
|
34
36
|
}) {
|
|
@@ -87,6 +89,8 @@ function VerificationResults({
|
|
|
87
89
|
title,
|
|
88
90
|
adapters,
|
|
89
91
|
onSelect: setSelected,
|
|
92
|
+
...activeAttempt !== void 0 ? { activeAttempt } : {},
|
|
93
|
+
...onAttemptChange ? { onAttemptChange } : {},
|
|
90
94
|
onFiltersChange: setFilters,
|
|
91
95
|
onExpandAllChange: setExpandAll
|
|
92
96
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VerificationResults.js","sources":["../../../src/data/verification/VerificationResults.tsx"],"sourcesContent":["// Props-only VerificationResults: renders a captain VerifyReport through the\n// shared TestRunner, so both the captain webapp and gavel pr/ui can drop it in\n// without forking a data-fetching or routing dependency. Ported from gavel's\n// VerificationFixtureResults.tsx.\n\nimport { useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport {\n emptyTestFilters,\n filterTests,\n TestRunner,\n type Test,\n type TestFilters,\n type TestNodeAdapterRegistry,\n} from \"../test-runner\";\nimport { verificationAdapters } from \"./adapters\";\nimport { verifyReportTests } from \"./verifyReportTests\";\nimport type { VerifyReport } from \"./verify-report\";\n\nexport type VerificationResultsProps = {\n report: VerifyReport | null;\n /** Overrides the run-complete state. Defaults to `report.state !== \"running\"`. */\n done?: boolean;\n /** Header title, passed through to TestRunner. Defaults to no title. */\n title?: ReactNode | null;\n className?: string;\n adapters?: TestNodeAdapterRegistry;\n emptyText?: string;\n /**\n * Controlled selection — omit to let the component own selection state\n * (keyed by a stable task_id/name so the same row stays selected across a\n * re-created report of the same shape, e.g. after a live-update refresh).\n * Pass both this and `onSelect` for a host that persists selection at the\n * route level.\n */\n selected?: Test | null;\n onSelect?: (node: Test | null) => void;\n /** Controlled status/framework filters — omit to let the component own filter state. */\n filters?: TestFilters;\n onFiltersChange?: (next: TestFilters) => void;\n};\n\nconst DEFAULT_ADAPTERS = verificationAdapters();\n\n/**\n * A node's identity across a re-created forest: its own `task_id` when\n * present, else its name. Object identity can't be used — `verifyReportTests`\n * builds a brand-new `Test[]` from every report, so the previously-selected\n * object never appears in a fresh forest even when the underlying node is\n * unchanged.\n */\nfunction selectionKey(node: Test): string {\n return node.task_id ?? node.name;\n}\n\nfunction findBySelectionKey(nodes: Test[], key: string): Test | null {\n for (const node of nodes) {\n if (selectionKey(node) === key) return node;\n if (node.children) {\n const found = findBySelectionKey(node.children, key);\n if (found) return found;\n }\n }\n return null;\n}\n\nexport function VerificationResults({\n report,\n done,\n title = null,\n className,\n adapters = DEFAULT_ADAPTERS,\n emptyText = \"No verification has run yet\",\n selected: controlledSelected,\n onSelect: controlledOnSelect,\n filters: controlledFilters,\n onFiltersChange: controlledOnFiltersChange,\n}: VerificationResultsProps) {\n const tests = useMemo(() => (report ? verifyReportTests(report) : []), [report]);\n\n const [selectedKey, setSelectedKey] = useState<string | null>(null);\n const [internalFilters, setInternalFilters] = useState<TestFilters>(() => emptyTestFilters());\n const [expandAll, setExpandAll] = useState<boolean | null>(null);\n\n const filtersControlled = controlledFilters !== undefined;\n const filters = filtersControlled ? controlledFilters : internalFilters;\n const setFilters = (next: TestFilters) => {\n if (filtersControlled) controlledOnFiltersChange?.(next);\n else setInternalFilters(next);\n };\n\n const selectionControlled = controlledSelected !== undefined;\n const uncontrolledSelected = useMemo(\n () => (selectedKey ? findBySelectionKey(tests, selectedKey) : null),\n [tests, selectedKey],\n );\n const selected = selectionControlled ? controlledSelected : uncontrolledSelected;\n const setSelected = (node: Test | null) => {\n if (selectionControlled) controlledOnSelect?.(node);\n else setSelectedKey(node ? selectionKey(node) : null);\n };\n\n const visible = useMemo(\n () => filterTests(tests, filters.status, filters.framework),\n [tests, filters],\n );\n\n const startTime = report?.started_at ? Date.parse(report.started_at) : undefined;\n const endTime = report?.finished_at ? Date.parse(report.finished_at) : undefined;\n\n // A cmd/AI verifier's reason and feedback are the only place its verdict\n // survives once its nodes are empty (e.g. an error before any check ran), so\n // they're shown above the runner whenever present — not only in that empty\n // case — since a partial pass can carry a reason alongside real test nodes.\n const verdict =\n report && (report.reason || report.feedback) ? (\n <div className=\"shrink-0 space-y-2 border-b border-border px-3 py-2\">\n {report.reason && <p className=\"text-xs text-foreground\">{report.reason}</p>}\n {report.feedback && (\n <pre className=\"max-h-40 overflow-auto whitespace-pre-wrap rounded bg-muted p-2 font-mono text-[11px]\">\n {report.feedback}\n </pre>\n )}\n </div>\n ) : null;\n\n if (!report || tests.length === 0) {\n return (\n <div className={cn(\"flex flex-col\", className)}>\n {verdict}\n {!verdict && <p className=\"px-3 py-4 text-xs text-muted-foreground\">{emptyText}</p>}\n </div>\n );\n }\n\n return (\n <div className={cn(\"flex h-[30rem] min-h-80 flex-col\", className)}>\n {verdict}\n <TestRunner\n className=\"min-h-0 flex-1\"\n tests={visible}\n allTests={tests}\n selected={selected}\n filters={filters}\n expandAll={expandAll}\n done={done ?? report.state !== \"running\"}\n status={{ running: report.state === \"running\" }}\n {...(report.state === \"running\" ? { statusText: \"Running verification…\" } : {})}\n {...(startTime !== undefined ? { startTime } : {})}\n {...(endTime !== undefined ? { endTime } : {})}\n title={title}\n adapters={adapters}\n onSelect={setSelected}\n onFiltersChange={setFilters}\n onExpandAllChange={setExpandAll}\n />\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"VerificationResults.js","sources":["../../../src/data/verification/VerificationResults.tsx"],"sourcesContent":["// Props-only VerificationResults: renders a captain VerifyReport through the\n// shared TestRunner, so both the captain webapp and gavel pr/ui can drop it in\n// without forking a data-fetching or routing dependency. Ported from gavel's\n// VerificationFixtureResults.tsx.\n\nimport { useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport {\n emptyTestFilters,\n filterTests,\n TestRunner,\n type Test,\n type TestFilters,\n type TestNodeAdapterRegistry,\n} from \"../test-runner\";\nimport { verificationAdapters } from \"./adapters\";\nimport { verifyReportTests } from \"./verifyReportTests\";\nimport type { VerifyReport } from \"./verify-report\";\n\nexport type VerificationResultsProps = {\n report: VerifyReport | null;\n /** Overrides the run-complete state. Defaults to `report.state !== \"running\"`. */\n done?: boolean;\n /** Header title, passed through to TestRunner. Defaults to no title. */\n title?: ReactNode | null;\n className?: string;\n adapters?: TestNodeAdapterRegistry;\n emptyText?: string;\n /**\n * Controlled selection — omit to let the component own selection state\n * (keyed by a stable task_id/name so the same row stays selected across a\n * re-created report of the same shape, e.g. after a live-update refresh).\n * Pass both this and `onSelect` for a host that persists selection at the\n * route level.\n */\n selected?: Test | null;\n onSelect?: (node: Test | null) => void;\n activeAttempt?: number;\n onAttemptChange?: (attempt: number) => void;\n /** Controlled status/framework filters — omit to let the component own filter state. */\n filters?: TestFilters;\n onFiltersChange?: (next: TestFilters) => void;\n};\n\nconst DEFAULT_ADAPTERS = verificationAdapters();\n\n/**\n * A node's identity across a re-created forest: its own `task_id` when\n * present, else its name. Object identity can't be used — `verifyReportTests`\n * builds a brand-new `Test[]` from every report, so the previously-selected\n * object never appears in a fresh forest even when the underlying node is\n * unchanged.\n */\nfunction selectionKey(node: Test): string {\n return node.task_id ?? node.name;\n}\n\nfunction findBySelectionKey(nodes: Test[], key: string): Test | null {\n for (const node of nodes) {\n if (selectionKey(node) === key) return node;\n if (node.children) {\n const found = findBySelectionKey(node.children, key);\n if (found) return found;\n }\n }\n return null;\n}\n\nexport function VerificationResults({\n report,\n done,\n title = null,\n className,\n adapters = DEFAULT_ADAPTERS,\n emptyText = \"No verification has run yet\",\n selected: controlledSelected,\n onSelect: controlledOnSelect,\n activeAttempt,\n onAttemptChange,\n filters: controlledFilters,\n onFiltersChange: controlledOnFiltersChange,\n}: VerificationResultsProps) {\n const tests = useMemo(() => (report ? verifyReportTests(report) : []), [report]);\n\n const [selectedKey, setSelectedKey] = useState<string | null>(null);\n const [internalFilters, setInternalFilters] = useState<TestFilters>(() => emptyTestFilters());\n const [expandAll, setExpandAll] = useState<boolean | null>(null);\n\n const filtersControlled = controlledFilters !== undefined;\n const filters = filtersControlled ? controlledFilters : internalFilters;\n const setFilters = (next: TestFilters) => {\n if (filtersControlled) controlledOnFiltersChange?.(next);\n else setInternalFilters(next);\n };\n\n const selectionControlled = controlledSelected !== undefined;\n const uncontrolledSelected = useMemo(\n () => (selectedKey ? findBySelectionKey(tests, selectedKey) : null),\n [tests, selectedKey],\n );\n const selected = selectionControlled ? controlledSelected : uncontrolledSelected;\n const setSelected = (node: Test | null) => {\n if (selectionControlled) controlledOnSelect?.(node);\n else setSelectedKey(node ? selectionKey(node) : null);\n };\n\n const visible = useMemo(\n () => filterTests(tests, filters.status, filters.framework),\n [tests, filters],\n );\n\n const startTime = report?.started_at ? Date.parse(report.started_at) : undefined;\n const endTime = report?.finished_at ? Date.parse(report.finished_at) : undefined;\n\n // A cmd/AI verifier's reason and feedback are the only place its verdict\n // survives once its nodes are empty (e.g. an error before any check ran), so\n // they're shown above the runner whenever present — not only in that empty\n // case — since a partial pass can carry a reason alongside real test nodes.\n const verdict =\n report && (report.reason || report.feedback) ? (\n <div className=\"shrink-0 space-y-2 border-b border-border px-3 py-2\">\n {report.reason && <p className=\"text-xs text-foreground\">{report.reason}</p>}\n {report.feedback && (\n <pre className=\"max-h-40 overflow-auto whitespace-pre-wrap rounded bg-muted p-2 font-mono text-[11px]\">\n {report.feedback}\n </pre>\n )}\n </div>\n ) : null;\n\n if (!report || tests.length === 0) {\n return (\n <div className={cn(\"flex flex-col\", className)}>\n {verdict}\n {!verdict && <p className=\"px-3 py-4 text-xs text-muted-foreground\">{emptyText}</p>}\n </div>\n );\n }\n\n return (\n <div className={cn(\"flex h-[30rem] min-h-80 flex-col\", className)}>\n {verdict}\n <TestRunner\n className=\"min-h-0 flex-1\"\n tests={visible}\n allTests={tests}\n selected={selected}\n filters={filters}\n expandAll={expandAll}\n done={done ?? report.state !== \"running\"}\n status={{ running: report.state === \"running\" }}\n {...(report.state === \"running\" ? { statusText: \"Running verification…\" } : {})}\n {...(startTime !== undefined ? { startTime } : {})}\n {...(endTime !== undefined ? { endTime } : {})}\n title={title}\n adapters={adapters}\n onSelect={setSelected}\n {...(activeAttempt !== undefined ? { activeAttempt } : {})}\n {...(onAttemptChange ? { onAttemptChange } : {})}\n onFiltersChange={setFilters}\n onExpandAllChange={setExpandAll}\n />\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const JsonView = require("../JsonView.cjs");
|
|
5
|
+
const stepKind = require("./stepKind.cjs");
|
|
6
|
+
const stepKindViews = require("./stepKindViews.cjs");
|
|
5
7
|
const TestFailureDetail = require("../test-runner/TestFailureDetail.cjs");
|
|
6
8
|
const MarkIcons = require("../test-runner/MarkIcons.cjs");
|
|
7
9
|
const Expectation = require("../test-runner/Expectation.cjs");
|
|
@@ -57,10 +59,15 @@ function CelDetails({ node }) {
|
|
|
57
59
|
}
|
|
58
60
|
);
|
|
59
61
|
}
|
|
60
|
-
function
|
|
62
|
+
function rawStepDetail(rest) {
|
|
63
|
+
return Object.keys(rest).length > 0 ? rest : void 0;
|
|
64
|
+
}
|
|
65
|
+
function FixtureDetail({ node, renderWait }) {
|
|
61
66
|
const context = node.context;
|
|
62
67
|
const command = (context == null ? void 0 : context.command) ?? node.command;
|
|
63
68
|
const cwd = (context == null ? void 0 : context.cwd) ?? node.work_dir;
|
|
69
|
+
const stepDetail = stepKind.readStepDetail(node.detail);
|
|
70
|
+
const rawDetail = stepDetail.kind === "step" ? rawStepDetail(stepDetail.step.rest) : node.detail;
|
|
64
71
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 p-density-4", children: [
|
|
65
72
|
node.message && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap break-words text-sm", children: node.message }),
|
|
66
73
|
command && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-1", children: [
|
|
@@ -79,9 +86,11 @@ function FixtureDetail({ node }) {
|
|
|
79
86
|
] }),
|
|
80
87
|
/* @__PURE__ */ jsxRuntime.jsx(TestFailureDetail.TestOutput, { node }),
|
|
81
88
|
/* @__PURE__ */ jsxRuntime.jsx(CelDetails, { node }),
|
|
82
|
-
|
|
89
|
+
stepDetail.kind === "step" && /* @__PURE__ */ jsxRuntime.jsx(stepKindViews.StepKindSections, { step: stepDetail.step, ...renderWait ? { renderWait } : {} }),
|
|
90
|
+
stepDetail.kind === "invalid" && /* @__PURE__ */ jsxRuntime.jsx(stepKindViews.MalformedStepDetail, { error: stepDetail.error }),
|
|
91
|
+
rawDetail != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
83
92
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "Detail" }),
|
|
84
|
-
/* @__PURE__ */ jsxRuntime.jsx(JsonView.JsonView, { data:
|
|
93
|
+
/* @__PURE__ */ jsxRuntime.jsx(JsonView.JsonView, { data: rawDetail })
|
|
85
94
|
] })
|
|
86
95
|
] });
|
|
87
96
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapterViews.cjs","sources":["../../../src/data/verification/adapterViews.tsx"],"sourcesContent":["// Detail-body components for the verification node adapters. Split from\n// adapters.ts (react/only-export-components: a file mixing component\n// declarations with the plain TestNodeAdapter/registry exports loses Fast\n// Refresh). Ported from gavel's VerificationStepOutput.tsx (the checklist list\n// and the CelDetails block).\n\nimport { JsonView } from \"../JsonView\";\nimport {\n Expectation,\n OutcomeIcon,\n TestOutput,\n type FixtureContext,\n type Test,\n type TestOutcome,\n} from \"../test-runner\";\n\n// ── Checklist: the synthesized \"Acceptance criteria\" node and its items ────\n\nfunction checklistItemOutcome(item: Test): TestOutcome {\n if (item.failed) return \"failed\";\n if (item.passed) return \"passed\";\n return \"pending\";\n}\n\nfunction ChecklistItemRow({ item }: { item: Test }) {\n return (\n <li className=\"flex items-start gap-1.5 text-xs\">\n <OutcomeIcon outcome={checklistItemOutcome(item)} className=\"mt-0.5 text-sm\" />\n <span className=\"min-w-0\">\n {item.name}\n {item.message ? (\n <span className=\"block text-[11px] text-muted-foreground\">{item.message}</span>\n ) : null}\n </span>\n </li>\n );\n}\n\n/** Renders every checklist item for the \"Acceptance criteria\" parent, or the\n * single item itself when a leaf criterion is selected directly. */\nexport function ChecklistDetail({ node }: { node: Test }) {\n const items = node.children && node.children.length > 0 ? node.children : [node];\n return (\n <div className=\"space-y-2 p-density-4\">\n <ul className=\"space-y-1\">\n {items.map((item, index) => (\n <ChecklistItemRow key={item.task_id ?? index} item={item} />\n ))}\n </ul>\n </div>\n );\n}\n\n// ── Fixture / CEL: the failing-step detail (command + CelDetails) ──────────\n\nfunction readCelTrace(detail: unknown): string | undefined {\n if (detail && typeof detail === \"object\" && !Array.isArray(detail)) {\n const value = (detail as Record<string, unknown>).cel_trace;\n if (typeof value === \"string\" && value.length > 0) return value;\n }\n return undefined;\n}\n\n// A command step with no CEL assertion stores the whole command result object\n// in `actual` — the command/output is already rendered above, so dumping it\n// again as JSON is noise. Anything a CEL expression compared is shown as-is,\n// structured values included. `hasCelGate` mirrors gavel's own gate: a plain\n// `context.cel_expression`, or a trace recorded in `node.detail` when the\n// expression itself wasn't preserved on `context`.\nfunction comparisonValue(hasCelGate: boolean, value: unknown): unknown {\n if (value === undefined) return undefined;\n if (hasCelGate) return value;\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) return undefined;\n return value;\n}\n\n// CEL detail is rendered only for a failing node: the expression and the\n// values it saw are what explain the verdict.\nexport function CelDetails({ node }: { node: Test }) {\n if (node.passed) return null;\n const context = node.context as FixtureContext | undefined;\n const vars = context?.cel_vars ?? {};\n const expression = readCelTrace(node.detail) || context?.cel_expression;\n const hasCelGate = !!expression;\n const expected = comparisonValue(hasCelGate, context?.expected);\n const actual = comparisonValue(hasCelGate, context?.actual);\n const hasComparison = expected !== undefined || actual !== undefined;\n if (!expression && Object.keys(vars).length === 0 && !hasComparison) return null;\n return (\n <Expectation\n check={expression}\n checkLabel=\"expression\"\n vars={vars}\n expected={expected}\n actual={actual}\n />\n );\n}\n\nexport function FixtureDetail({ node }: { node: Test }) {\n const context = node.context as FixtureContext | undefined;\n const command = context?.command ?? node.command;\n const cwd = context?.cwd ?? node.work_dir;\n return (\n <div className=\"space-y-4 p-density-4\">\n {node.message && (\n <p className=\"whitespace-pre-wrap break-words text-sm\">{node.message}</p>\n )}\n {command && (\n <div className=\"min-w-0 space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">Command</div>\n <code className=\"block overflow-x-auto whitespace-pre rounded bg-muted px-2 py-1.5 text-xs\">\n {command}\n </code>\n <div className=\"flex flex-wrap items-center gap-2 text-[10px] text-muted-foreground\">\n {cwd && <span>in {cwd}</span>}\n {typeof context?.exit_code === \"number\" && (\n <span className={context.exit_code === 0 ? undefined : \"text-red-600\"}>\n exit {context.exit_code}\n </span>\n )}\n </div>\n </div>\n )}\n <TestOutput node={node} />\n <CelDetails node={node} />\n {
|
|
1
|
+
{"version":3,"file":"adapterViews.cjs","sources":["../../../src/data/verification/adapterViews.tsx"],"sourcesContent":["// Detail-body components for the verification node adapters. Split from\n// adapters.ts (react/only-export-components: a file mixing component\n// declarations with the plain TestNodeAdapter/registry exports loses Fast\n// Refresh). Ported from gavel's VerificationStepOutput.tsx (the checklist list\n// and the CelDetails block).\n\nimport type { ReactNode } from \"react\";\nimport { JsonView } from \"../JsonView\";\nimport { readStepDetail, type WaitDetail } from \"./stepKind\";\nimport { MalformedStepDetail, StepKindSections } from \"./stepKindViews\";\nimport {\n Expectation,\n OutcomeIcon,\n TestOutput,\n type FixtureContext,\n type Test,\n type TestOutcome,\n} from \"../test-runner\";\n\n// ── Checklist: the synthesized \"Acceptance criteria\" node and its items ────\n\nfunction checklistItemOutcome(item: Test): TestOutcome {\n if (item.failed) return \"failed\";\n if (item.passed) return \"passed\";\n return \"pending\";\n}\n\nfunction ChecklistItemRow({ item }: { item: Test }) {\n return (\n <li className=\"flex items-start gap-1.5 text-xs\">\n <OutcomeIcon outcome={checklistItemOutcome(item)} className=\"mt-0.5 text-sm\" />\n <span className=\"min-w-0\">\n {item.name}\n {item.message ? (\n <span className=\"block text-[11px] text-muted-foreground\">{item.message}</span>\n ) : null}\n </span>\n </li>\n );\n}\n\n/** Renders every checklist item for the \"Acceptance criteria\" parent, or the\n * single item itself when a leaf criterion is selected directly. */\nexport function ChecklistDetail({ node }: { node: Test }) {\n const items = node.children && node.children.length > 0 ? node.children : [node];\n return (\n <div className=\"space-y-2 p-density-4\">\n <ul className=\"space-y-1\">\n {items.map((item, index) => (\n <ChecklistItemRow key={item.task_id ?? index} item={item} />\n ))}\n </ul>\n </div>\n );\n}\n\n// ── Fixture / CEL: the failing-step detail (command + CelDetails) ──────────\n\nfunction readCelTrace(detail: unknown): string | undefined {\n if (detail && typeof detail === \"object\" && !Array.isArray(detail)) {\n const value = (detail as Record<string, unknown>).cel_trace;\n if (typeof value === \"string\" && value.length > 0) return value;\n }\n return undefined;\n}\n\n// A command step with no CEL assertion stores the whole command result object\n// in `actual` — the command/output is already rendered above, so dumping it\n// again as JSON is noise. Anything a CEL expression compared is shown as-is,\n// structured values included. `hasCelGate` mirrors gavel's own gate: a plain\n// `context.cel_expression`, or a trace recorded in `node.detail` when the\n// expression itself wasn't preserved on `context`.\nfunction comparisonValue(hasCelGate: boolean, value: unknown): unknown {\n if (value === undefined) return undefined;\n if (hasCelGate) return value;\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) return undefined;\n return value;\n}\n\n// CEL detail is rendered only for a failing node: the expression and the\n// values it saw are what explain the verdict.\nexport function CelDetails({ node }: { node: Test }) {\n if (node.passed) return null;\n const context = node.context as FixtureContext | undefined;\n const vars = context?.cel_vars ?? {};\n const expression = readCelTrace(node.detail) || context?.cel_expression;\n const hasCelGate = !!expression;\n const expected = comparisonValue(hasCelGate, context?.expected);\n const actual = comparisonValue(hasCelGate, context?.actual);\n const hasComparison = expected !== undefined || actual !== undefined;\n if (!expression && Object.keys(vars).length === 0 && !hasComparison) return null;\n return (\n <Expectation\n check={expression}\n checkLabel=\"expression\"\n vars={vars}\n expected={expected}\n actual={actual}\n />\n );\n}\n\nfunction rawStepDetail(rest: Record<string, unknown>): Record<string, unknown> | undefined {\n return Object.keys(rest).length > 0 ? rest : undefined;\n}\n\nexport function FixtureDetail({ node, renderWait }: { node: Test; renderWait?: (wait: WaitDetail) => ReactNode }) {\n const context = node.context as FixtureContext | undefined;\n const command = context?.command ?? node.command;\n const cwd = context?.cwd ?? node.work_dir;\n const stepDetail = readStepDetail(node.detail);\n // A typed step shows its own sections, so the raw block keeps only what they don't cover.\n const rawDetail = stepDetail.kind === \"step\" ? rawStepDetail(stepDetail.step.rest) : node.detail;\n return (\n <div className=\"space-y-4 p-density-4\">\n {node.message && (\n <p className=\"whitespace-pre-wrap break-words text-sm\">{node.message}</p>\n )}\n {command && (\n <div className=\"min-w-0 space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">Command</div>\n <code className=\"block overflow-x-auto whitespace-pre rounded bg-muted px-2 py-1.5 text-xs\">\n {command}\n </code>\n <div className=\"flex flex-wrap items-center gap-2 text-[10px] text-muted-foreground\">\n {cwd && <span>in {cwd}</span>}\n {typeof context?.exit_code === \"number\" && (\n <span className={context.exit_code === 0 ? undefined : \"text-red-600\"}>\n exit {context.exit_code}\n </span>\n )}\n </div>\n </div>\n )}\n <TestOutput node={node} />\n <CelDetails node={node} />\n {stepDetail.kind === \"step\" && <StepKindSections step={stepDetail.step} {...(renderWait ? { renderWait } : {})} />}\n {stepDetail.kind === \"invalid\" && <MalformedStepDetail error={stepDetail.error} />}\n {rawDetail != null && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">Detail</div>\n <JsonView data={rawDetail} />\n </div>\n )}\n </div>\n );\n}\n"],"names":["jsxs","jsx","OutcomeIcon","Expectation","readStepDetail","TestOutput","StepKindSections","MalformedStepDetail","JsonView"],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { WaitDetail } from './stepKind.js';
|
|
1
3
|
import { Test } from '../test-runner/index.js';
|
|
2
4
|
/** Renders every checklist item for the "Acceptance criteria" parent, or the
|
|
3
5
|
* single item itself when a leaf criterion is selected directly. */
|
|
@@ -7,7 +9,8 @@ export declare function ChecklistDetail({ node }: {
|
|
|
7
9
|
export declare function CelDetails({ node }: {
|
|
8
10
|
node: Test;
|
|
9
11
|
}): import("react").JSX.Element | null;
|
|
10
|
-
export declare function FixtureDetail({ node }: {
|
|
12
|
+
export declare function FixtureDetail({ node, renderWait }: {
|
|
11
13
|
node: Test;
|
|
14
|
+
renderWait?: (wait: WaitDetail) => ReactNode;
|
|
12
15
|
}): import("react").JSX.Element;
|
|
13
16
|
//# sourceMappingURL=adapterViews.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapterViews.d.ts","sourceRoot":"","sources":["../../../src/data/verification/adapterViews.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"adapterViews.d.ts","sourceRoot":"","sources":["../../../src/data/verification/adapterViews.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7D,OAAO,EAKL,KAAK,IAAI,EAEV,MAAM,gBAAgB,CAAC;AAwBxB;qEACqE;AACrE,wBAAgB,eAAe,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,+BAWvD;AA2BD,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,sCAmBlD;AAMD,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,SAAS,CAAA;CAAE,+BAwC/G"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { JsonView } from "../JsonView.js";
|
|
3
|
+
import { readStepDetail } from "./stepKind.js";
|
|
4
|
+
import { StepKindSections, MalformedStepDetail } from "./stepKindViews.js";
|
|
3
5
|
import { TestOutput } from "../test-runner/TestFailureDetail.js";
|
|
4
6
|
import { OutcomeIcon } from "../test-runner/MarkIcons.js";
|
|
5
7
|
import { Expectation } from "../test-runner/Expectation.js";
|
|
@@ -55,10 +57,15 @@ function CelDetails({ node }) {
|
|
|
55
57
|
}
|
|
56
58
|
);
|
|
57
59
|
}
|
|
58
|
-
function
|
|
60
|
+
function rawStepDetail(rest) {
|
|
61
|
+
return Object.keys(rest).length > 0 ? rest : void 0;
|
|
62
|
+
}
|
|
63
|
+
function FixtureDetail({ node, renderWait }) {
|
|
59
64
|
const context = node.context;
|
|
60
65
|
const command = (context == null ? void 0 : context.command) ?? node.command;
|
|
61
66
|
const cwd = (context == null ? void 0 : context.cwd) ?? node.work_dir;
|
|
67
|
+
const stepDetail = readStepDetail(node.detail);
|
|
68
|
+
const rawDetail = stepDetail.kind === "step" ? rawStepDetail(stepDetail.step.rest) : node.detail;
|
|
62
69
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-4 p-density-4", children: [
|
|
63
70
|
node.message && /* @__PURE__ */ jsx("p", { className: "whitespace-pre-wrap break-words text-sm", children: node.message }),
|
|
64
71
|
command && /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-1", children: [
|
|
@@ -77,9 +84,11 @@ function FixtureDetail({ node }) {
|
|
|
77
84
|
] }),
|
|
78
85
|
/* @__PURE__ */ jsx(TestOutput, { node }),
|
|
79
86
|
/* @__PURE__ */ jsx(CelDetails, { node }),
|
|
80
|
-
|
|
87
|
+
stepDetail.kind === "step" && /* @__PURE__ */ jsx(StepKindSections, { step: stepDetail.step, ...renderWait ? { renderWait } : {} }),
|
|
88
|
+
stepDetail.kind === "invalid" && /* @__PURE__ */ jsx(MalformedStepDetail, { error: stepDetail.error }),
|
|
89
|
+
rawDetail != null && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
81
90
|
/* @__PURE__ */ jsx("div", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "Detail" }),
|
|
82
|
-
/* @__PURE__ */ jsx(JsonView, { data:
|
|
91
|
+
/* @__PURE__ */ jsx(JsonView, { data: rawDetail })
|
|
83
92
|
] })
|
|
84
93
|
] });
|
|
85
94
|
}
|