@flanksource/clicky-ui 0.3.46 → 0.3.48
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/NOTICE.md +11 -0
- package/README.md +49 -0
- package/dist/ai.cjs +13 -8
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +7 -2
- package/dist/ai.js.map +1 -1
- 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/components/ErrorWrapper.cjs +2 -3
- package/dist/components/ErrorWrapper.cjs.map +1 -1
- package/dist/components/ErrorWrapper.d.ts.map +1 -1
- package/dist/components/ErrorWrapper.js +3 -4
- package/dist/components/ErrorWrapper.js.map +1 -1
- package/dist/data/Clicky.cjs +3 -0
- package/dist/data/Clicky.cjs.map +1 -1
- package/dist/data/Clicky.js +3 -0
- package/dist/data/Clicky.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/FilterPill.cjs +15 -2
- package/dist/data/FilterPill.cjs.map +1 -1
- package/dist/data/FilterPill.d.ts +1 -1
- package/dist/data/FilterPill.d.ts.map +1 -1
- package/dist/data/FilterPill.js +15 -2
- package/dist/data/FilterPill.js.map +1 -1
- package/dist/data/LogViewer.cjs +27 -8
- package/dist/data/LogViewer.cjs.map +1 -1
- package/dist/data/LogViewer.d.ts +11 -3
- package/dist/data/LogViewer.d.ts.map +1 -1
- package/dist/data/LogViewer.js +27 -8
- package/dist/data/LogViewer.js.map +1 -1
- package/dist/data/Properties.cjs +2 -15
- package/dist/data/Properties.cjs.map +1 -1
- package/dist/data/Properties.d.ts +4 -0
- package/dist/data/Properties.d.ts.map +1 -1
- package/dist/data/Properties.js +2 -15
- package/dist/data/Properties.js.map +1 -1
- package/dist/data/PropertyValue.cjs +37 -0
- package/dist/data/PropertyValue.cjs.map +1 -0
- package/dist/data/PropertyValue.d.ts +6 -0
- package/dist/data/PropertyValue.d.ts.map +1 -0
- package/dist/data/PropertyValue.js +37 -0
- package/dist/data/PropertyValue.js.map +1 -0
- 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/Tree.cjs +4 -3
- package/dist/data/Tree.cjs.map +1 -1
- package/dist/data/Tree.d.ts +3 -1
- package/dist/data/Tree.d.ts.map +1 -1
- package/dist/data/Tree.js +4 -3
- package/dist/data/Tree.js.map +1 -1
- package/dist/data/ai/ChatFab.cjs +1 -1
- package/dist/data/ai/ChatFab.cjs.map +1 -1
- package/dist/data/ai/ChatFab.js +1 -1
- package/dist/data/ai/ChatFab.js.map +1 -1
- package/dist/data/ai/ChatWindow.cjs +106 -171
- package/dist/data/ai/ChatWindow.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.d.ts +6 -2
- package/dist/data/ai/ChatWindow.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.header.cjs +104 -0
- package/dist/data/ai/ChatWindow.header.cjs.map +1 -0
- package/dist/data/ai/ChatWindow.header.d.ts +29 -0
- package/dist/data/ai/ChatWindow.header.d.ts.map +1 -0
- package/dist/data/ai/ChatWindow.header.js +104 -0
- package/dist/data/ai/ChatWindow.header.js.map +1 -0
- package/dist/data/ai/ChatWindow.js +107 -172
- package/dist/data/ai/ChatWindow.js.map +1 -1
- package/dist/data/ai/ChatWindow.placement.cjs +95 -0
- package/dist/data/ai/ChatWindow.placement.cjs.map +1 -0
- package/dist/data/ai/ChatWindow.placement.d.ts +32 -0
- package/dist/data/ai/ChatWindow.placement.d.ts.map +1 -0
- package/dist/data/ai/ChatWindow.placement.js +95 -0
- package/dist/data/ai/ChatWindow.placement.js.map +1 -0
- package/dist/data/ai/SessionChatComposer.cjs +3 -1
- package/dist/data/ai/SessionChatComposer.cjs.map +1 -1
- package/dist/data/ai/SessionChatComposer.d.ts +4 -1
- package/dist/data/ai/SessionChatComposer.d.ts.map +1 -1
- package/dist/data/ai/SessionChatComposer.js +3 -1
- package/dist/data/ai/SessionChatComposer.js.map +1 -1
- package/dist/data/ai/SessionInspector.cjs +68 -72
- package/dist/data/ai/SessionInspector.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.composer-slot.cjs +8 -0
- package/dist/data/ai/SessionInspector.composer-slot.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.composer-slot.d.ts +9 -0
- package/dist/data/ai/SessionInspector.composer-slot.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.composer-slot.js +8 -0
- package/dist/data/ai/SessionInspector.composer-slot.js.map +1 -0
- package/dist/data/ai/SessionInspector.d.ts +6 -1
- package/dist/data/ai/SessionInspector.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.js +69 -73
- package/dist/data/ai/SessionInspector.js.map +1 -1
- package/dist/data/ai/SessionInspector.legacy.cjs +41 -42
- package/dist/data/ai/SessionInspector.legacy.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.legacy.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.legacy.js +41 -42
- package/dist/data/ai/SessionInspector.legacy.js.map +1 -1
- package/dist/data/ai/SessionInspector.remote-view.cjs +14 -9
- package/dist/data/ai/SessionInspector.remote-view.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.remote-view.d.ts +6 -2
- package/dist/data/ai/SessionInspector.remote-view.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.remote-view.js +14 -9
- package/dist/data/ai/SessionInspector.remote-view.js.map +1 -1
- package/dist/data/ai/SessionInspector.remote.cjs +84 -16
- package/dist/data/ai/SessionInspector.remote.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.remote.d.ts +42 -7
- package/dist/data/ai/SessionInspector.remote.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.remote.js +86 -18
- package/dist/data/ai/SessionInspector.remote.js.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.cjs +5 -0
- package/dist/data/ai/SessionInspector.transcript.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.js +5 -0
- package/dist/data/ai/SessionInspector.transcript.js.map +1 -1
- package/dist/data/ai/SessionTail.cjs +63 -0
- package/dist/data/ai/SessionTail.cjs.map +1 -0
- package/dist/data/ai/SessionTail.d.ts +14 -0
- package/dist/data/ai/SessionTail.d.ts.map +1 -0
- package/dist/data/ai/SessionTail.js +63 -0
- package/dist/data/ai/SessionTail.js.map +1 -0
- package/dist/data/ai/SessionViewer.cjs +10 -3
- package/dist/data/ai/SessionViewer.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.d.ts +7 -1
- package/dist/data/ai/SessionViewer.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.js +10 -3
- package/dist/data/ai/SessionViewer.js.map +1 -1
- package/dist/data/ai/SessionViewer.unified.d.ts +14 -0
- package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
- package/dist/data/ai/index.d.ts +4 -3
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/ai/use-session-scroll.cjs +30 -6
- package/dist/data/ai/use-session-scroll.cjs.map +1 -1
- package/dist/data/ai/use-session-scroll.d.ts +7 -0
- package/dist/data/ai/use-session-scroll.d.ts.map +1 -1
- package/dist/data/ai/use-session-scroll.js +30 -6
- package/dist/data/ai/use-session-scroll.js.map +1 -1
- package/dist/data/chat/Chat.cjs +1 -1
- package/dist/data/chat/Chat.cjs.map +1 -1
- package/dist/data/chat/Chat.js +1 -1
- package/dist/data/chat/Chat.js.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.cjs +4 -4
- package/dist/data/chat/ChatRuntimeToolbar.cjs.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.d.ts.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.js +4 -4
- package/dist/data/chat/ChatRuntimeToolbar.js.map +1 -1
- package/dist/data/chat/PromptInput.cjs +4 -2
- package/dist/data/chat/PromptInput.cjs.map +1 -1
- package/dist/data/chat/PromptInput.d.ts +5 -1
- package/dist/data/chat/PromptInput.d.ts.map +1 -1
- package/dist/data/chat/PromptInput.js +4 -2
- package/dist/data/chat/PromptInput.js.map +1 -1
- package/dist/data/diagnostics/ErrorDetails.cjs +13 -2
- package/dist/data/diagnostics/ErrorDetails.cjs.map +1 -1
- package/dist/data/diagnostics/ErrorDetails.d.ts +3 -1
- package/dist/data/diagnostics/ErrorDetails.d.ts.map +1 -1
- package/dist/data/diagnostics/ErrorDetails.js +14 -3
- package/dist/data/diagnostics/ErrorDetails.js.map +1 -1
- package/dist/data/diagnostics/FrameSourceWindow.cjs +3 -2
- package/dist/data/diagnostics/FrameSourceWindow.cjs.map +1 -1
- package/dist/data/diagnostics/FrameSourceWindow.d.ts.map +1 -1
- package/dist/data/diagnostics/FrameSourceWindow.js +3 -2
- package/dist/data/diagnostics/FrameSourceWindow.js.map +1 -1
- package/dist/data/diagnostics/error-diagnostics.cjs +5 -0
- package/dist/data/diagnostics/error-diagnostics.cjs.map +1 -1
- package/dist/data/diagnostics/error-diagnostics.d.ts +1 -0
- package/dist/data/diagnostics/error-diagnostics.d.ts.map +1 -1
- package/dist/data/diagnostics/error-diagnostics.js +6 -1
- package/dist/data/diagnostics/error-diagnostics.js.map +1 -1
- package/dist/data/har/HarPanel.cjs +3 -1
- package/dist/data/har/HarPanel.cjs.map +1 -1
- package/dist/data/har/HarPanel.d.ts +4 -1
- package/dist/data/har/HarPanel.d.ts.map +1 -1
- package/dist/data/har/HarPanel.js +3 -1
- package/dist/data/har/HarPanel.js.map +1 -1
- package/dist/data/test-runner/Expectation.cjs +57 -0
- package/dist/data/test-runner/Expectation.cjs.map +1 -0
- package/dist/data/test-runner/Expectation.d.ts +19 -0
- package/dist/data/test-runner/Expectation.d.ts.map +1 -0
- package/dist/data/test-runner/Expectation.js +57 -0
- package/dist/data/test-runner/Expectation.js.map +1 -0
- package/dist/data/test-runner/MarkIcons.cjs +38 -0
- package/dist/data/test-runner/MarkIcons.cjs.map +1 -0
- package/dist/data/test-runner/MarkIcons.d.ts +15 -0
- package/dist/data/test-runner/MarkIcons.d.ts.map +1 -0
- package/dist/data/test-runner/MarkIcons.js +38 -0
- package/dist/data/test-runner/MarkIcons.js.map +1 -0
- package/dist/data/test-runner/TestDetailPanel.cjs +99 -53
- 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 +101 -55
- package/dist/data/test-runner/TestDetailPanel.js.map +1 -1
- package/dist/data/test-runner/TestFailureDetail.cjs +23 -27
- package/dist/data/test-runner/TestFailureDetail.cjs.map +1 -1
- package/dist/data/test-runner/TestFailureDetail.d.ts +2 -2
- package/dist/data/test-runner/TestFailureDetail.d.ts.map +1 -1
- package/dist/data/test-runner/TestFailureDetail.js +23 -27
- package/dist/data/test-runner/TestFailureDetail.js.map +1 -1
- package/dist/data/test-runner/TestFilterBar.cjs +87 -93
- package/dist/data/test-runner/TestFilterBar.cjs.map +1 -1
- package/dist/data/test-runner/TestFilterBar.d.ts +3 -2
- package/dist/data/test-runner/TestFilterBar.d.ts.map +1 -1
- package/dist/data/test-runner/TestFilterBar.js +89 -95
- package/dist/data/test-runner/TestFilterBar.js.map +1 -1
- package/dist/data/test-runner/TestRunSummary.cjs +35 -21
- package/dist/data/test-runner/TestRunSummary.cjs.map +1 -1
- package/dist/data/test-runner/TestRunSummary.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunSummary.js +35 -21
- package/dist/data/test-runner/TestRunSummary.js.map +1 -1
- package/dist/data/test-runner/TestRunner.cjs +58 -30
- package/dist/data/test-runner/TestRunner.cjs.map +1 -1
- package/dist/data/test-runner/TestRunner.d.ts +6 -3
- package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunner.js +58 -30
- package/dist/data/test-runner/TestRunner.js.map +1 -1
- package/dist/data/test-runner/TestTree.cjs +5 -2
- package/dist/data/test-runner/TestTree.cjs.map +1 -1
- package/dist/data/test-runner/TestTree.d.ts +5 -2
- package/dist/data/test-runner/TestTree.d.ts.map +1 -1
- package/dist/data/test-runner/TestTree.js +5 -2
- package/dist/data/test-runner/TestTree.js.map +1 -1
- package/dist/data/test-runner/TestTreeNode.cjs +28 -19
- 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 +29 -20
- package/dist/data/test-runner/TestTreeNode.js.map +1 -1
- package/dist/data/test-runner/adapter.cjs +15 -0
- package/dist/data/test-runner/adapter.cjs.map +1 -1
- package/dist/data/test-runner/adapter.d.ts +27 -7
- package/dist/data/test-runner/adapter.d.ts.map +1 -1
- package/dist/data/test-runner/adapter.js +15 -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/copy.cjs +114 -0
- package/dist/data/test-runner/copy.cjs.map +1 -0
- package/dist/data/test-runner/copy.d.ts +47 -0
- package/dist/data/test-runner/copy.d.ts.map +1 -0
- package/dist/data/test-runner/copy.js +114 -0
- package/dist/data/test-runner/copy.js.map +1 -0
- package/dist/data/test-runner/index.d.ts +6 -3
- package/dist/data/test-runner/index.d.ts.map +1 -1
- package/dist/data/test-runner/marks.cjs +184 -0
- package/dist/data/test-runner/marks.cjs.map +1 -0
- package/dist/data/test-runner/marks.d.ts +40 -0
- package/dist/data/test-runner/marks.d.ts.map +1 -0
- package/dist/data/test-runner/marks.js +184 -0
- package/dist/data/test-runner/marks.js.map +1 -0
- package/dist/data/test-runner/status.cjs +27 -44
- package/dist/data/test-runner/status.cjs.map +1 -1
- package/dist/data/test-runner/status.d.ts +12 -3
- package/dist/data/test-runner/status.d.ts.map +1 -1
- package/dist/data/test-runner/status.js +27 -44
- package/dist/data/test-runner/status.js.map +1 -1
- package/dist/data/traces/TerminalCastPlayer.d.ts +21 -0
- package/dist/data/traces/TerminalCastPlayer.d.ts.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/cast.d.ts +9 -0
- package/dist/data/traces/cast.d.ts.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.d.ts +13 -0
- package/dist/data/traces/har-adapter.d.ts.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-timeline.d.ts +26 -0
- package/dist/data/traces/terminal-timeline.d.ts.map +1 -0
- package/dist/data/traces/types.d.ts +141 -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 +28 -44
- 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 +28 -44
- package/dist/data/verification/adapterViews.js.map +1 -1
- package/dist/data/verification/adapters.cjs +163 -8
- 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 +163 -8
- 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.js +3 -3
- package/dist/data.cjs +58 -3
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +3 -0
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +60 -5
- package/dist/data.js.map +1 -1
- package/dist/icons/components/UiLogoEslint.cjs +10 -0
- package/dist/icons/components/UiLogoEslint.cjs.map +1 -0
- package/dist/icons/components/UiLogoEslint.d.ts +9 -0
- package/dist/icons/components/UiLogoEslint.d.ts.map +1 -0
- package/dist/icons/components/UiLogoEslint.js +10 -0
- package/dist/icons/components/UiLogoEslint.js.map +1 -0
- package/dist/icons/components/UiLogoGo.cjs +10 -0
- package/dist/icons/components/UiLogoGo.cjs.map +1 -0
- package/dist/icons/components/UiLogoGo.d.ts +9 -0
- package/dist/icons/components/UiLogoGo.d.ts.map +1 -0
- package/dist/icons/components/UiLogoGo.js +10 -0
- package/dist/icons/components/UiLogoGo.js.map +1 -0
- package/dist/icons/components/UiLogoJest.cjs +10 -0
- package/dist/icons/components/UiLogoJest.cjs.map +1 -0
- package/dist/icons/components/UiLogoJest.d.ts +9 -0
- package/dist/icons/components/UiLogoJest.d.ts.map +1 -0
- package/dist/icons/components/UiLogoJest.js +10 -0
- package/dist/icons/components/UiLogoJest.js.map +1 -0
- package/dist/icons/components/UiLogoMarkdown.cjs +10 -0
- package/dist/icons/components/UiLogoMarkdown.cjs.map +1 -0
- package/dist/icons/components/UiLogoMarkdown.d.ts +9 -0
- package/dist/icons/components/UiLogoMarkdown.d.ts.map +1 -0
- package/dist/icons/components/UiLogoMarkdown.js +10 -0
- package/dist/icons/components/UiLogoMarkdown.js.map +1 -0
- package/dist/icons/components/UiLogoOxc.cjs +10 -0
- package/dist/icons/components/UiLogoOxc.cjs.map +1 -0
- package/dist/icons/components/UiLogoOxc.d.ts +9 -0
- package/dist/icons/components/UiLogoOxc.d.ts.map +1 -0
- package/dist/icons/components/UiLogoOxc.js +10 -0
- package/dist/icons/components/UiLogoOxc.js.map +1 -0
- package/dist/icons/components/UiLogoPlaywright.cjs +10 -0
- package/dist/icons/components/UiLogoPlaywright.cjs.map +1 -0
- package/dist/icons/components/UiLogoPlaywright.d.ts +9 -0
- package/dist/icons/components/UiLogoPlaywright.d.ts.map +1 -0
- package/dist/icons/components/UiLogoPlaywright.js +10 -0
- package/dist/icons/components/UiLogoPlaywright.js.map +1 -0
- package/dist/icons/components/UiLogoPython.cjs +10 -0
- package/dist/icons/components/UiLogoPython.cjs.map +1 -0
- package/dist/icons/components/UiLogoPython.d.ts +9 -0
- package/dist/icons/components/UiLogoPython.d.ts.map +1 -0
- package/dist/icons/components/UiLogoPython.js +10 -0
- package/dist/icons/components/UiLogoPython.js.map +1 -0
- package/dist/icons/components/UiLogoReact.cjs +10 -0
- package/dist/icons/components/UiLogoReact.cjs.map +1 -0
- package/dist/icons/components/UiLogoReact.d.ts +9 -0
- package/dist/icons/components/UiLogoReact.d.ts.map +1 -0
- package/dist/icons/components/UiLogoReact.js +10 -0
- package/dist/icons/components/UiLogoReact.js.map +1 -0
- package/dist/icons/components/UiLogoRuff.cjs +10 -0
- package/dist/icons/components/UiLogoRuff.cjs.map +1 -0
- package/dist/icons/components/UiLogoRuff.d.ts +9 -0
- package/dist/icons/components/UiLogoRuff.d.ts.map +1 -0
- package/dist/icons/components/UiLogoRuff.js +10 -0
- package/dist/icons/components/UiLogoRuff.js.map +1 -0
- package/dist/icons/components/UiLogoTypescript.cjs +10 -0
- package/dist/icons/components/UiLogoTypescript.cjs.map +1 -0
- package/dist/icons/components/UiLogoTypescript.d.ts +9 -0
- package/dist/icons/components/UiLogoTypescript.d.ts.map +1 -0
- package/dist/icons/components/UiLogoTypescript.js +10 -0
- package/dist/icons/components/UiLogoTypescript.js.map +1 -0
- package/dist/icons/components/UiLogoVitest.cjs +10 -0
- package/dist/icons/components/UiLogoVitest.cjs.map +1 -0
- package/dist/icons/components/UiLogoVitest.d.ts +9 -0
- package/dist/icons/components/UiLogoVitest.d.ts.map +1 -0
- package/dist/icons/components/UiLogoVitest.js +10 -0
- package/dist/icons/components/UiLogoVitest.js.map +1 -0
- package/dist/icons/index.d.ts +11 -0
- package/dist/icons/index.d.ts.map +1 -1
- package/dist/icons/registry.cjs +22 -0
- package/dist/icons/registry.cjs.map +1 -1
- package/dist/icons/registry.d.ts.map +1 -1
- package/dist/icons/registry.js +22 -0
- package/dist/icons/registry.js.map +1 -1
- package/dist/icons.cjs +22 -0
- package/dist/icons.cjs.map +1 -1
- package/dist/icons.js +22 -0
- package/dist/icons.js.map +1 -1
- package/dist/index.cjs +60 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +62 -5
- package/dist/index.js.map +1 -1
- package/dist/overlay/DropdownMenuSubmenu.cjs +4 -4
- package/dist/overlay/DropdownMenuSubmenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenuSubmenu.js +4 -4
- package/dist/overlay/DropdownMenuSubmenu.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/InlineError.cjs +12 -43
- package/dist/rpc/InlineError.cjs.map +1 -1
- package/dist/rpc/InlineError.d.ts.map +1 -1
- package/dist/rpc/InlineError.js +13 -44
- package/dist/rpc/InlineError.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 +119 -22
- package/dist/rpc/OperationScheduleDialog.cjs.map +1 -1
- package/dist/rpc/OperationScheduleDialog.d.ts +7 -0
- package/dist/rpc/OperationScheduleDialog.d.ts.map +1 -1
- package/dist/rpc/OperationScheduleDialog.js +120 -23
- package/dist/rpc/OperationScheduleDialog.js.map +1 -1
- package/dist/rpc/OperationSchedules.cjs +17 -2
- package/dist/rpc/OperationSchedules.cjs.map +1 -1
- package/dist/rpc/OperationSchedules.d.ts.map +1 -1
- package/dist/rpc/OperationSchedules.js +17 -2
- package/dist/rpc/OperationSchedules.js.map +1 -1
- package/dist/rpc/operation-schedule-model.cjs +2 -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 +2 -7
- package/dist/rpc/operation-schedule-model.js.map +1 -1
- package/dist/rpc/operation-schedule-types.d.ts +12 -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
- package/dist/data/test-runner/frameworkIcon.cjs +0 -27
- package/dist/data/test-runner/frameworkIcon.cjs.map +0 -1
- package/dist/data/test-runner/frameworkIcon.d.ts +0 -3
- package/dist/data/test-runner/frameworkIcon.d.ts.map +0 -1
- package/dist/data/test-runner/frameworkIcon.js +0 -27
- package/dist/data/test-runner/frameworkIcon.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkIcons.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/MarkIcons.tsx"],"names":[],"mappings":"AAKA,OAAO,EAIL,KAAK,YAAY,EAEjB,KAAK,WAAW,EAEjB,MAAM,SAAS,CAAC;AAEjB,KAAK,aAAa,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAiBxD,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,aAAa,GAAG;IAAE,OAAO,EAAE,WAAW,CAAA;CAAE,+BAE3F;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,SAAS,GACV,EAAE,aAAa,GAAG;IAAE,QAAQ,EAAE,YAAY,CAAA;CAAE,+BAE5C;AAED,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,sCAGzF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Icon } from "../Icon.js";
|
|
3
|
+
import { cn } from "../../lib/utils.js";
|
|
4
|
+
import { LINT_SEVERITIES, TEST_OUTCOMES, toolMark } from "./marks.js";
|
|
5
|
+
function MarkIcon({ mark, className }) {
|
|
6
|
+
return /* @__PURE__ */ jsx(
|
|
7
|
+
Icon,
|
|
8
|
+
{
|
|
9
|
+
icon: mark.icon,
|
|
10
|
+
title: mark.label,
|
|
11
|
+
className: cn(
|
|
12
|
+
"shrink-0",
|
|
13
|
+
mark.className,
|
|
14
|
+
"spin" in mark && mark.spin && "motion-safe:animate-spin",
|
|
15
|
+
className
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
function OutcomeIcon({ outcome, className }) {
|
|
21
|
+
return /* @__PURE__ */ jsx(MarkIcon, { mark: TEST_OUTCOMES[outcome], className });
|
|
22
|
+
}
|
|
23
|
+
function LintSeverityIcon({
|
|
24
|
+
severity,
|
|
25
|
+
className
|
|
26
|
+
}) {
|
|
27
|
+
return /* @__PURE__ */ jsx(MarkIcon, { mark: LINT_SEVERITIES[severity], className });
|
|
28
|
+
}
|
|
29
|
+
function ToolIcon({ tool, className }) {
|
|
30
|
+
const mark = toolMark(tool);
|
|
31
|
+
return mark ? /* @__PURE__ */ jsx(MarkIcon, { mark, className }) : null;
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
LintSeverityIcon,
|
|
35
|
+
OutcomeIcon,
|
|
36
|
+
ToolIcon
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=MarkIcons.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkIcons.js","sources":["../../../src/data/test-runner/MarkIcons.tsx"],"sourcesContent":["// Renders the marks.ts catalogs. Kept apart from them so this file exports\n// components only (react/only-export-components).\n\nimport { Icon } from \"../Icon\";\nimport { cn } from \"../../lib/utils\";\nimport {\n LINT_SEVERITIES,\n TEST_OUTCOMES,\n toolMark,\n type LintSeverity,\n type ResultMark,\n type TestOutcome,\n type ToolMark,\n} from \"./marks\";\n\ntype MarkIconProps = { className?: string | undefined };\n\nfunction MarkIcon({ mark, className }: MarkIconProps & { mark: ResultMark | ToolMark }) {\n return (\n <Icon\n icon={mark.icon}\n title={mark.label}\n className={cn(\n \"shrink-0\",\n mark.className,\n \"spin\" in mark && mark.spin && \"motion-safe:animate-spin\",\n className,\n )}\n />\n );\n}\n\nexport function OutcomeIcon({ outcome, className }: MarkIconProps & { outcome: TestOutcome }) {\n return <MarkIcon mark={TEST_OUTCOMES[outcome]} className={className} />;\n}\n\nexport function LintSeverityIcon({\n severity,\n className,\n}: MarkIconProps & { severity: LintSeverity }) {\n return <MarkIcon mark={LINT_SEVERITIES[severity]} className={className} />;\n}\n\nexport function ToolIcon({ tool, className }: MarkIconProps & { tool: string | undefined }) {\n const mark = toolMark(tool);\n return mark ? <MarkIcon mark={mark} className={className} /> : null;\n}\n"],"names":[],"mappings":";;;;AAiBA,SAAS,SAAS,EAAE,MAAM,aAA8D;AACtF,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAM,KAAK;AAAA,MACX,OAAO,KAAK;AAAA,MACZ,WAAW;AAAA,QACT;AAAA,QACA,KAAK;AAAA,QACL,UAAU,QAAQ,KAAK,QAAQ;AAAA,QAC/B;AAAA,MAAA;AAAA,IACF;AAAA,EAAA;AAGN;AAEO,SAAS,YAAY,EAAE,SAAS,aAAuD;AAC5F,6BAAQ,UAAA,EAAS,MAAM,cAAc,OAAO,GAAG,WAAsB;AACvE;AAEO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AACF,GAA+C;AAC7C,6BAAQ,UAAA,EAAS,MAAM,gBAAgB,QAAQ,GAAG,WAAsB;AAC1E;AAEO,SAAS,SAAS,EAAE,MAAM,aAA2D;AAC1F,QAAM,OAAO,SAAS,IAAI;AAC1B,SAAO,OAAO,oBAAC,UAAA,EAAS,MAAY,WAAsB,IAAK;AACjE;"}
|
|
@@ -4,24 +4,26 @@ const jsxRuntime = require("react/jsx-runtime");
|
|
|
4
4
|
const react = require("react");
|
|
5
5
|
const Icon = require("../Icon.cjs");
|
|
6
6
|
const button = require("../../components/button.cjs");
|
|
7
|
+
const select = require("../../components/select.cjs");
|
|
8
|
+
const SplitButton = require("../../components/SplitButton.cjs");
|
|
9
|
+
const clipboard = require("../../components/clipboard.cjs");
|
|
10
|
+
const utils = require("../../lib/utils.cjs");
|
|
7
11
|
const JsonView = require("../JsonView.cjs");
|
|
8
12
|
const TabButton = require("../TabButton.cjs");
|
|
9
|
-
const utils = require("../../lib/utils.cjs");
|
|
10
13
|
const context = require("./context.cjs");
|
|
14
|
+
const copy = require("./copy.cjs");
|
|
11
15
|
const status = require("./status.cjs");
|
|
12
|
-
const
|
|
16
|
+
const marks = require("./marks.cjs");
|
|
17
|
+
const MarkIcons = require("./MarkIcons.cjs");
|
|
13
18
|
const TestFailureDetail = require("./TestFailureDetail.cjs");
|
|
14
19
|
const UiClass = require("../../icons/components/UiClass.cjs");
|
|
20
|
+
const UiClock = require("../../icons/components/UiClock.cjs");
|
|
15
21
|
const UiRefresh = require("../../icons/components/UiRefresh.cjs");
|
|
16
22
|
const UiStop = require("../../icons/components/UiStop.cjs");
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
success: "emerald",
|
|
22
|
-
info: "sky",
|
|
23
|
-
neutral: "neutral"
|
|
24
|
-
};
|
|
23
|
+
const UiJson = require("../../icons/components/UiJson.cjs");
|
|
24
|
+
const UiWarningCircle = require("../../icons/components/UiWarningCircle.cjs");
|
|
25
|
+
const UiCheck = require("../../icons/components/UiCheck.cjs");
|
|
26
|
+
const UiCopy = require("../../icons/components/UiCopy.cjs");
|
|
25
27
|
function DefaultDetailBody({ node }) {
|
|
26
28
|
var _a;
|
|
27
29
|
const hasChildren = (((_a = node.children) == null ? void 0 : _a.length) ?? 0) > 0;
|
|
@@ -55,31 +57,78 @@ function DefaultDetailBody({ node }) {
|
|
|
55
57
|
] })
|
|
56
58
|
] });
|
|
57
59
|
}
|
|
58
|
-
function
|
|
60
|
+
function copyMenuItem(item, copy2) {
|
|
61
|
+
const icon = item.icon ? { icon: item.icon } : {};
|
|
62
|
+
if ("reason" in item) {
|
|
63
|
+
return { label: item.label, ...icon, disabled: true, title: item.reason, onSelect: () => {
|
|
64
|
+
} };
|
|
65
|
+
}
|
|
66
|
+
return { label: item.label, ...icon, onSelect: () => copy2(item.value) };
|
|
67
|
+
}
|
|
68
|
+
const COPY_LABEL = { idle: "Copy details", copied: "Copied", error: "Copy failed" };
|
|
69
|
+
const COPY_ICON = { idle: UiCopy.UiCopy, copied: UiCheck.UiCheck, error: UiWarningCircle.UiWarningCircle };
|
|
70
|
+
function CopyDetailsButton({ node }) {
|
|
59
71
|
const runner = context.useTestRunner();
|
|
60
|
-
const
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
const { state, copy: copy$1 } = clipboard.useCopyFlash();
|
|
73
|
+
const sections = react.useMemo(() => runner.adapters.resolveCopy(node, runner), [node, runner]);
|
|
74
|
+
const items = [
|
|
75
|
+
{ label: "Copy as JSON", icon: UiJson.UiJson, onSelect: () => copy$1(copy.buildNodeJson(node)) },
|
|
76
|
+
...sections.items.map((item) => copyMenuItem(item, copy$1))
|
|
77
|
+
];
|
|
78
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
79
|
+
SplitButton.SplitButton,
|
|
80
|
+
{
|
|
81
|
+
label: COPY_LABEL[state],
|
|
82
|
+
icon: COPY_ICON[state],
|
|
83
|
+
variant: "outline",
|
|
84
|
+
size: "sm",
|
|
85
|
+
align: "right",
|
|
86
|
+
title: "More copy options",
|
|
87
|
+
onClick: () => copy$1(copy.buildNodeBrief(node, sections)),
|
|
88
|
+
items
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
function DetailHeader({ node, actionNode, actions, attemptChooser }) {
|
|
93
|
+
const runner = context.useTestRunner();
|
|
94
|
+
const outcome = status.outcomeFor(node);
|
|
95
|
+
const canRerun = !!runner.onRerun && actionNode.framework !== "task";
|
|
96
|
+
const canStop = !!runner.onStop && !!actionNode.can_stop && !!actionNode.task_id;
|
|
97
|
+
const location = node.file ? `${node.file}${node.line ? `:${node.line}` : ""}` : void 0;
|
|
98
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
99
|
+
"div",
|
|
100
|
+
{
|
|
101
|
+
className: "flex min-w-0 items-center gap-2 border-b border-border px-density-4 py-density-2",
|
|
102
|
+
"data-detail-header": "",
|
|
103
|
+
children: [
|
|
104
|
+
outcome ? /* @__PURE__ */ jsxRuntime.jsx(MarkIcons.OutcomeIcon, { outcome, className: "text-lg" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiClass.UiClass, className: "shrink-0 text-lg text-muted-foreground" }),
|
|
105
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "min-w-0 shrink truncate text-base font-semibold", title: node.name, children: node.name }),
|
|
106
|
+
node.framework && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex shrink-0 items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-xs text-muted-foreground", children: [
|
|
107
|
+
/* @__PURE__ */ jsxRuntime.jsx(MarkIcons.ToolIcon, { tool: marks.toolKeyFor(node), className: "text-sm" }),
|
|
108
|
+
node.framework
|
|
109
|
+
] }),
|
|
110
|
+
node.duration ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex shrink-0 items-center gap-1 text-xs text-muted-foreground", children: [
|
|
111
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiClock.UiClock, className: "text-xs" }),
|
|
112
|
+
status.formatTestDuration(node.duration)
|
|
113
|
+
] }) : null,
|
|
114
|
+
location && /* @__PURE__ */ jsxRuntime.jsx(
|
|
115
|
+
"span",
|
|
116
|
+
{
|
|
117
|
+
className: "min-w-0 shrink-[100] truncate font-mono text-xs text-muted-foreground",
|
|
118
|
+
title: location,
|
|
119
|
+
children: location
|
|
120
|
+
}
|
|
121
|
+
),
|
|
122
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-auto flex shrink-0 items-center gap-1", children: [
|
|
123
|
+
attemptChooser,
|
|
76
124
|
actions,
|
|
125
|
+
/* @__PURE__ */ jsxRuntime.jsx(CopyDetailsButton, { node }),
|
|
77
126
|
canRerun && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
78
127
|
button.Button,
|
|
79
128
|
{
|
|
80
129
|
size: "sm",
|
|
81
130
|
disabled: runner.busy.rerun,
|
|
82
|
-
onClick: () => runner.onRerun(
|
|
131
|
+
onClick: () => runner.onRerun(actionNode),
|
|
83
132
|
title: "Rerun this test or subtree",
|
|
84
133
|
children: [
|
|
85
134
|
/* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiRefresh.UiRefresh, className: "mr-1 text-sm" }),
|
|
@@ -93,7 +142,7 @@ function DetailHeader({ node, actions }) {
|
|
|
93
142
|
size: "sm",
|
|
94
143
|
variant: "destructive",
|
|
95
144
|
disabled: runner.busy.stop,
|
|
96
|
-
onClick: () => runner.onStop(
|
|
145
|
+
onClick: () => runner.onStop(actionNode),
|
|
97
146
|
title: "Stop this running task",
|
|
98
147
|
children: [
|
|
99
148
|
/* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiStop.UiStop, className: "mr-1 text-sm" }),
|
|
@@ -102,28 +151,15 @@ function DetailHeader({ node, actions }) {
|
|
|
102
151
|
}
|
|
103
152
|
)
|
|
104
153
|
] })
|
|
105
|
-
]
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: fwIcon, className: "text-sm" }),
|
|
109
|
-
node.framework
|
|
110
|
-
] }),
|
|
111
|
-
node.duration ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
112
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiClock.UiClock, className: "text-xs" }),
|
|
113
|
-
status.formatTestDuration(node.duration)
|
|
114
|
-
] }) : null,
|
|
115
|
-
node.file && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono", children: [
|
|
116
|
-
node.file,
|
|
117
|
-
node.line ? `:${node.line}` : ""
|
|
118
|
-
] })
|
|
119
|
-
] })
|
|
120
|
-
] })
|
|
121
|
-
] });
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
);
|
|
122
157
|
}
|
|
123
158
|
function TestDetailPanel() {
|
|
124
159
|
var _a;
|
|
125
160
|
const runner = context.useTestRunner();
|
|
126
|
-
const
|
|
161
|
+
const selected = runner.selected;
|
|
162
|
+
const [attemptSelection, setAttemptSelection] = react.useState(null);
|
|
127
163
|
const controlled = runner.activeTab !== void 0;
|
|
128
164
|
const [internalTab, setInternalTab] = react.useState("detail");
|
|
129
165
|
const activeTab = controlled ? runner.activeTab : internalTab;
|
|
@@ -132,22 +168,32 @@ function TestDetailPanel() {
|
|
|
132
168
|
if (controlled) (_a2 = runner.onTabChange) == null ? void 0 : _a2.call(runner, id);
|
|
133
169
|
else setInternalTab(id);
|
|
134
170
|
};
|
|
135
|
-
if (!
|
|
171
|
+
if (!selected) {
|
|
136
172
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center text-sm text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
137
173
|
/* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiClass.UiClass, className: "mb-2 block text-4xl" }),
|
|
138
174
|
"Select a test to view its details."
|
|
139
175
|
] }) });
|
|
140
176
|
}
|
|
177
|
+
const attempts = runner.adapters.resolveAttempts(selected, runner);
|
|
178
|
+
const key = selected.task_id ?? selected.name;
|
|
179
|
+
const attemptId = runner.activeAttempt ?? ((attemptSelection == null ? void 0 : attemptSelection.key) === key ? attemptSelection.id : void 0);
|
|
180
|
+
const attempt = attempts.find((a) => a.id === attemptId) ?? attempts.at(-1);
|
|
181
|
+
const node = attempts.length > 1 && attempt ? attempt.node : selected;
|
|
182
|
+
const attemptChooser = attempts.length > 1 && attempt ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-44 shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(select.Select, { "aria-label": "Attempt", value: String(attempt.id), className: "h-7 text-xs", onChange: (event) => {
|
|
183
|
+
const id = Number(event.target.value);
|
|
184
|
+
if (runner.onAttemptChange) runner.onAttemptChange(id);
|
|
185
|
+
else setAttemptSelection({ key, id });
|
|
186
|
+
}, options: attempts.map((a) => ({ value: String(a.id), label: `Attempt ${a.id}/${attempts.length} · ${a.status}${a.durationMs !== void 0 ? ` · ${status.formatTestDuration(a.durationMs * 1e6)}` : ""}` })) }) }) : null;
|
|
141
187
|
const detailAdapter = runner.adapters.resolveDetail(node, runner);
|
|
142
|
-
const actionAdapter = runner.adapters.resolveActions(
|
|
188
|
+
const actionAdapter = runner.adapters.resolveActions(selected, runner);
|
|
143
189
|
const tabs = runner.adapters.resolveTabs(node, runner);
|
|
144
190
|
const ownsScroll = runner.adapters.ownsScroll(node, runner);
|
|
145
191
|
const body = (detailAdapter == null ? void 0 : detailAdapter.renderDetail) ? detailAdapter.renderDetail({ node, runner }) : /* @__PURE__ */ jsxRuntime.jsx(DefaultDetailBody, { node });
|
|
146
|
-
const actions = (_a = actionAdapter == null ? void 0 : actionAdapter.nodeActions) == null ? void 0 : _a.call(actionAdapter, { node, runner });
|
|
147
|
-
const detailRegion =
|
|
192
|
+
const actions = (_a = actionAdapter == null ? void 0 : actionAdapter.nodeActions) == null ? void 0 : _a.call(actionAdapter, { node: selected, runner });
|
|
193
|
+
const detailRegion = utils.cn("min-h-0 flex-1 [container-type:size]", !ownsScroll && "overflow-y-auto");
|
|
148
194
|
if (tabs.length === 0) {
|
|
149
195
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [
|
|
150
|
-
/* @__PURE__ */ jsxRuntime.jsx(DetailHeader, { node, actions }),
|
|
196
|
+
/* @__PURE__ */ jsxRuntime.jsx(DetailHeader, { node, actionNode: selected, actions, attemptChooser }),
|
|
151
197
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: detailRegion, children: body })
|
|
152
198
|
] });
|
|
153
199
|
}
|
|
@@ -155,7 +201,7 @@ function TestDetailPanel() {
|
|
|
155
201
|
const allTabs = [detailTab, ...tabs];
|
|
156
202
|
const active = allTabs.find((t) => t.id === activeTab) ?? detailTab;
|
|
157
203
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [
|
|
158
|
-
/* @__PURE__ */ jsxRuntime.jsx(DetailHeader, { node, actions }),
|
|
204
|
+
/* @__PURE__ */ jsxRuntime.jsx(DetailHeader, { node, actionNode: selected, actions, attemptChooser }),
|
|
159
205
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center gap-1 border-b border-border px-density-2 py-density-1", children: allTabs.map((t) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
160
206
|
TabButton.TabButton,
|
|
161
207
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestDetailPanel.cjs","sources":["../../../src/data/test-runner/TestDetailPanel.tsx"],"sourcesContent":["import { useState, type ReactNode } from \"react\";\nimport { Icon } from \"../Icon\";\nimport { Button } from \"../../components/button\";\nimport { JsonView } from \"../JsonView\";\nimport { TabButton } from \"../TabButton\";\nimport { cn } from \"../../lib/utils\";\nimport { UiClass, UiClock, UiRefresh, UiStop } from \"../../icons\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport { formatTestDuration, statusIconFor, statusToneFor, sum } from \"./status\";\nimport { frameworkIcon } from \"./frameworkIcon\";\nimport { TestAttempts, TestFailureDetail, TestOutput } from \"./TestFailureDetail\";\n\nconst ICON_TONE = {\n danger: \"rose\",\n warning: \"amber\",\n success: \"emerald\",\n info: \"sky\",\n neutral: \"neutral\",\n} as const;\n\n/** Built-in detail body — used when no adapter contributes `renderDetail`. */\nfunction DefaultDetailBody({ node }: { node: Test }) {\n const hasChildren = (node.children?.length ?? 0) > 0;\n const counts = hasChildren ? sum(node) : null;\n return (\n <div className=\"space-y-4 p-density-4\">\n {node.message && !node.failure_detail && (\n <p className=\"whitespace-pre-wrap break-words text-sm\">{node.message}</p>\n )}\n {node.failure_detail && <TestFailureDetail failure={node.failure_detail} />}\n <TestOutput node={node} />\n {node.attempts && node.attempts.length > 0 && <TestAttempts attempts={node.attempts} />}\n {counts && counts.total > 0 && (\n <div className=\"flex flex-wrap gap-3 text-xs text-muted-foreground\">\n <span>{counts.total} total</span>\n {counts.passed > 0 && <span>{counts.passed} passed</span>}\n {counts.failed > 0 && <span>{counts.failed} failed</span>}\n {counts.skipped > 0 && <span>{counts.skipped} skipped</span>}\n </div>\n )}\n {node.detail != null && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">Detail</div>\n <JsonView data={node.detail} />\n </div>\n )}\n </div>\n );\n}\n\nfunction DetailHeader({ node, actions }: { node: Test; actions?: ReactNode }) {\n const runner = useTestRunner();\n const fwIcon = frameworkIcon(node.framework);\n const canRerun = !!runner.onRerun && node.framework !== \"task\";\n const canStop = !!runner.onStop && !!node.can_stop && !!node.task_id;\n return (\n <div className=\"flex items-start gap-2 border-b border-border p-density-4\">\n <Icon\n icon={statusIconFor(node)}\n className={cn(\"mt-0.5 shrink-0 text-2xl\", node.running && \"animate-spin\")}\n tone={ICON_TONE[statusToneFor(node)]}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-start justify-between gap-2\">\n <h2 className=\"break-words text-base font-semibold\">{node.name}</h2>\n <div className=\"flex shrink-0 items-center gap-1\">\n {actions}\n {canRerun && (\n <Button\n size=\"sm\"\n disabled={runner.busy.rerun}\n onClick={() => runner.onRerun!(node)}\n title=\"Rerun this test or subtree\"\n >\n <Icon icon={UiRefresh} className=\"mr-1 text-sm\" />\n {runner.busy.rerun ? \"Running...\" : \"Rerun\"}\n </Button>\n )}\n {canStop && (\n <Button\n size=\"sm\"\n variant=\"destructive\"\n disabled={runner.busy.stop}\n onClick={() => runner.onStop!(node)}\n title=\"Stop this running task\"\n >\n <Icon icon={UiStop} className=\"mr-1 text-sm\" />\n {runner.busy.stop ? \"Stopping...\" : \"Stop\"}\n </Button>\n )}\n </div>\n </div>\n <div className=\"mt-1 flex flex-wrap items-center gap-2 text-xs text-muted-foreground\">\n {fwIcon && (\n <span className=\"inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5\">\n <Icon icon={fwIcon} className=\"text-sm\" />\n {node.framework}\n </span>\n )}\n {node.duration ? (\n <span className=\"inline-flex items-center gap-1\">\n <Icon icon={UiClock} className=\"text-xs\" />\n {formatTestDuration(node.duration)}\n </span>\n ) : null}\n {node.file && (\n <span className=\"font-mono\">\n {node.file}\n {node.line ? `:${node.line}` : \"\"}\n </span>\n )}\n </div>\n </div>\n </div>\n );\n}\n\n/**\n * The right pane. Resolves the node's adapter for body / tabs / header actions,\n * falling back to the built-in default body. Shows an empty state when nothing\n * is selected.\n */\nexport function TestDetailPanel() {\n const runner = useTestRunner();\n const node = runner.selected;\n // Tab state is controlled when the host supplies activeTab (e.g. to mirror it\n // into the URL); otherwise the panel owns it. The render below tolerates an\n // unknown id by falling back to the built-in \"detail\" tab.\n const controlled = runner.activeTab !== undefined;\n const [internalTab, setInternalTab] = useState<string>(\"detail\");\n const activeTab = controlled ? runner.activeTab! : internalTab;\n const setActiveTab = (id: string) => {\n if (controlled) runner.onTabChange?.(id);\n else setInternalTab(id);\n };\n\n if (!node) {\n return (\n <div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n <div className=\"text-center\">\n <Icon icon={UiClass} className=\"mb-2 block text-4xl\" />\n Select a test to view its details.\n </div>\n </div>\n );\n }\n\n const detailAdapter = runner.adapters.resolveDetail(node, runner);\n const actionAdapter = runner.adapters.resolveActions(node, runner);\n const tabs = runner.adapters.resolveTabs(node, runner);\n const ownsScroll = runner.adapters.ownsScroll(node, runner);\n\n const body = detailAdapter?.renderDetail\n ? detailAdapter.renderDetail({ node, runner })\n : <DefaultDetailBody node={node} />;\n const actions = actionAdapter?.nodeActions?.({ node, runner });\n\n const detailRegion = ownsScroll ? \"min-h-0 flex-1\" : \"min-h-0 flex-1 overflow-y-auto\";\n\n // No extra tabs → just the body under the header.\n if (tabs.length === 0) {\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <DetailHeader node={node} actions={actions} />\n <div className={detailRegion}>{body}</div>\n </div>\n );\n }\n\n const detailTab = { id: \"detail\", label: \"Detail\", render: () => body };\n const allTabs = [detailTab, ...tabs];\n const active = allTabs.find((t) => t.id === activeTab) ?? detailTab;\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <DetailHeader node={node} actions={actions} />\n <div className=\"flex shrink-0 items-center gap-1 border-b border-border px-density-2 py-density-1\">\n {allTabs.map((t) => (\n <TabButton\n key={t.id}\n active={active.id === t.id}\n onClick={() => setActiveTab(t.id)}\n label={t.label}\n />\n ))}\n </div>\n <div className={detailRegion}>{active.render()}</div>\n </div>\n );\n}\n"],"names":["sum","jsxs","jsx","TestFailureDetail","TestOutput","TestAttempts","JsonView","useTestRunner","frameworkIcon","Icon","statusIconFor","cn","statusToneFor","Button","UiRefresh","UiStop","UiClock","formatTestDuration","useState","_a","UiClass","TabButton"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TestDetailPanel.cjs","sources":["../../../src/data/test-runner/TestDetailPanel.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport { Icon } from \"../Icon\";\nimport { Button } from \"../../components/button\";\nimport { Select } from \"../../components/select\";\nimport { SplitButton } from \"../../components/SplitButton\";\nimport { useCopyFlash } from \"../../components/clipboard\";\nimport type { DropdownMenuItem } from \"../../overlay/DropdownMenu\";\nimport { cn } from \"../../lib/utils\";\nimport { JsonView } from \"../JsonView\";\nimport { TabButton } from \"../TabButton\";\nimport {\n UiCheck,\n UiClass,\n UiClock,\n UiCopy,\n UiJson,\n UiRefresh,\n UiStop,\n UiWarningCircle,\n} from \"../../icons\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport { buildNodeBrief, buildNodeJson, type CopyItem } from \"./copy\";\nimport { formatTestDuration, outcomeFor, sum } from \"./status\";\nimport { toolKeyFor } from \"./marks\";\nimport { OutcomeIcon, ToolIcon } from \"./MarkIcons\";\nimport { TestAttempts, TestFailureDetail, TestOutput } from \"./TestFailureDetail\";\n\n/** Built-in detail body — used when no adapter contributes `renderDetail`. */\nfunction DefaultDetailBody({ node }: { node: Test }) {\n const hasChildren = (node.children?.length ?? 0) > 0;\n const counts = hasChildren ? sum(node) : null;\n return (\n <div className=\"space-y-4 p-density-4\">\n {node.message && !node.failure_detail && (\n <p className=\"whitespace-pre-wrap break-words text-sm\">{node.message}</p>\n )}\n {node.failure_detail && <TestFailureDetail failure={node.failure_detail} />}\n <TestOutput node={node} />\n {node.attempts && node.attempts.length > 0 && <TestAttempts attempts={node.attempts} />}\n {counts && counts.total > 0 && (\n <div className=\"flex flex-wrap gap-3 text-xs text-muted-foreground\">\n <span>{counts.total} total</span>\n {counts.passed > 0 && <span>{counts.passed} passed</span>}\n {counts.failed > 0 && <span>{counts.failed} failed</span>}\n {counts.skipped > 0 && <span>{counts.skipped} skipped</span>}\n </div>\n )}\n {node.detail != null && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">Detail</div>\n <JsonView data={node.detail} />\n </div>\n )}\n </div>\n );\n}\n\nfunction copyMenuItem(item: CopyItem, copy: (text: string) => void): DropdownMenuItem {\n const icon = item.icon ? { icon: item.icon } : {};\n if (\"reason\" in item) {\n return { label: item.label, ...icon, disabled: true, title: item.reason, onSelect: () => {} };\n }\n return { label: item.label, ...icon, onSelect: () => copy(item.value) };\n}\n\nconst COPY_LABEL = { idle: \"Copy details\", copied: \"Copied\", error: \"Copy failed\" } as const;\nconst COPY_ICON = { idle: UiCopy, copied: UiCheck, error: UiWarningCircle } as const;\n\n/**\n * \"Copy details\" split button: the primary action copies a Markdown brief of\n * the generic sections plus every matching adapter's `copy` sections; the menu\n * offers the node as JSON and the adapters' items, disabled with a reason when\n * they have nothing to copy. The label flips to \"Copied\" or \"Copy failed\".\n */\nfunction CopyDetailsButton({ node }: { node: Test }) {\n const runner = useTestRunner();\n const { state, copy } = useCopyFlash();\n const sections = useMemo(() => runner.adapters.resolveCopy(node, runner), [node, runner]);\n const items: DropdownMenuItem[] = [\n { label: \"Copy as JSON\", icon: UiJson, onSelect: () => copy(buildNodeJson(node)) },\n ...sections.items.map((item) => copyMenuItem(item, copy)),\n ];\n return (\n <SplitButton\n label={COPY_LABEL[state]}\n icon={COPY_ICON[state]}\n variant=\"outline\"\n size=\"sm\"\n align=\"right\"\n title=\"More copy options\"\n onClick={() => copy(buildNodeBrief(node, sections))}\n items={items}\n />\n );\n}\n\nfunction DetailHeader({ node, actionNode, actions, attemptChooser }: { node: Test; actionNode: Test; actions?: ReactNode; attemptChooser?: ReactNode }) {\n const runner = useTestRunner();\n const outcome = outcomeFor(node);\n const canRerun = !!runner.onRerun && actionNode.framework !== \"task\";\n const canStop = !!runner.onStop && !!actionNode.can_stop && !!actionNode.task_id;\n const location = node.file ? `${node.file}${node.line ? `:${node.line}` : \"\"}` : undefined;\n return (\n <div\n className=\"flex min-w-0 items-center gap-2 border-b border-border px-density-4 py-density-2\"\n data-detail-header=\"\"\n >\n {outcome ? (\n <OutcomeIcon outcome={outcome} className=\"text-lg\" />\n ) : (\n <Icon icon={UiClass} className=\"shrink-0 text-lg text-muted-foreground\" />\n )}\n <h2 className=\"min-w-0 shrink truncate text-base font-semibold\" title={node.name}>\n {node.name}\n </h2>\n {node.framework && (\n <span className=\"inline-flex shrink-0 items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-xs text-muted-foreground\">\n <ToolIcon tool={toolKeyFor(node)} className=\"text-sm\" />\n {node.framework}\n </span>\n )}\n {node.duration ? (\n <span className=\"inline-flex shrink-0 items-center gap-1 text-xs text-muted-foreground\">\n <Icon icon={UiClock} className=\"text-xs\" />\n {formatTestDuration(node.duration)}\n </span>\n ) : null}\n {location && (\n <span\n className=\"min-w-0 shrink-[100] truncate font-mono text-xs text-muted-foreground\"\n title={location}\n >\n {location}\n </span>\n )}\n <div className=\"ml-auto flex shrink-0 items-center gap-1\">\n {attemptChooser}\n {actions}\n <CopyDetailsButton node={node} />\n {canRerun && (\n <Button\n size=\"sm\"\n disabled={runner.busy.rerun}\n onClick={() => runner.onRerun!(actionNode)}\n title=\"Rerun this test or subtree\"\n >\n <Icon icon={UiRefresh} className=\"mr-1 text-sm\" />\n {runner.busy.rerun ? \"Running...\" : \"Rerun\"}\n </Button>\n )}\n {canStop && (\n <Button\n size=\"sm\"\n variant=\"destructive\"\n disabled={runner.busy.stop}\n onClick={() => runner.onStop!(actionNode)}\n title=\"Stop this running task\"\n >\n <Icon icon={UiStop} className=\"mr-1 text-sm\" />\n {runner.busy.stop ? \"Stopping...\" : \"Stop\"}\n </Button>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * The right pane. Resolves the node's adapter for body / tabs / header actions,\n * falling back to the built-in default body. Shows an empty state when nothing\n * is selected.\n */\nexport function TestDetailPanel() {\n const runner = useTestRunner();\n const selected = runner.selected;\n const [attemptSelection, setAttemptSelection] = useState<{ key: string; id: number } | null>(null);\n // Tab state is controlled when the host supplies activeTab (e.g. to mirror it\n // into the URL); otherwise the panel owns it. The render below tolerates an\n // unknown id by falling back to the built-in \"detail\" tab.\n const controlled = runner.activeTab !== undefined;\n const [internalTab, setInternalTab] = useState<string>(\"detail\");\n const activeTab = controlled ? runner.activeTab! : internalTab;\n const setActiveTab = (id: string) => {\n if (controlled) runner.onTabChange?.(id);\n else setInternalTab(id);\n };\n\n if (!selected) {\n return (\n <div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n <div className=\"text-center\">\n <Icon icon={UiClass} className=\"mb-2 block text-4xl\" />\n Select a test to view its details.\n </div>\n </div>\n );\n }\n\n const attempts = runner.adapters.resolveAttempts(selected, runner);\n const key = selected.task_id ?? selected.name;\n const attemptId = runner.activeAttempt ?? (attemptSelection?.key === key ? attemptSelection.id : undefined);\n const attempt = attempts.find((a) => a.id === attemptId) ?? attempts.at(-1);\n const node = attempts.length > 1 && attempt ? attempt.node : selected;\n const attemptChooser = attempts.length > 1 && attempt ? (\n <div className=\"w-44 shrink-0\">\n <Select aria-label=\"Attempt\" value={String(attempt.id)} className=\"h-7 text-xs\" onChange={(event) => {\n const id = Number(event.target.value);\n if (runner.onAttemptChange) runner.onAttemptChange(id);\n else setAttemptSelection({ key, id });\n }} options={attempts.map((a) => ({ value: String(a.id), label: `Attempt ${a.id}/${attempts.length} · ${a.status}${a.durationMs !== undefined ? ` · ${formatTestDuration(a.durationMs * 1e6)}` : \"\"}` }))} />\n </div>\n ) : null;\n\n const detailAdapter = runner.adapters.resolveDetail(node, runner);\n const actionAdapter = runner.adapters.resolveActions(selected, runner);\n const tabs = runner.adapters.resolveTabs(node, runner);\n const ownsScroll = runner.adapters.ownsScroll(node, runner);\n\n const body = detailAdapter?.renderDetail\n ? detailAdapter.renderDetail({ node, runner })\n : <DefaultDetailBody node={node} />;\n const actions = actionAdapter?.nodeActions?.({ node: selected, runner });\n\n // A size container, so log blocks can cap themselves at a share of the pane (cqh).\n const detailRegion = cn(\"min-h-0 flex-1 [container-type:size]\", !ownsScroll && \"overflow-y-auto\");\n\n // No extra tabs → just the body under the header.\n if (tabs.length === 0) {\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <DetailHeader node={node} actionNode={selected} actions={actions} attemptChooser={attemptChooser} />\n <div className={detailRegion}>{body}</div>\n </div>\n );\n }\n\n const detailTab = { id: \"detail\", label: \"Detail\", render: () => body };\n const allTabs = [detailTab, ...tabs];\n const active = allTabs.find((t) => t.id === activeTab) ?? detailTab;\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <DetailHeader node={node} actionNode={selected} actions={actions} attemptChooser={attemptChooser} />\n <div className=\"flex shrink-0 items-center gap-1 border-b border-border px-density-2 py-density-1\">\n {allTabs.map((t) => (\n <TabButton\n key={t.id}\n active={active.id === t.id}\n onClick={() => setActiveTab(t.id)}\n label={t.label}\n />\n ))}\n </div>\n <div className={detailRegion}>{active.render()}</div>\n </div>\n );\n}\n"],"names":["sum","jsxs","jsx","TestFailureDetail","TestOutput","TestAttempts","JsonView","copy","UiCopy","UiCheck","UiWarningCircle","useTestRunner","useCopyFlash","useMemo","UiJson","buildNodeJson","SplitButton","buildNodeBrief","outcomeFor","OutcomeIcon","Icon","UiClass","ToolIcon","toolKeyFor","UiClock","formatTestDuration","Button","UiRefresh","UiStop","useState","_a","Select","cn","TabButton"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,SAAS,kBAAkB,EAAE,QAAwB;;AACnD,QAAM,iBAAe,UAAK,aAAL,mBAAe,WAAU,KAAK;AACnD,QAAM,SAAS,cAAcA,WAAI,IAAI,IAAI;AACzC,SACEC,2BAAAA,KAAC,OAAA,EAAI,WAAU,yBACZ,UAAA;AAAA,IAAA,KAAK,WAAW,CAAC,KAAK,iDACpB,KAAA,EAAE,WAAU,2CAA2C,UAAA,KAAK,QAAA,CAAQ;AAAA,IAEtE,KAAK,kBAAkBC,+BAACC,kBAAAA,mBAAA,EAAkB,SAAS,KAAK,gBAAgB;AAAA,IACzED,+BAACE,kBAAAA,cAAW,MAAY;AAAA,IACvB,KAAK,YAAY,KAAK,SAAS,SAAS,KAAKF,2BAAAA,IAACG,kBAAAA,cAAA,EAAa,UAAU,KAAK,SAAA,CAAU;AAAA,IACpF,UAAU,OAAO,QAAQ,KACxBJ,2BAAAA,KAAC,OAAA,EAAI,WAAU,sDACb,UAAA;AAAA,MAAAA,gCAAC,QAAA,EAAM,UAAA;AAAA,QAAA,OAAO;AAAA,QAAM;AAAA,MAAA,GAAM;AAAA,MACzB,OAAO,SAAS,KAAKA,2BAAAA,KAAC,QAAA,EAAM,UAAA;AAAA,QAAA,OAAO;AAAA,QAAO;AAAA,MAAA,GAAO;AAAA,MACjD,OAAO,SAAS,KAAKA,2BAAAA,KAAC,QAAA,EAAM,UAAA;AAAA,QAAA,OAAO;AAAA,QAAO;AAAA,MAAA,GAAO;AAAA,MACjD,OAAO,UAAU,KAAKA,2BAAAA,KAAC,QAAA,EAAM,UAAA;AAAA,QAAA,OAAO;AAAA,QAAQ;AAAA,MAAA,EAAA,CAAQ;AAAA,IAAA,GACvD;AAAA,IAED,KAAK,UAAU,QACdA,2BAAAA,KAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,MAAAC,2BAAAA,IAAC,OAAA,EAAI,WAAU,6DAA4D,UAAA,UAAM;AAAA,MACjFA,2BAAAA,IAACI,SAAAA,UAAA,EAAS,MAAM,KAAK,OAAA,CAAQ;AAAA,IAAA,EAAA,CAC/B;AAAA,EAAA,GAEJ;AAEJ;AAEA,SAAS,aAAa,MAAgBC,OAAgD;AACpF,QAAM,OAAO,KAAK,OAAO,EAAE,MAAM,KAAK,KAAA,IAAS,CAAA;AAC/C,MAAI,YAAY,MAAM;AACpB,WAAO,EAAE,OAAO,KAAK,OAAO,GAAG,MAAM,UAAU,MAAM,OAAO,KAAK,QAAQ,UAAU,MAAM;AAAA,IAAC,EAAA;AAAA,EAC5F;AACA,SAAO,EAAE,OAAO,KAAK,OAAO,GAAG,MAAM,UAAU,MAAMA,MAAK,KAAK,KAAK,EAAA;AACtE;AAEA,MAAM,aAAa,EAAE,MAAM,gBAAgB,QAAQ,UAAU,OAAO,cAAA;AACpE,MAAM,YAAY,EAAE,MAAMC,OAAAA,QAAQ,QAAQC,QAAAA,SAAS,OAAOC,gCAAA;AAQ1D,SAAS,kBAAkB,EAAE,QAAwB;AACnD,QAAM,SAASC,QAAAA,cAAA;AACf,QAAM,EAAE,OAAA,MAAOJ,OAAA,IAASK,uBAAA;AACxB,QAAM,WAAWC,MAAAA,QAAQ,MAAM,OAAO,SAAS,YAAY,MAAM,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC;AACxF,QAAM,QAA4B;AAAA,IAChC,EAAE,OAAO,gBAAgB,MAAMC,OAAAA,QAAQ,UAAU,MAAMP,OAAKQ,KAAAA,cAAc,IAAI,CAAC,EAAA;AAAA,IAC/E,GAAG,SAAS,MAAM,IAAI,CAAC,SAAS,aAAa,MAAMR,MAAI,CAAC;AAAA,EAAA;AAE1D,SACEL,2BAAAA;AAAAA,IAACc,YAAAA;AAAAA,IAAA;AAAA,MACC,OAAO,WAAW,KAAK;AAAA,MACvB,MAAM,UAAU,KAAK;AAAA,MACrB,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,OAAM;AAAA,MACN,OAAM;AAAA,MACN,SAAS,MAAMT,OAAKU,KAAAA,eAAe,MAAM,QAAQ,CAAC;AAAA,MAClD;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,SAAS,aAAa,EAAE,MAAM,YAAY,SAAS,kBAAqG;AACtJ,QAAM,SAASN,QAAAA,cAAA;AACf,QAAM,UAAUO,OAAAA,WAAW,IAAI;AAC/B,QAAM,WAAW,CAAC,CAAC,OAAO,WAAW,WAAW,cAAc;AAC9D,QAAM,UAAU,CAAC,CAAC,OAAO,UAAU,CAAC,CAAC,WAAW,YAAY,CAAC,CAAC,WAAW;AACzE,QAAM,WAAW,KAAK,OAAO,GAAG,KAAK,IAAI,GAAG,KAAK,OAAO,IAAI,KAAK,IAAI,KAAK,EAAE,KAAK;AACjF,SACEjB,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,sBAAmB;AAAA,MAElB,UAAA;AAAA,QAAA,UACCC,2BAAAA,IAACiB,UAAAA,aAAA,EAAY,SAAkB,WAAU,UAAA,CAAU,IAEnDjB,2BAAAA,IAACkB,KAAAA,MAAA,EAAK,MAAMC,QAAAA,SAAS,WAAU,yCAAA,CAAyC;AAAA,QAE1EnB,2BAAAA,IAAC,QAAG,WAAU,mDAAkD,OAAO,KAAK,MACzE,eAAK,KAAA,CACR;AAAA,QACC,KAAK,aACJD,gCAAC,QAAA,EAAK,WAAU,wGACd,UAAA;AAAA,UAAAC,+BAACoB,UAAAA,YAAS,MAAMC,MAAAA,WAAW,IAAI,GAAG,WAAU,WAAU;AAAA,UACrD,KAAK;AAAA,QAAA,GACR;AAAA,QAED,KAAK,WACJtB,gCAAC,QAAA,EAAK,WAAU,yEACd,UAAA;AAAA,UAAAC,2BAAAA,IAACkB,KAAAA,MAAA,EAAK,MAAMI,QAAAA,SAAS,WAAU,WAAU;AAAA,UACxCC,OAAAA,mBAAmB,KAAK,QAAQ;AAAA,QAAA,EAAA,CACnC,IACE;AAAA,QACH,YACCvB,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO;AAAA,YAEN,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAGLD,2BAAAA,KAAC,OAAA,EAAI,WAAU,4CACZ,UAAA;AAAA,UAAA;AAAA,UACA;AAAA,UACDC,+BAAC,qBAAkB,MAAY;AAAA,UAC9B,YACCD,2BAAAA;AAAAA,YAACyB,OAAAA;AAAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,UAAU,OAAO,KAAK;AAAA,cACtB,SAAS,MAAM,OAAO,QAAS,UAAU;AAAA,cACzC,OAAM;AAAA,cAEN,UAAA;AAAA,gBAAAxB,2BAAAA,IAACkB,KAAAA,MAAA,EAAK,MAAMO,UAAAA,WAAW,WAAU,gBAAe;AAAA,gBAC/C,OAAO,KAAK,QAAQ,eAAe;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGvC,WACC1B,2BAAAA;AAAAA,YAACyB,OAAAA;AAAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,UAAU,OAAO,KAAK;AAAA,cACtB,SAAS,MAAM,OAAO,OAAQ,UAAU;AAAA,cACxC,OAAM;AAAA,cAEN,UAAA;AAAA,gBAAAxB,2BAAAA,IAACkB,KAAAA,MAAA,EAAK,MAAMQ,OAAAA,QAAQ,WAAU,gBAAe;AAAA,gBAC5C,OAAO,KAAK,OAAO,gBAAgB;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACtC,EAAA,CAEJ;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AAOO,SAAS,kBAAkB;;AAChC,QAAM,SAASjB,QAAAA,cAAA;AACf,QAAM,WAAW,OAAO;AACxB,QAAM,CAAC,kBAAkB,mBAAmB,IAAIkB,MAAAA,SAA6C,IAAI;AAIjG,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,CAAC,aAAa,cAAc,IAAIA,MAAAA,SAAiB,QAAQ;AAC/D,QAAM,YAAY,aAAa,OAAO,YAAa;AACnD,QAAM,eAAe,CAAC,OAAe;;AACnC,QAAI,WAAY,EAAAC,MAAA,OAAO,gBAAP,gBAAAA,IAAA,aAAqB;AAAA,wBACjB,EAAE;AAAA,EACxB;AAEA,MAAI,CAAC,UAAU;AACb,0CACG,OAAA,EAAI,WAAU,yEACb,UAAA7B,2BAAAA,KAAC,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,MAAAC,2BAAAA,IAACkB,KAAAA,MAAA,EAAK,MAAMC,QAAAA,SAAS,WAAU,uBAAsB;AAAA,MAAE;AAAA,IAAA,EAAA,CAEzD,EAAA,CACF;AAAA,EAEJ;AAEA,QAAM,WAAW,OAAO,SAAS,gBAAgB,UAAU,MAAM;AACjE,QAAM,MAAM,SAAS,WAAW,SAAS;AACzC,QAAM,YAAY,OAAO,mBAAkB,qDAAkB,SAAQ,MAAM,iBAAiB,KAAK;AACjG,QAAM,UAAU,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS,KAAK,SAAS,GAAG,EAAE;AAC1E,QAAM,OAAO,SAAS,SAAS,KAAK,UAAU,QAAQ,OAAO;AAC7D,QAAM,iBAAiB,SAAS,SAAS,KAAK,UAC5CnB,+BAAC,OAAA,EAAI,WAAU,iBACb,UAAAA,2BAAAA,IAAC6B,eAAA,EAAO,cAAW,WAAU,OAAO,OAAO,QAAQ,EAAE,GAAG,WAAU,eAAc,UAAU,CAAC,UAAU;AACnG,UAAM,KAAK,OAAO,MAAM,OAAO,KAAK;AACpC,QAAI,OAAO,gBAAiB,QAAO,gBAAgB,EAAE;AAAA,QAChD,qBAAoB,EAAE,KAAK,IAAI;AAAA,EACtC,GAAG,SAAS,SAAS,IAAI,CAAC,OAAO,EAAE,OAAO,OAAO,EAAE,EAAE,GAAG,OAAO,WAAW,EAAE,EAAE,IAAI,SAAS,MAAM,MAAM,EAAE,MAAM,GAAG,EAAE,eAAe,SAAY,MAAMN,OAAAA,mBAAmB,EAAE,aAAa,GAAG,CAAC,KAAK,EAAE,KAAK,EAAA,CAAG,GAC5M,IACE;AAEJ,QAAM,gBAAgB,OAAO,SAAS,cAAc,MAAM,MAAM;AAChE,QAAM,gBAAgB,OAAO,SAAS,eAAe,UAAU,MAAM;AACrE,QAAM,OAAO,OAAO,SAAS,YAAY,MAAM,MAAM;AACrD,QAAM,aAAa,OAAO,SAAS,WAAW,MAAM,MAAM;AAE1D,QAAM,QAAO,+CAAe,gBACxB,cAAc,aAAa,EAAE,MAAM,OAAA,CAAQ,IAC3CvB,2BAAAA,IAAC,mBAAA,EAAkB,KAAA,CAAY;AACnC,QAAM,WAAU,oDAAe,gBAAf,uCAA6B,EAAE,MAAM,UAAU;AAG/D,QAAM,eAAe8B,MAAAA,GAAG,wCAAwC,CAAC,cAAc,iBAAiB;AAGhG,MAAI,KAAK,WAAW,GAAG;AACrB,WACE/B,2BAAAA,KAAC,OAAA,EAAI,WAAU,gCACb,UAAA;AAAA,MAAAC,2BAAAA,IAAC,cAAA,EAAa,MAAY,YAAY,UAAU,SAAkB,gBAAgC;AAAA,MAClGA,2BAAAA,IAAC,OAAA,EAAI,WAAW,cAAe,UAAA,KAAA,CAAK;AAAA,IAAA,GACtC;AAAA,EAEJ;AAEA,QAAM,YAAY,EAAE,IAAI,UAAU,OAAO,UAAU,QAAQ,MAAM,KAAA;AACjE,QAAM,UAAU,CAAC,WAAW,GAAG,IAAI;AACnC,QAAM,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS,KAAK;AAE1D,SACED,2BAAAA,KAAC,OAAA,EAAI,WAAU,gCACb,UAAA;AAAA,IAAAC,2BAAAA,IAAC,cAAA,EAAa,MAAY,YAAY,UAAU,SAAkB,gBAAgC;AAAA,mCACjG,OAAA,EAAI,WAAU,qFACZ,UAAA,QAAQ,IAAI,CAAC,MACZA,2BAAAA;AAAAA,MAAC+B,UAAAA;AAAAA,MAAA;AAAA,QAEC,QAAQ,OAAO,OAAO,EAAE;AAAA,QACxB,SAAS,MAAM,aAAa,EAAE,EAAE;AAAA,QAChC,OAAO,EAAE;AAAA,MAAA;AAAA,MAHJ,EAAE;AAAA,IAAA,CAKV,GACH;AAAA,mCACC,OAAA,EAAI,WAAW,cAAe,UAAA,OAAO,SAAO,CAAE;AAAA,EAAA,GACjD;AAEJ;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestDetailPanel.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/TestDetailPanel.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TestDetailPanel.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/TestDetailPanel.tsx"],"names":[],"mappings":"AAwKA;;;;GAIG;AACH,wBAAgB,eAAe,gCAoF9B"}
|
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from "react";
|
|
2
|
+
import { useState, useMemo } from "react";
|
|
3
3
|
import { Icon } from "../Icon.js";
|
|
4
4
|
import { Button } from "../../components/button.js";
|
|
5
|
+
import { Select } from "../../components/select.js";
|
|
6
|
+
import { SplitButton } from "../../components/SplitButton.js";
|
|
7
|
+
import { useCopyFlash } from "../../components/clipboard.js";
|
|
8
|
+
import { cn } from "../../lib/utils.js";
|
|
5
9
|
import { JsonView } from "../JsonView.js";
|
|
6
10
|
import { TabButton } from "../TabButton.js";
|
|
7
|
-
import { cn } from "../../lib/utils.js";
|
|
8
11
|
import { useTestRunner } from "./context.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
12
|
+
import { buildNodeJson, buildNodeBrief } from "./copy.js";
|
|
13
|
+
import { formatTestDuration, sum, outcomeFor } from "./status.js";
|
|
14
|
+
import { toolKeyFor } from "./marks.js";
|
|
15
|
+
import { OutcomeIcon, ToolIcon } from "./MarkIcons.js";
|
|
11
16
|
import { TestFailureDetail, TestOutput, TestAttempts } from "./TestFailureDetail.js";
|
|
12
17
|
import { UiClass } from "../../icons/components/UiClass.js";
|
|
18
|
+
import { UiClock } from "../../icons/components/UiClock.js";
|
|
13
19
|
import { UiRefresh } from "../../icons/components/UiRefresh.js";
|
|
14
20
|
import { UiStop } from "../../icons/components/UiStop.js";
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
success: "emerald",
|
|
20
|
-
info: "sky",
|
|
21
|
-
neutral: "neutral"
|
|
22
|
-
};
|
|
21
|
+
import { UiJson } from "../../icons/components/UiJson.js";
|
|
22
|
+
import { UiWarningCircle } from "../../icons/components/UiWarningCircle.js";
|
|
23
|
+
import { UiCheck } from "../../icons/components/UiCheck.js";
|
|
24
|
+
import { UiCopy } from "../../icons/components/UiCopy.js";
|
|
23
25
|
function DefaultDetailBody({ node }) {
|
|
24
26
|
var _a;
|
|
25
27
|
const hasChildren = (((_a = node.children) == null ? void 0 : _a.length) ?? 0) > 0;
|
|
@@ -53,31 +55,78 @@ function DefaultDetailBody({ node }) {
|
|
|
53
55
|
] })
|
|
54
56
|
] });
|
|
55
57
|
}
|
|
56
|
-
function
|
|
58
|
+
function copyMenuItem(item, copy) {
|
|
59
|
+
const icon = item.icon ? { icon: item.icon } : {};
|
|
60
|
+
if ("reason" in item) {
|
|
61
|
+
return { label: item.label, ...icon, disabled: true, title: item.reason, onSelect: () => {
|
|
62
|
+
} };
|
|
63
|
+
}
|
|
64
|
+
return { label: item.label, ...icon, onSelect: () => copy(item.value) };
|
|
65
|
+
}
|
|
66
|
+
const COPY_LABEL = { idle: "Copy details", copied: "Copied", error: "Copy failed" };
|
|
67
|
+
const COPY_ICON = { idle: UiCopy, copied: UiCheck, error: UiWarningCircle };
|
|
68
|
+
function CopyDetailsButton({ node }) {
|
|
57
69
|
const runner = useTestRunner();
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
const { state, copy } = useCopyFlash();
|
|
71
|
+
const sections = useMemo(() => runner.adapters.resolveCopy(node, runner), [node, runner]);
|
|
72
|
+
const items = [
|
|
73
|
+
{ label: "Copy as JSON", icon: UiJson, onSelect: () => copy(buildNodeJson(node)) },
|
|
74
|
+
...sections.items.map((item) => copyMenuItem(item, copy))
|
|
75
|
+
];
|
|
76
|
+
return /* @__PURE__ */ jsx(
|
|
77
|
+
SplitButton,
|
|
78
|
+
{
|
|
79
|
+
label: COPY_LABEL[state],
|
|
80
|
+
icon: COPY_ICON[state],
|
|
81
|
+
variant: "outline",
|
|
82
|
+
size: "sm",
|
|
83
|
+
align: "right",
|
|
84
|
+
title: "More copy options",
|
|
85
|
+
onClick: () => copy(buildNodeBrief(node, sections)),
|
|
86
|
+
items
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
function DetailHeader({ node, actionNode, actions, attemptChooser }) {
|
|
91
|
+
const runner = useTestRunner();
|
|
92
|
+
const outcome = outcomeFor(node);
|
|
93
|
+
const canRerun = !!runner.onRerun && actionNode.framework !== "task";
|
|
94
|
+
const canStop = !!runner.onStop && !!actionNode.can_stop && !!actionNode.task_id;
|
|
95
|
+
const location = node.file ? `${node.file}${node.line ? `:${node.line}` : ""}` : void 0;
|
|
96
|
+
return /* @__PURE__ */ jsxs(
|
|
97
|
+
"div",
|
|
98
|
+
{
|
|
99
|
+
className: "flex min-w-0 items-center gap-2 border-b border-border px-density-4 py-density-2",
|
|
100
|
+
"data-detail-header": "",
|
|
101
|
+
children: [
|
|
102
|
+
outcome ? /* @__PURE__ */ jsx(OutcomeIcon, { outcome, className: "text-lg" }) : /* @__PURE__ */ jsx(Icon, { icon: UiClass, className: "shrink-0 text-lg text-muted-foreground" }),
|
|
103
|
+
/* @__PURE__ */ jsx("h2", { className: "min-w-0 shrink truncate text-base font-semibold", title: node.name, children: node.name }),
|
|
104
|
+
node.framework && /* @__PURE__ */ jsxs("span", { className: "inline-flex shrink-0 items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-xs text-muted-foreground", children: [
|
|
105
|
+
/* @__PURE__ */ jsx(ToolIcon, { tool: toolKeyFor(node), className: "text-sm" }),
|
|
106
|
+
node.framework
|
|
107
|
+
] }),
|
|
108
|
+
node.duration ? /* @__PURE__ */ jsxs("span", { className: "inline-flex shrink-0 items-center gap-1 text-xs text-muted-foreground", children: [
|
|
109
|
+
/* @__PURE__ */ jsx(Icon, { icon: UiClock, className: "text-xs" }),
|
|
110
|
+
formatTestDuration(node.duration)
|
|
111
|
+
] }) : null,
|
|
112
|
+
location && /* @__PURE__ */ jsx(
|
|
113
|
+
"span",
|
|
114
|
+
{
|
|
115
|
+
className: "min-w-0 shrink-[100] truncate font-mono text-xs text-muted-foreground",
|
|
116
|
+
title: location,
|
|
117
|
+
children: location
|
|
118
|
+
}
|
|
119
|
+
),
|
|
120
|
+
/* @__PURE__ */ jsxs("div", { className: "ml-auto flex shrink-0 items-center gap-1", children: [
|
|
121
|
+
attemptChooser,
|
|
74
122
|
actions,
|
|
123
|
+
/* @__PURE__ */ jsx(CopyDetailsButton, { node }),
|
|
75
124
|
canRerun && /* @__PURE__ */ jsxs(
|
|
76
125
|
Button,
|
|
77
126
|
{
|
|
78
127
|
size: "sm",
|
|
79
128
|
disabled: runner.busy.rerun,
|
|
80
|
-
onClick: () => runner.onRerun(
|
|
129
|
+
onClick: () => runner.onRerun(actionNode),
|
|
81
130
|
title: "Rerun this test or subtree",
|
|
82
131
|
children: [
|
|
83
132
|
/* @__PURE__ */ jsx(Icon, { icon: UiRefresh, className: "mr-1 text-sm" }),
|
|
@@ -91,7 +140,7 @@ function DetailHeader({ node, actions }) {
|
|
|
91
140
|
size: "sm",
|
|
92
141
|
variant: "destructive",
|
|
93
142
|
disabled: runner.busy.stop,
|
|
94
|
-
onClick: () => runner.onStop(
|
|
143
|
+
onClick: () => runner.onStop(actionNode),
|
|
95
144
|
title: "Stop this running task",
|
|
96
145
|
children: [
|
|
97
146
|
/* @__PURE__ */ jsx(Icon, { icon: UiStop, className: "mr-1 text-sm" }),
|
|
@@ -100,28 +149,15 @@ function DetailHeader({ node, actions }) {
|
|
|
100
149
|
}
|
|
101
150
|
)
|
|
102
151
|
] })
|
|
103
|
-
]
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
/* @__PURE__ */ jsx(Icon, { icon: fwIcon, className: "text-sm" }),
|
|
107
|
-
node.framework
|
|
108
|
-
] }),
|
|
109
|
-
node.duration ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
110
|
-
/* @__PURE__ */ jsx(Icon, { icon: UiClock, className: "text-xs" }),
|
|
111
|
-
formatTestDuration(node.duration)
|
|
112
|
-
] }) : null,
|
|
113
|
-
node.file && /* @__PURE__ */ jsxs("span", { className: "font-mono", children: [
|
|
114
|
-
node.file,
|
|
115
|
-
node.line ? `:${node.line}` : ""
|
|
116
|
-
] })
|
|
117
|
-
] })
|
|
118
|
-
] })
|
|
119
|
-
] });
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
);
|
|
120
155
|
}
|
|
121
156
|
function TestDetailPanel() {
|
|
122
157
|
var _a;
|
|
123
158
|
const runner = useTestRunner();
|
|
124
|
-
const
|
|
159
|
+
const selected = runner.selected;
|
|
160
|
+
const [attemptSelection, setAttemptSelection] = useState(null);
|
|
125
161
|
const controlled = runner.activeTab !== void 0;
|
|
126
162
|
const [internalTab, setInternalTab] = useState("detail");
|
|
127
163
|
const activeTab = controlled ? runner.activeTab : internalTab;
|
|
@@ -130,22 +166,32 @@ function TestDetailPanel() {
|
|
|
130
166
|
if (controlled) (_a2 = runner.onTabChange) == null ? void 0 : _a2.call(runner, id);
|
|
131
167
|
else setInternalTab(id);
|
|
132
168
|
};
|
|
133
|
-
if (!
|
|
169
|
+
if (!selected) {
|
|
134
170
|
return /* @__PURE__ */ jsx("div", { className: "flex h-full items-center justify-center text-sm text-muted-foreground", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
135
171
|
/* @__PURE__ */ jsx(Icon, { icon: UiClass, className: "mb-2 block text-4xl" }),
|
|
136
172
|
"Select a test to view its details."
|
|
137
173
|
] }) });
|
|
138
174
|
}
|
|
175
|
+
const attempts = runner.adapters.resolveAttempts(selected, runner);
|
|
176
|
+
const key = selected.task_id ?? selected.name;
|
|
177
|
+
const attemptId = runner.activeAttempt ?? ((attemptSelection == null ? void 0 : attemptSelection.key) === key ? attemptSelection.id : void 0);
|
|
178
|
+
const attempt = attempts.find((a) => a.id === attemptId) ?? attempts.at(-1);
|
|
179
|
+
const node = attempts.length > 1 && attempt ? attempt.node : selected;
|
|
180
|
+
const attemptChooser = attempts.length > 1 && attempt ? /* @__PURE__ */ jsx("div", { className: "w-44 shrink-0", children: /* @__PURE__ */ jsx(Select, { "aria-label": "Attempt", value: String(attempt.id), className: "h-7 text-xs", onChange: (event) => {
|
|
181
|
+
const id = Number(event.target.value);
|
|
182
|
+
if (runner.onAttemptChange) runner.onAttemptChange(id);
|
|
183
|
+
else setAttemptSelection({ key, id });
|
|
184
|
+
}, options: attempts.map((a) => ({ value: String(a.id), label: `Attempt ${a.id}/${attempts.length} · ${a.status}${a.durationMs !== void 0 ? ` · ${formatTestDuration(a.durationMs * 1e6)}` : ""}` })) }) }) : null;
|
|
139
185
|
const detailAdapter = runner.adapters.resolveDetail(node, runner);
|
|
140
|
-
const actionAdapter = runner.adapters.resolveActions(
|
|
186
|
+
const actionAdapter = runner.adapters.resolveActions(selected, runner);
|
|
141
187
|
const tabs = runner.adapters.resolveTabs(node, runner);
|
|
142
188
|
const ownsScroll = runner.adapters.ownsScroll(node, runner);
|
|
143
189
|
const body = (detailAdapter == null ? void 0 : detailAdapter.renderDetail) ? detailAdapter.renderDetail({ node, runner }) : /* @__PURE__ */ jsx(DefaultDetailBody, { node });
|
|
144
|
-
const actions = (_a = actionAdapter == null ? void 0 : actionAdapter.nodeActions) == null ? void 0 : _a.call(actionAdapter, { node, runner });
|
|
145
|
-
const detailRegion =
|
|
190
|
+
const actions = (_a = actionAdapter == null ? void 0 : actionAdapter.nodeActions) == null ? void 0 : _a.call(actionAdapter, { node: selected, runner });
|
|
191
|
+
const detailRegion = cn("min-h-0 flex-1 [container-type:size]", !ownsScroll && "overflow-y-auto");
|
|
146
192
|
if (tabs.length === 0) {
|
|
147
193
|
return /* @__PURE__ */ jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [
|
|
148
|
-
/* @__PURE__ */ jsx(DetailHeader, { node, actions }),
|
|
194
|
+
/* @__PURE__ */ jsx(DetailHeader, { node, actionNode: selected, actions, attemptChooser }),
|
|
149
195
|
/* @__PURE__ */ jsx("div", { className: detailRegion, children: body })
|
|
150
196
|
] });
|
|
151
197
|
}
|
|
@@ -153,7 +199,7 @@ function TestDetailPanel() {
|
|
|
153
199
|
const allTabs = [detailTab, ...tabs];
|
|
154
200
|
const active = allTabs.find((t) => t.id === activeTab) ?? detailTab;
|
|
155
201
|
return /* @__PURE__ */ jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [
|
|
156
|
-
/* @__PURE__ */ jsx(DetailHeader, { node, actions }),
|
|
202
|
+
/* @__PURE__ */ jsx(DetailHeader, { node, actionNode: selected, actions, attemptChooser }),
|
|
157
203
|
/* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-1 border-b border-border px-density-2 py-density-1", children: allTabs.map((t) => /* @__PURE__ */ jsx(
|
|
158
204
|
TabButton,
|
|
159
205
|
{
|