@flanksource/clicky-ui 0.3.46 → 0.3.47
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/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/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/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/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 +74 -42
- 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 +76 -44
- 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 +52 -30
- package/dist/data/test-runner/TestRunner.cjs.map +1 -1
- package/dist/data/test-runner/TestRunner.d.ts +3 -2
- package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunner.js +52 -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 +27 -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 +28 -20
- package/dist/data/test-runner/TestTreeNode.js.map +1 -1
- package/dist/data/test-runner/adapter.cjs +11 -0
- package/dist/data/test-runner/adapter.cjs.map +1 -1
- package/dist/data/test-runner/adapter.d.ts +18 -7
- package/dist/data/test-runner/adapter.d.ts.map +1 -1
- package/dist/data/test-runner/adapter.js +11 -0
- package/dist/data/test-runner/adapter.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 +5 -2
- package/dist/data/test-runner/index.d.ts.map +1 -1
- package/dist/data/test-runner/marks.cjs +143 -0
- package/dist/data/test-runner/marks.cjs.map +1 -0
- package/dist/data/test-runner/marks.d.ts +30 -0
- package/dist/data/test-runner/marks.d.ts.map +1 -0
- package/dist/data/test-runner/marks.js +143 -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/verification/adapterViews.cjs +16 -41
- package/dist/data/verification/adapterViews.cjs.map +1 -1
- package/dist/data/verification/adapterViews.d.ts.map +1 -1
- package/dist/data/verification/adapterViews.js +16 -41
- package/dist/data/verification/adapterViews.js.map +1 -1
- package/dist/data/verification/adapters.cjs +115 -3
- package/dist/data/verification/adapters.cjs.map +1 -1
- package/dist/data/verification/adapters.d.ts.map +1 -1
- package/dist/data/verification/adapters.js +115 -3
- package/dist/data/verification/adapters.js.map +1 -1
- package/dist/data/verification/verifyReportTests.cjs.map +1 -1
- 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 +44 -3
- 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 +45 -4
- 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 +44 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +45 -4
- 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/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/OperationScheduleDialog.cjs +63 -10
- package/dist/rpc/OperationScheduleDialog.cjs.map +1 -1
- package/dist/rpc/OperationScheduleDialog.d.ts +4 -0
- package/dist/rpc/OperationScheduleDialog.d.ts.map +1 -1
- package/dist/rpc/OperationScheduleDialog.js +63 -10
- package/dist/rpc/OperationScheduleDialog.js.map +1 -1
- package/dist/rpc/OperationSchedules.cjs +12 -2
- package/dist/rpc/OperationSchedules.cjs.map +1 -1
- package/dist/rpc/OperationSchedules.d.ts.map +1 -1
- package/dist/rpc/OperationSchedules.js +12 -2
- package/dist/rpc/OperationSchedules.js.map +1 -1
- package/dist/rpc/operation-schedule-model.cjs +2 -0
- package/dist/rpc/operation-schedule-model.cjs.map +1 -1
- package/dist/rpc/operation-schedule-model.d.ts.map +1 -1
- package/dist/rpc/operation-schedule-model.js +2 -0
- package/dist/rpc/operation-schedule-model.js.map +1 -1
- package/dist/rpc/operation-schedule-types.d.ts +7 -1
- package/dist/rpc/operation-schedule-types.d.ts.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
|
@@ -3,6 +3,7 @@ import { useMemo } from "react";
|
|
|
3
3
|
import { Icon } from "../Icon.js";
|
|
4
4
|
import { SplitPane } from "../../layout/SplitPane.js";
|
|
5
5
|
import { cn } from "../../lib/utils.js";
|
|
6
|
+
import { useContainerWiderThan } from "../../hooks/use-container-width.js";
|
|
6
7
|
import { collectFrameworks, aggregateStatusCounts } from "./status.js";
|
|
7
8
|
import { TestNodeAdapterRegistry, createTestRunnerRegistry } from "./adapter.js";
|
|
8
9
|
import { TestRunnerProvider } from "./context.js";
|
|
@@ -11,10 +12,12 @@ import { TestDetailPanel } from "./TestDetailPanel.js";
|
|
|
11
12
|
import { TestRunSummary } from "./TestRunSummary.js";
|
|
12
13
|
import { TestFilterBar } from "./TestFilterBar.js";
|
|
13
14
|
import { UiBeaker } from "../../icons/components/UiBeaker.js";
|
|
15
|
+
import { UiArrowLeft } from "../../icons/components/UiArrowLeft.js";
|
|
14
16
|
function toRegistry(adapters) {
|
|
15
17
|
if (adapters instanceof TestNodeAdapterRegistry) return adapters;
|
|
16
18
|
return createTestRunnerRegistry(adapters ?? []);
|
|
17
19
|
}
|
|
20
|
+
const SPLIT_MIN_WIDTH = 640;
|
|
18
21
|
function TestRunner({
|
|
19
22
|
tests,
|
|
20
23
|
allTests,
|
|
@@ -88,19 +91,30 @@ function TestRunner({
|
|
|
88
91
|
const summaryTests = allTests ?? tests;
|
|
89
92
|
const frameworks = useMemo(() => collectFrameworks(summaryTests), [summaryTests]);
|
|
90
93
|
const filterCounts = useMemo(() => aggregateStatusCounts(summaryTests), [summaryTests]);
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
94
|
+
const filterBar = !hideHeader && summaryTests.length > 0 ? /* @__PURE__ */ jsx(
|
|
95
|
+
TestFilterBar,
|
|
96
|
+
{
|
|
97
|
+
filters,
|
|
98
|
+
onChange: onFiltersChange,
|
|
99
|
+
counts: filterCounts,
|
|
100
|
+
frameworks
|
|
101
|
+
}
|
|
102
|
+
) : null;
|
|
103
|
+
const { ref, wider: roomy } = useContainerWiderThan(SPLIT_MIN_WIDTH);
|
|
104
|
+
return /* @__PURE__ */ jsx(TestRunnerProvider, { value: ctx, children: /* @__PURE__ */ jsxs("div", { ref, className: cn("flex h-full min-h-0 flex-col bg-background", className), children: [
|
|
105
|
+
!hideHeader && /* @__PURE__ */ jsxs(
|
|
106
|
+
"div",
|
|
107
|
+
{
|
|
108
|
+
className: "flex min-w-0 items-center gap-3 border-b border-border bg-card px-density-4 py-density-2",
|
|
109
|
+
"data-runner-header": "",
|
|
110
|
+
children: [
|
|
111
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [
|
|
112
|
+
title === void 0 ? /* @__PURE__ */ jsxs("h1", { className: "inline-flex shrink-0 items-center gap-1.5 text-base font-bold", children: [
|
|
113
|
+
/* @__PURE__ */ jsx(Icon, { icon: UiBeaker, className: "text-primary" }),
|
|
114
|
+
"Test Results"
|
|
115
|
+
] }) : title,
|
|
116
|
+
statusText && /* @__PURE__ */ jsx("span", { className: "truncate text-sm text-muted-foreground", children: statusText })
|
|
117
|
+
] }),
|
|
104
118
|
showSummary && /* @__PURE__ */ jsx(
|
|
105
119
|
TestRunSummary,
|
|
106
120
|
{
|
|
@@ -109,22 +123,16 @@ function TestRunner({
|
|
|
109
123
|
endTime,
|
|
110
124
|
done,
|
|
111
125
|
now,
|
|
112
|
-
runMeta
|
|
126
|
+
runMeta,
|
|
127
|
+
compact: true,
|
|
128
|
+
className: "ml-auto flex-nowrap"
|
|
113
129
|
}
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
filters,
|
|
121
|
-
onChange: onFiltersChange,
|
|
122
|
-
counts: filterCounts,
|
|
123
|
-
frameworks
|
|
124
|
-
}
|
|
125
|
-
) })
|
|
126
|
-
] }),
|
|
127
|
-
/* @__PURE__ */ jsx(
|
|
130
|
+
),
|
|
131
|
+
headerSlot && /* @__PURE__ */ jsx("div", { className: cn("flex shrink-0 items-center gap-1", !showSummary && "ml-auto"), children: headerSlot })
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
),
|
|
135
|
+
roomy ? /* @__PURE__ */ jsx(
|
|
128
136
|
SplitPane,
|
|
129
137
|
{
|
|
130
138
|
className: "min-h-0 flex-1",
|
|
@@ -132,10 +140,24 @@ function TestRunner({
|
|
|
132
140
|
minLeft: 25,
|
|
133
141
|
minRight: 30,
|
|
134
142
|
leftClass: "border-r-2 border-border bg-muted/30",
|
|
135
|
-
left: /* @__PURE__ */ jsx(TestTree, {}),
|
|
143
|
+
left: /* @__PURE__ */ jsx(TestTree, { actions: filterBar }),
|
|
136
144
|
right: /* @__PURE__ */ jsx(TestDetailPanel, {})
|
|
137
145
|
}
|
|
138
|
-
)
|
|
146
|
+
) : selected ? /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [
|
|
147
|
+
/* @__PURE__ */ jsxs(
|
|
148
|
+
"button",
|
|
149
|
+
{
|
|
150
|
+
type: "button",
|
|
151
|
+
onClick: () => onSelect(null),
|
|
152
|
+
className: "inline-flex items-center gap-1.5 border-b border-border px-density-3 py-density-2 text-left text-sm text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
153
|
+
children: [
|
|
154
|
+
/* @__PURE__ */ jsx(Icon, { icon: UiArrowLeft }),
|
|
155
|
+
"Back to results"
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
),
|
|
159
|
+
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(TestDetailPanel, {}) })
|
|
160
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-y-auto", children: /* @__PURE__ */ jsx(TestTree, { actions: filterBar }) })
|
|
139
161
|
] }) });
|
|
140
162
|
}
|
|
141
163
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestRunner.js","sources":["../../../src/data/test-runner/TestRunner.tsx"],"sourcesContent":["import { useMemo, type ReactNode } from \"react\";\nimport { Icon } from \"../Icon\";\nimport { SplitPane } from \"../../layout/SplitPane\";\nimport { cn } from \"../../lib/utils\";\nimport { UiBeaker } from \"../../icons\";\nimport type { RunMeta, SnapshotStatus, Test } from \"./types\";\nimport { aggregateStatusCounts, collectFrameworks } from \"./status\";\nimport { type TestFilters } from \"./filterState\";\nimport {\n createTestRunnerRegistry,\n type TestNodeAdapter,\n TestNodeAdapterRegistry,\n} from \"./adapter\";\nimport { TestRunnerProvider, type TestRunnerContext } from \"./context\";\nimport { TestTree } from \"./TestTree\";\nimport { TestDetailPanel } from \"./TestDetailPanel\";\nimport { TestRunSummary } from \"./TestRunSummary\";\nimport { TestFilterBar } from \"./TestFilterBar\";\n\nexport type TestRunnerProps = {\n tests: Test[];\n /**\n * The full, unfiltered forest driving the filter bar's pills/counts and the\n * header summary — falls back to `tests` when omitted (every existing\n * caller pre-filters `tests` itself). Pass this explicitly when `tests` is a\n * filtered subset of a larger report, so toggling a status filter (e.g.\n * excluding the only failed node) can't make its own pill — or the whole\n * filter bar, once every pill's count reads zero — disappear.\n */\n allTests?: Test[];\n selected: Test | null;\n filters: TestFilters;\n expandAll: boolean | null;\n done: boolean;\n runMeta?: RunMeta;\n status?: SnapshotStatus;\n /** Free-form status line shown next to the title (e.g. \"Running tests...\"). */\n statusText?: string;\n now?: number;\n busy?: { rerun?: boolean; stop?: boolean };\n\n /** Controlled active detail-tab id; omit to let the detail pane own tab state. */\n activeTab?: string;\n /** Called with the picked tab id when `activeTab` is controlled. */\n onTabChange?: (tabId: string) => void;\n\n onSelect: (node: Test | null) => void;\n onFiltersChange: (next: TestFilters) => void;\n onExpandAllChange: (next: boolean | null) => void;\n onRerun?: (node: Test) => void;\n onStop?: (node: Test) => void;\n\n /** Domain node adapters, or a pre-built registry. Defaults to default-only. */\n adapters?: TestNodeAdapter[] | TestNodeAdapterRegistry;\n /**\n * Header title. Defaults (when omitted) to the \"Test Results\" beaker heading.\n * Pass `null` to render no title — e.g. a host that owns the title in its own\n * dialog/page header and embeds the runner below it.\n */\n title?: ReactNode;\n /**\n * Render the built-in run summary (counts + progress) in the header. Defaults\n * to true; pass false when the host shows the summary itself (e.g. in a dialog\n * header) to avoid duplicating it.\n */\n showSummary?: boolean;\n /** Extra header content (e.g. export/download controls owned by the host). */\n headerSlot?: ReactNode;\n /**\n * Suppresses the entire built-in header bar (title, summary, filter row).\n * Defaults to false; pass true when a host renders its own combined header\n * (e.g. a dialog header that already embeds `TestRunSummary` and filters) so\n * the runner doesn't render a second bordered bar underneath it.\n */\n hideHeader?: boolean;\n /** Initial left-pane width percentage. */\n defaultSplit?: number;\n startTime?: number | null;\n endTime?: number | null;\n className?: string;\n};\n\nfunction toRegistry(\n adapters: TestNodeAdapter[] | TestNodeAdapterRegistry | undefined,\n): TestNodeAdapterRegistry {\n if (adapters instanceof TestNodeAdapterRegistry) return adapters;\n return createTestRunnerRegistry(adapters ?? []);\n}\n\n/**\n * Top-level, pure-presentational test runner: a summary/filter header over a\n * resizable tree + detail split. All data and handlers flow in via props and\n * are exposed to sub-components through a single `TestRunnerContext`. Domain\n * rendering is pluggable via node adapters; no fetch/SSE/routing lives here.\n */\nexport function TestRunner({\n tests,\n allTests,\n selected,\n filters,\n expandAll,\n done,\n runMeta,\n status,\n statusText,\n now,\n busy,\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n adapters,\n title,\n showSummary = true,\n headerSlot,\n hideHeader = false,\n defaultSplit = 45,\n startTime,\n endTime,\n className,\n}: TestRunnerProps) {\n const registry = useMemo(() => toRegistry(adapters), [adapters]);\n\n const ctx: TestRunnerContext = useMemo(\n () => ({\n tests,\n selected,\n runMeta,\n status,\n done,\n now,\n filters,\n expandAll,\n busy: busy ?? {},\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n adapters: registry,\n }),\n [\n tests,\n selected,\n runMeta,\n status,\n done,\n now,\n filters,\n expandAll,\n busy,\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n registry,\n ],\n );\n\n const summaryTests = allTests ?? tests;\n const frameworks = useMemo(() => collectFrameworks(summaryTests), [summaryTests]);\n const filterCounts = useMemo(() => aggregateStatusCounts(summaryTests), [summaryTests]);\n const hasContent = summaryTests.length > 0;\n\n return (\n <TestRunnerProvider value={ctx}>\n <div className={cn(\"flex h-full min-h-0 flex-col bg-background\", className)}>\n {!hideHeader && (\n <div className=\"border-b border-border bg-card px-density-4 py-density-3\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-center gap-3\">\n {title === undefined ? (\n <h1 className=\"inline-flex items-center gap-1.5 text-lg font-bold\">\n <Icon icon={UiBeaker} className=\"text-primary\" />\n Test Results\n </h1>\n ) : (\n title\n )}\n {statusText && <span className=\"text-sm text-muted-foreground\">{statusText}</span>}\n </div>\n <div className=\"flex items-center gap-3\">\n {headerSlot}\n {showSummary && (\n <TestRunSummary\n tests={summaryTests}\n startTime={startTime}\n endTime={endTime}\n done={done}\n now={now}\n runMeta={runMeta}\n />\n )}\n </div>\n </div>\n {hasContent && (\n <div className=\"mt-2\">\n <TestFilterBar\n filters={filters}\n onChange={onFiltersChange}\n counts={filterCounts}\n frameworks={frameworks}\n />\n </div>\n )}\n </div>\n )}\n\n <SplitPane\n className=\"min-h-0 flex-1\"\n defaultSplit={defaultSplit}\n minLeft={25}\n minRight={30}\n leftClass=\"border-r-2 border-border bg-muted/30\"\n left={<TestTree />}\n right={<TestDetailPanel />}\n />\n </div>\n </TestRunnerProvider>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TestRunner.js","sources":["../../../src/data/test-runner/TestRunner.tsx"],"sourcesContent":["import { useMemo, type ReactNode } from \"react\";\nimport { Icon } from \"../Icon\";\nimport { SplitPane } from \"../../layout/SplitPane\";\nimport { cn } from \"../../lib/utils\";\nimport { UiArrowLeft, UiBeaker } from \"../../icons\";\nimport { useContainerWiderThan } from \"../../hooks/use-container-width\";\nimport type { RunMeta, SnapshotStatus, Test } from \"./types\";\nimport { aggregateStatusCounts, collectFrameworks } from \"./status\";\nimport { type TestFilters } from \"./filterState\";\nimport {\n createTestRunnerRegistry,\n type TestNodeAdapter,\n TestNodeAdapterRegistry,\n} from \"./adapter\";\nimport { TestRunnerProvider, type TestRunnerContext } from \"./context\";\nimport { TestTree } from \"./TestTree\";\nimport { TestDetailPanel } from \"./TestDetailPanel\";\nimport { TestRunSummary } from \"./TestRunSummary\";\nimport { TestFilterBar } from \"./TestFilterBar\";\n\nexport type TestRunnerProps = {\n tests: Test[];\n /**\n * The full, unfiltered forest driving the filter bar's pills/counts and the\n * header summary — falls back to `tests` when omitted (every existing\n * caller pre-filters `tests` itself). Pass this explicitly when `tests` is a\n * filtered subset of a larger report, so toggling a status filter (e.g.\n * excluding the only failed node) can't make its own pill — or the whole\n * filter bar, once every pill's count reads zero — disappear.\n */\n allTests?: Test[];\n selected: Test | null;\n filters: TestFilters;\n expandAll: boolean | null;\n done: boolean;\n runMeta?: RunMeta;\n status?: SnapshotStatus;\n /** Free-form status line shown next to the title (e.g. \"Running tests...\"). */\n statusText?: string;\n now?: number;\n busy?: { rerun?: boolean; stop?: boolean };\n\n /** Controlled active detail-tab id; omit to let the detail pane own tab state. */\n activeTab?: string;\n /** Called with the picked tab id when `activeTab` is controlled. */\n onTabChange?: (tabId: string) => void;\n\n onSelect: (node: Test | null) => void;\n onFiltersChange: (next: TestFilters) => void;\n onExpandAllChange: (next: boolean | null) => void;\n onRerun?: (node: Test) => void;\n onStop?: (node: Test) => void;\n\n /** Domain node adapters, or a pre-built registry. Defaults to default-only. */\n adapters?: TestNodeAdapter[] | TestNodeAdapterRegistry;\n /**\n * Header title. Defaults (when omitted) to the \"Test Results\" beaker heading.\n * Pass `null` to render no title — e.g. a host that owns the title in its own\n * dialog/page header and embeds the runner below it.\n */\n title?: ReactNode;\n /**\n * Render the built-in run summary (counts + progress) in the header. Defaults\n * to true; pass false when the host shows the summary itself (e.g. in a dialog\n * header) to avoid duplicating it.\n */\n showSummary?: boolean;\n /** Run actions at the right end of the one-line header (e.g. re-run, export, copy). */\n headerSlot?: ReactNode;\n /**\n * Suppresses the built-in header bar (title, summary) and the status/tool\n * facets in the tree toolbar.\n * Defaults to false; pass true when a host renders its own combined header\n * (e.g. a dialog header that already embeds `TestRunSummary` and filters) so\n * the runner doesn't render a second bordered bar underneath it.\n */\n hideHeader?: boolean;\n /** Initial left-pane width percentage. */\n defaultSplit?: number;\n startTime?: number | null;\n endTime?: number | null;\n className?: string;\n};\n\nfunction toRegistry(\n adapters: TestNodeAdapter[] | TestNodeAdapterRegistry | undefined,\n): TestNodeAdapterRegistry {\n if (adapters instanceof TestNodeAdapterRegistry) return adapters;\n return createTestRunnerRegistry(adapters ?? []);\n}\n\nconst SPLIT_MIN_WIDTH = 640;\n\n/**\n * Top-level, pure-presentational test runner: a summary/filter header over a\n * resizable tree + detail split. All data and handlers flow in via props and\n * are exposed to sub-components through a single `TestRunnerContext`. Domain\n * rendering is pluggable via node adapters; no fetch/SSE/routing lives here.\n */\nexport function TestRunner({\n tests,\n allTests,\n selected,\n filters,\n expandAll,\n done,\n runMeta,\n status,\n statusText,\n now,\n busy,\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n adapters,\n title,\n showSummary = true,\n headerSlot,\n hideHeader = false,\n defaultSplit = 45,\n startTime,\n endTime,\n className,\n}: TestRunnerProps) {\n const registry = useMemo(() => toRegistry(adapters), [adapters]);\n\n const ctx: TestRunnerContext = useMemo(\n () => ({\n tests,\n selected,\n runMeta,\n status,\n done,\n now,\n filters,\n expandAll,\n busy: busy ?? {},\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n adapters: registry,\n }),\n [\n tests,\n selected,\n runMeta,\n status,\n done,\n now,\n filters,\n expandAll,\n busy,\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n registry,\n ],\n );\n\n const summaryTests = allTests ?? tests;\n const frameworks = useMemo(() => collectFrameworks(summaryTests), [summaryTests]);\n const filterCounts = useMemo(() => aggregateStatusCounts(summaryTests), [summaryTests]);\n // A host that hides the header renders its own filters (see hideHeader).\n const filterBar =\n !hideHeader && summaryTests.length > 0 ? (\n <TestFilterBar\n filters={filters}\n onChange={onFiltersChange}\n counts={filterCounts}\n frameworks={frameworks}\n />\n ) : null;\n // Below this the split leaves both panes too narrow to read, so the runner\n // goes master/detail: the tree, then the selected test with a way back.\n const { ref, wider: roomy } = useContainerWiderThan(SPLIT_MIN_WIDTH);\n\n return (\n <TestRunnerProvider value={ctx}>\n <div ref={ref} className={cn(\"flex h-full min-h-0 flex-col bg-background\", className)}>\n {!hideHeader && (\n <div\n className=\"flex min-w-0 items-center gap-3 border-b border-border bg-card px-density-4 py-density-2\"\n data-runner-header=\"\"\n >\n <div className=\"flex min-w-0 items-center gap-3\">\n {title === undefined ? (\n <h1 className=\"inline-flex shrink-0 items-center gap-1.5 text-base font-bold\">\n <Icon icon={UiBeaker} className=\"text-primary\" />\n Test Results\n </h1>\n ) : (\n title\n )}\n {statusText && (\n <span className=\"truncate text-sm text-muted-foreground\">{statusText}</span>\n )}\n </div>\n {showSummary && (\n <TestRunSummary\n tests={summaryTests}\n startTime={startTime}\n endTime={endTime}\n done={done}\n now={now}\n runMeta={runMeta}\n compact\n className=\"ml-auto flex-nowrap\"\n />\n )}\n {headerSlot && (\n <div className={cn(\"flex shrink-0 items-center gap-1\", !showSummary && \"ml-auto\")}>\n {headerSlot}\n </div>\n )}\n </div>\n )}\n\n {roomy ? (\n <SplitPane\n className=\"min-h-0 flex-1\"\n defaultSplit={defaultSplit}\n minLeft={25}\n minRight={30}\n leftClass=\"border-r-2 border-border bg-muted/30\"\n left={<TestTree actions={filterBar} />}\n right={<TestDetailPanel />}\n />\n ) : selected ? (\n <div className=\"flex min-h-0 flex-1 flex-col\">\n <button\n type=\"button\"\n onClick={() => onSelect(null)}\n className=\"inline-flex items-center gap-1.5 border-b border-border px-density-3 py-density-2 text-left text-sm text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <Icon icon={UiArrowLeft} />\n Back to results\n </button>\n <div className=\"min-h-0 flex-1 overflow-hidden\">\n <TestDetailPanel />\n </div>\n </div>\n ) : (\n <div className=\"min-h-0 flex-1 overflow-y-auto\">\n <TestTree actions={filterBar} />\n </div>\n )}\n </div>\n </TestRunnerProvider>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -19,7 +19,7 @@ const nodeKey = /* @__PURE__ */ (() => {
|
|
|
19
19
|
return key;
|
|
20
20
|
};
|
|
21
21
|
})();
|
|
22
|
-
function TestTree({ className }) {
|
|
22
|
+
function TestTree({ className, actions }) {
|
|
23
23
|
const runner = context.useTestRunner();
|
|
24
24
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
25
25
|
Tree.Tree,
|
|
@@ -33,8 +33,11 @@ function TestTree({ className }) {
|
|
|
33
33
|
expandAll: runner.expandAll,
|
|
34
34
|
onExpandAllChange: runner.onExpandAllChange,
|
|
35
35
|
defaultOpen: (node, depth) => depth < 1 || status.hasFailed(node),
|
|
36
|
+
showSearch: true,
|
|
37
|
+
searchLabel: "Filter tests",
|
|
36
38
|
getSearchText: (node) => `${node.name} ${node.framework ?? ""}`,
|
|
37
|
-
renderRow: ({ node, selected }) => /* @__PURE__ */ jsxRuntime.jsx(TestTreeNode.TestTreeNode, { node, selected })
|
|
39
|
+
renderRow: ({ node, selected }) => /* @__PURE__ */ jsxRuntime.jsx(TestTreeNode.TestTreeNode, { node, selected }),
|
|
40
|
+
actions
|
|
38
41
|
}
|
|
39
42
|
);
|
|
40
43
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestTree.cjs","sources":["../../../src/data/test-runner/TestTree.tsx"],"sourcesContent":["import { Tree } from \"../Tree\";\nimport { cn } from \"../../lib/utils\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport { hasFailed } from \"./status\";\nimport { TestTreeNode } from \"./TestTreeNode\";\n\nconst nodeKey = (() => {\n // Tests carry no guaranteed id; derive a stable per-render key from route_path\n // when present, else the node's name path. A WeakMap keeps keys stable across\n // re-renders for the same object identity.\n const cache = new WeakMap<Test, string>();\n let counter = 0;\n return (node: Test): string => {\n if (node.route_path) return node.route_path;\n let key = cache.get(node);\n if (!key) {\n key = `tn-${counter++}-${node.name}`;\n cache.set(node, key);\n }\n return key;\n };\n})();\n\n/**\n * The left pane: the test forest rendered through the clicky `Tree`. Selection,\n * handlers and adapters all come from the runner context; failing branches and\n * the top level open by default.\n */\nexport function TestTree({ className }: { className?: string }) {\n const runner = useTestRunner();\n return (\n <Tree<Test>\n className={cn(\"min-h-0\", className)}\n roots={runner.tests}\n getKey={nodeKey}\n getChildren={(node) => node.children}\n selected={runner.selected}\n onSelect={(node) => runner.onSelect(node === runner.selected ? null : node)}\n expandAll={runner.expandAll}\n onExpandAllChange={runner.onExpandAllChange}\n defaultOpen={(node, depth) => depth < 1 || hasFailed(node)}\n getSearchText={(node) => `${node.name} ${node.framework ?? \"\"}`}\n renderRow={({ node, selected }) => <TestTreeNode node={node} selected={selected} />}\n />\n );\n}\n"],"names":["useTestRunner","jsx","Tree","cn","hasFailed","TestTreeNode"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"TestTree.cjs","sources":["../../../src/data/test-runner/TestTree.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { Tree } from \"../Tree\";\nimport { cn } from \"../../lib/utils\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport { hasFailed } from \"./status\";\nimport { TestTreeNode } from \"./TestTreeNode\";\n\nconst nodeKey = (() => {\n // Tests carry no guaranteed id; derive a stable per-render key from route_path\n // when present, else the node's name path. A WeakMap keeps keys stable across\n // re-renders for the same object identity.\n const cache = new WeakMap<Test, string>();\n let counter = 0;\n return (node: Test): string => {\n if (node.route_path) return node.route_path;\n let key = cache.get(node);\n if (!key) {\n key = `tn-${counter++}-${node.name}`;\n cache.set(node, key);\n }\n return key;\n };\n})();\n\n/**\n * The left pane: the test forest rendered through the clicky `Tree`. Selection,\n * handlers and adapters all come from the runner context; failing branches and\n * the top level open by default. A name filter is always shown, and `actions`\n * sit in the tree toolbar beside it and Expand all / Collapse all.\n */\nexport function TestTree({ className, actions }: { className?: string; actions?: ReactNode }) {\n const runner = useTestRunner();\n return (\n <Tree<Test>\n className={cn(\"min-h-0\", className)}\n roots={runner.tests}\n getKey={nodeKey}\n getChildren={(node) => node.children}\n selected={runner.selected}\n onSelect={(node) => runner.onSelect(node === runner.selected ? null : node)}\n expandAll={runner.expandAll}\n onExpandAllChange={runner.onExpandAllChange}\n defaultOpen={(node, depth) => depth < 1 || hasFailed(node)}\n showSearch\n searchLabel=\"Filter tests\"\n getSearchText={(node) => `${node.name} ${node.framework ?? \"\"}`}\n renderRow={({ node, selected }) => <TestTreeNode node={node} selected={selected} />}\n actions={actions}\n />\n );\n}\n"],"names":["useTestRunner","jsx","Tree","cn","hasFailed","TestTreeNode"],"mappings":";;;;;;;;AAQA,MAAM,UAAW,uBAAM;AAIrB,QAAM,4BAAY,QAAA;AAClB,MAAI,UAAU;AACd,SAAO,CAAC,SAAuB;AAC7B,QAAI,KAAK,WAAY,QAAO,KAAK;AACjC,QAAI,MAAM,MAAM,IAAI,IAAI;AACxB,QAAI,CAAC,KAAK;AACR,YAAM,MAAM,SAAS,IAAI,KAAK,IAAI;AAClC,YAAM,IAAI,MAAM,GAAG;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AACF,GAAA;AAQO,SAAS,SAAS,EAAE,WAAW,WAAwD;AAC5F,QAAM,SAASA,QAAAA,cAAA;AACf,SACEC,2BAAAA;AAAAA,IAACC,KAAAA;AAAAA,IAAA;AAAA,MACC,WAAWC,MAAAA,GAAG,WAAW,SAAS;AAAA,MAClC,OAAO,OAAO;AAAA,MACd,QAAQ;AAAA,MACR,aAAa,CAAC,SAAS,KAAK;AAAA,MAC5B,UAAU,OAAO;AAAA,MACjB,UAAU,CAAC,SAAS,OAAO,SAAS,SAAS,OAAO,WAAW,OAAO,IAAI;AAAA,MAC1E,WAAW,OAAO;AAAA,MAClB,mBAAmB,OAAO;AAAA,MAC1B,aAAa,CAAC,MAAM,UAAU,QAAQ,KAAKC,OAAAA,UAAU,IAAI;AAAA,MACzD,YAAU;AAAA,MACV,aAAY;AAAA,MACZ,eAAe,CAAC,SAAS,GAAG,KAAK,IAAI,IAAI,KAAK,aAAa,EAAE;AAAA,MAC7D,WAAW,CAAC,EAAE,MAAM,eAAeH,2BAAAA,IAACI,2BAAA,EAAa,MAAY,UAAoB;AAAA,MACjF;AAAA,IAAA;AAAA,EAAA;AAGN;;"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
1
2
|
/**
|
|
2
3
|
* The left pane: the test forest rendered through the clicky `Tree`. Selection,
|
|
3
4
|
* handlers and adapters all come from the runner context; failing branches and
|
|
4
|
-
* the top level open by default.
|
|
5
|
+
* the top level open by default. A name filter is always shown, and `actions`
|
|
6
|
+
* sit in the tree toolbar beside it and Expand all / Collapse all.
|
|
5
7
|
*/
|
|
6
|
-
export declare function TestTree({ className }: {
|
|
8
|
+
export declare function TestTree({ className, actions }: {
|
|
7
9
|
className?: string;
|
|
10
|
+
actions?: ReactNode;
|
|
8
11
|
}): import("react").JSX.Element;
|
|
9
12
|
//# sourceMappingURL=TestTree.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestTree.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/TestTree.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TestTree.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/TestTree.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAyBvC;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,SAAS,CAAA;CAAE,+BAoB3F"}
|
|
@@ -17,7 +17,7 @@ const nodeKey = /* @__PURE__ */ (() => {
|
|
|
17
17
|
return key;
|
|
18
18
|
};
|
|
19
19
|
})();
|
|
20
|
-
function TestTree({ className }) {
|
|
20
|
+
function TestTree({ className, actions }) {
|
|
21
21
|
const runner = useTestRunner();
|
|
22
22
|
return /* @__PURE__ */ jsx(
|
|
23
23
|
Tree,
|
|
@@ -31,8 +31,11 @@ function TestTree({ className }) {
|
|
|
31
31
|
expandAll: runner.expandAll,
|
|
32
32
|
onExpandAllChange: runner.onExpandAllChange,
|
|
33
33
|
defaultOpen: (node, depth) => depth < 1 || hasFailed(node),
|
|
34
|
+
showSearch: true,
|
|
35
|
+
searchLabel: "Filter tests",
|
|
34
36
|
getSearchText: (node) => `${node.name} ${node.framework ?? ""}`,
|
|
35
|
-
renderRow: ({ node, selected }) => /* @__PURE__ */ jsx(TestTreeNode, { node, selected })
|
|
37
|
+
renderRow: ({ node, selected }) => /* @__PURE__ */ jsx(TestTreeNode, { node, selected }),
|
|
38
|
+
actions
|
|
36
39
|
}
|
|
37
40
|
);
|
|
38
41
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestTree.js","sources":["../../../src/data/test-runner/TestTree.tsx"],"sourcesContent":["import { Tree } from \"../Tree\";\nimport { cn } from \"../../lib/utils\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport { hasFailed } from \"./status\";\nimport { TestTreeNode } from \"./TestTreeNode\";\n\nconst nodeKey = (() => {\n // Tests carry no guaranteed id; derive a stable per-render key from route_path\n // when present, else the node's name path. A WeakMap keeps keys stable across\n // re-renders for the same object identity.\n const cache = new WeakMap<Test, string>();\n let counter = 0;\n return (node: Test): string => {\n if (node.route_path) return node.route_path;\n let key = cache.get(node);\n if (!key) {\n key = `tn-${counter++}-${node.name}`;\n cache.set(node, key);\n }\n return key;\n };\n})();\n\n/**\n * The left pane: the test forest rendered through the clicky `Tree`. Selection,\n * handlers and adapters all come from the runner context; failing branches and\n * the top level open by default.\n */\nexport function TestTree({ className }: { className?: string }) {\n const runner = useTestRunner();\n return (\n <Tree<Test>\n className={cn(\"min-h-0\", className)}\n roots={runner.tests}\n getKey={nodeKey}\n getChildren={(node) => node.children}\n selected={runner.selected}\n onSelect={(node) => runner.onSelect(node === runner.selected ? null : node)}\n expandAll={runner.expandAll}\n onExpandAllChange={runner.onExpandAllChange}\n defaultOpen={(node, depth) => depth < 1 || hasFailed(node)}\n getSearchText={(node) => `${node.name} ${node.framework ?? \"\"}`}\n renderRow={({ node, selected }) => <TestTreeNode node={node} selected={selected} />}\n />\n );\n}\n"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"TestTree.js","sources":["../../../src/data/test-runner/TestTree.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { Tree } from \"../Tree\";\nimport { cn } from \"../../lib/utils\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport { hasFailed } from \"./status\";\nimport { TestTreeNode } from \"./TestTreeNode\";\n\nconst nodeKey = (() => {\n // Tests carry no guaranteed id; derive a stable per-render key from route_path\n // when present, else the node's name path. A WeakMap keeps keys stable across\n // re-renders for the same object identity.\n const cache = new WeakMap<Test, string>();\n let counter = 0;\n return (node: Test): string => {\n if (node.route_path) return node.route_path;\n let key = cache.get(node);\n if (!key) {\n key = `tn-${counter++}-${node.name}`;\n cache.set(node, key);\n }\n return key;\n };\n})();\n\n/**\n * The left pane: the test forest rendered through the clicky `Tree`. Selection,\n * handlers and adapters all come from the runner context; failing branches and\n * the top level open by default. A name filter is always shown, and `actions`\n * sit in the tree toolbar beside it and Expand all / Collapse all.\n */\nexport function TestTree({ className, actions }: { className?: string; actions?: ReactNode }) {\n const runner = useTestRunner();\n return (\n <Tree<Test>\n className={cn(\"min-h-0\", className)}\n roots={runner.tests}\n getKey={nodeKey}\n getChildren={(node) => node.children}\n selected={runner.selected}\n onSelect={(node) => runner.onSelect(node === runner.selected ? null : node)}\n expandAll={runner.expandAll}\n onExpandAllChange={runner.onExpandAllChange}\n defaultOpen={(node, depth) => depth < 1 || hasFailed(node)}\n showSearch\n searchLabel=\"Filter tests\"\n getSearchText={(node) => `${node.name} ${node.framework ?? \"\"}`}\n renderRow={({ node, selected }) => <TestTreeNode node={node} selected={selected} />}\n actions={actions}\n />\n );\n}\n"],"names":[],"mappings":";;;;;;AAQA,MAAM,UAAW,uBAAM;AAIrB,QAAM,4BAAY,QAAA;AAClB,MAAI,UAAU;AACd,SAAO,CAAC,SAAuB;AAC7B,QAAI,KAAK,WAAY,QAAO,KAAK;AACjC,QAAI,MAAM,MAAM,IAAI,IAAI;AACxB,QAAI,CAAC,KAAK;AACR,YAAM,MAAM,SAAS,IAAI,KAAK,IAAI;AAClC,YAAM,IAAI,MAAM,GAAG;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AACF,GAAA;AAQO,SAAS,SAAS,EAAE,WAAW,WAAwD;AAC5F,QAAM,SAAS,cAAA;AACf,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,GAAG,WAAW,SAAS;AAAA,MAClC,OAAO,OAAO;AAAA,MACd,QAAQ;AAAA,MACR,aAAa,CAAC,SAAS,KAAK;AAAA,MAC5B,UAAU,OAAO;AAAA,MACjB,UAAU,CAAC,SAAS,OAAO,SAAS,SAAS,OAAO,WAAW,OAAO,IAAI;AAAA,MAC1E,WAAW,OAAO;AAAA,MAClB,mBAAmB,OAAO;AAAA,MAC1B,aAAa,CAAC,MAAM,UAAU,QAAQ,KAAK,UAAU,IAAI;AAAA,MACzD,YAAU;AAAA,MACV,aAAY;AAAA,MACZ,eAAe,CAAC,SAAS,GAAG,KAAK,IAAI,IAAI,KAAK,aAAa,EAAE;AAAA,MAC7D,WAAW,CAAC,EAAE,MAAM,eAAe,oBAAC,cAAA,EAAa,MAAY,UAAoB;AAAA,MACjF;AAAA,IAAA;AAAA,EAAA;AAGN;"}
|
|
@@ -7,7 +7,8 @@ const IconButton = require("../../components/IconButton.cjs");
|
|
|
7
7
|
const utils = require("../../lib/utils.cjs");
|
|
8
8
|
const context = require("./context.cjs");
|
|
9
9
|
const status = require("./status.cjs");
|
|
10
|
-
const
|
|
10
|
+
const MarkIcons = require("./MarkIcons.cjs");
|
|
11
|
+
const UiClass = require("../../icons/components/UiClass.cjs");
|
|
11
12
|
const UiStop = require("../../icons/components/UiStop.cjs");
|
|
12
13
|
const UiRefresh = require("../../icons/components/UiRefresh.cjs");
|
|
13
14
|
const NAME_TONE = {
|
|
@@ -26,6 +27,7 @@ function CountBadges({ node }) {
|
|
|
26
27
|
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-1", children: [
|
|
27
28
|
s.passed > 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge.Badge, { tone: "success", variant: "solid", size: "xxs", count: s.passed }),
|
|
28
29
|
s.failed > 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge.Badge, { tone: "danger", variant: "solid", size: "xxs", count: s.failed }),
|
|
30
|
+
s.warned > 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge.Badge, { tone: "warning", variant: "outline", size: "xxs", count: s.warned }),
|
|
29
31
|
s.timedout > 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge.Badge, { tone: "warning", variant: "solid", size: "xxs", count: s.timedout }),
|
|
30
32
|
s.skipped > 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge.Badge, { tone: "warning", variant: "soft", size: "xxs", count: s.skipped }),
|
|
31
33
|
s.running > 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge.Badge, { tone: "info", variant: "solid", size: "xxs", count: s.running }),
|
|
@@ -37,7 +39,7 @@ function TestTreeNode({ node, selected }) {
|
|
|
37
39
|
const runner = context.useTestRunner();
|
|
38
40
|
const hasChildren = (((_a = node.children) == null ? void 0 : _a.length) ?? 0) > 0;
|
|
39
41
|
const status$1 = status.testStatus(node);
|
|
40
|
-
const
|
|
42
|
+
const outcome = status.outcomeFor(node);
|
|
41
43
|
const fwAdapter = runner.adapters.resolveFrameworkIcon(node, runner);
|
|
42
44
|
const fwNode = (_b = fwAdapter == null ? void 0 : fwAdapter.renderFrameworkIcon) == null ? void 0 : _b.call(fwAdapter, { node, runner });
|
|
43
45
|
const leadingAdapter = runner.adapters.resolveRowLeading(node, runner);
|
|
@@ -46,24 +48,30 @@ function TestTreeNode({ node, selected }) {
|
|
|
46
48
|
const canStop = !!runner.onStop && !!node.can_stop && !!node.task_id;
|
|
47
49
|
const message = status$1 && MESSAGE_STATUSES.has(status$1) ? (node.message ?? "").trim() : "";
|
|
48
50
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
49
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon:
|
|
50
|
-
fwNode != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0 items-center text-sm
|
|
51
|
+
outcome ? /* @__PURE__ */ jsxRuntime.jsx(MarkIcons.OutcomeIcon, { outcome }) : /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiClass.UiClass, className: "shrink-0 text-muted-foreground" }),
|
|
52
|
+
fwNode != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0 items-center text-sm", children: fwNode }) : /* @__PURE__ */ jsxRuntime.jsx(MarkIcons.ToolIcon, { tool: node.framework, className: "text-sm" }),
|
|
51
53
|
(_c = leadingAdapter == null ? void 0 : leadingAdapter.renderRowLeading) == null ? void 0 : _c.call(leadingAdapter, { node, runner }),
|
|
52
|
-
/* @__PURE__ */ jsxRuntime.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
55
|
+
"span",
|
|
56
|
+
{
|
|
57
|
+
className: utils.cn(
|
|
58
|
+
"min-w-0 truncate",
|
|
59
|
+
selected ? "font-semibold" : "font-medium",
|
|
60
|
+
status$1 && NAME_TONE[status$1] || "text-foreground"
|
|
61
|
+
),
|
|
62
|
+
title: message || void 0,
|
|
63
|
+
children: status.humanizeName(node.name, node.framework)
|
|
64
|
+
}
|
|
65
|
+
),
|
|
66
|
+
message ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
67
|
+
"span",
|
|
68
|
+
{
|
|
69
|
+
className: "min-w-0 flex-1 shrink-[100] truncate text-xs text-muted-foreground",
|
|
70
|
+
title: message,
|
|
71
|
+
"data-row-message": "",
|
|
72
|
+
children: message
|
|
73
|
+
}
|
|
74
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1" }),
|
|
67
75
|
node.progress && node.progress.total > 0 && !node.passed && !node.failed && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-1 text-xs text-blue-600 dark:text-blue-400", children: [
|
|
68
76
|
node.progress.phase && /* @__PURE__ */ jsxRuntime.jsx("span", { children: node.progress.phase }),
|
|
69
77
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "tabular-nums", children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestTreeNode.cjs","sources":["../../../src/data/test-runner/TestTreeNode.tsx"],"sourcesContent":["import { Icon } from \"../Icon\";\nimport { Badge } from \"../Badge\";\nimport { IconButton } from \"../../components/IconButton\";\nimport { UiRefresh, UiStop } from \"../../icons\";\nimport { cn } from \"../../lib/utils\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport {\n formatTestDuration,\n humanizeName,\n
|
|
1
|
+
{"version":3,"file":"TestTreeNode.cjs","sources":["../../../src/data/test-runner/TestTreeNode.tsx"],"sourcesContent":["import { Icon } from \"../Icon\";\nimport { Badge } from \"../Badge\";\nimport { IconButton } from \"../../components/IconButton\";\nimport { UiClass, UiRefresh, UiStop } from \"../../icons\";\nimport { cn } from \"../../lib/utils\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport {\n formatTestDuration,\n humanizeName,\n outcomeFor,\n sum,\n testStatus,\n totalDuration,\n} from \"./status\";\nimport { OutcomeIcon, ToolIcon } from \"./MarkIcons\";\n\nconst NAME_TONE: Record<string, string> = {\n failed: \"text-red-600 dark:text-red-400\",\n timedout: \"text-amber-600 dark:text-amber-400\",\n warned: \"text-amber-600 dark:text-amber-400\",\n running: \"text-blue-600 dark:text-blue-400\",\n skipped: \"text-yellow-700 dark:text-yellow-500\",\n pending: \"text-muted-foreground\",\n passed: \"text-foreground\",\n};\n\nconst MESSAGE_STATUSES = new Set([\"failed\", \"timedout\", \"warned\", \"skipped\"]);\n\n/** Per-status roll-up count badges shown on a container row. */\nfunction CountBadges({ node }: { node: Test }) {\n const s = sum(node);\n if (s.total === 0) return null;\n return (\n <span className=\"flex shrink-0 items-center gap-1\">\n {s.passed > 0 && <Badge tone=\"success\" variant=\"solid\" size=\"xxs\" count={s.passed} />}\n {s.failed > 0 && <Badge tone=\"danger\" variant=\"solid\" size=\"xxs\" count={s.failed} />}\n {s.warned > 0 && <Badge tone=\"warning\" variant=\"outline\" size=\"xxs\" count={s.warned} />}\n {s.timedout > 0 && <Badge tone=\"warning\" variant=\"solid\" size=\"xxs\" count={s.timedout} />}\n {s.skipped > 0 && <Badge tone=\"warning\" variant=\"soft\" size=\"xxs\" count={s.skipped} />}\n {s.running > 0 && <Badge tone=\"info\" variant=\"solid\" size=\"xxs\" count={s.running} />}\n {s.pending > 0 && <Badge tone=\"neutral\" variant=\"soft\" size=\"xxs\" count={s.pending} />}\n </span>\n );\n}\n\n/**\n * Renders one test tree row: status icon, optional adapter decoration + framework\n * icon, status-colored name, duration, per-status count badges, and (when the\n * runner exposes the handlers) rerun/stop buttons. Designed as the `renderRow`\n * for the clicky `Tree`.\n */\nexport function TestTreeNode({ node, selected }: { node: Test; selected: boolean }) {\n const runner = useTestRunner();\n const hasChildren = (node.children?.length ?? 0) > 0;\n const status = testStatus(node);\n const outcome = outcomeFor(node);\n const fwAdapter = runner.adapters.resolveFrameworkIcon(node, runner);\n const fwNode = fwAdapter?.renderFrameworkIcon?.({ node, runner });\n const leadingAdapter = runner.adapters.resolveRowLeading(node, runner);\n const dur = node.duration || (hasChildren ? totalDuration(node) : 0);\n const canRerun = !!runner.onRerun && node.framework !== \"task\";\n const canStop = !!runner.onStop && !!node.can_stop && !!node.task_id;\n // A verdict line under the name for rows that need explaining; green,\n // running, and queued rows stay single-line.\n const message = status && MESSAGE_STATUSES.has(status) ? (node.message ?? \"\").trim() : \"\";\n\n return (\n <>\n {outcome ? (\n <OutcomeIcon outcome={outcome} />\n ) : (\n <Icon icon={UiClass} className=\"shrink-0 text-muted-foreground\" />\n )}\n\n {fwNode != null ? (\n <span className=\"flex shrink-0 items-center text-sm\">{fwNode}</span>\n ) : (\n <ToolIcon tool={node.framework} className=\"text-sm\" />\n )}\n\n {leadingAdapter?.renderRowLeading?.({ node, runner })}\n\n <span\n className={cn(\n \"min-w-0 truncate\",\n selected ? \"font-semibold\" : \"font-medium\",\n (status && NAME_TONE[status]) || \"text-foreground\",\n )}\n title={message || undefined}\n >\n {humanizeName(node.name, node.framework)}\n </span>\n {/* The verdict trails the name on the same line and gives way first. */}\n {message ? (\n <span\n className=\"min-w-0 flex-1 shrink-[100] truncate text-xs text-muted-foreground\"\n title={message}\n data-row-message=\"\"\n >\n {message}\n </span>\n ) : (\n <span className=\"flex-1\" />\n )}\n\n {node.progress && node.progress.total > 0 && !node.passed && !node.failed && (\n <span className=\"flex shrink-0 items-center gap-1 text-xs text-blue-600 dark:text-blue-400\">\n {node.progress.phase && <span>{node.progress.phase}</span>}\n <span className=\"tabular-nums\">\n {node.progress.done}/{node.progress.total}\n </span>\n </span>\n )}\n\n {dur > 0 && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{formatTestDuration(dur)}</span>\n )}\n\n {hasChildren && <CountBadges node={node} />}\n\n {canStop && (\n <IconButton\n icon={UiStop}\n label=\"Stop\"\n disabled={runner.busy.stop}\n onClick={(e) => {\n e.stopPropagation();\n runner.onStop!(node);\n }}\n />\n )}\n\n {canRerun && (\n <IconButton\n icon={UiRefresh}\n label=\"Rerun\"\n disabled={runner.busy.rerun}\n onClick={(e) => {\n e.stopPropagation();\n runner.onRerun!(node);\n }}\n />\n )}\n </>\n );\n}\n"],"names":["sum","jsxs","jsx","Badge","useTestRunner","status","testStatus","outcomeFor","totalDuration","Fragment","OutcomeIcon","Icon","UiClass","ToolIcon","cn","humanizeName","formatTestDuration","IconButton","UiStop","UiRefresh"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestTreeNode.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/TestTreeNode.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"TestTreeNode.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/TestTreeNode.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAyCpC;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,+BA8FjF"}
|
|
@@ -4,8 +4,9 @@ import { Badge } from "../Badge.js";
|
|
|
4
4
|
import { IconButton } from "../../components/IconButton.js";
|
|
5
5
|
import { cn } from "../../lib/utils.js";
|
|
6
6
|
import { useTestRunner } from "./context.js";
|
|
7
|
-
import { testStatus,
|
|
8
|
-
import {
|
|
7
|
+
import { testStatus, outcomeFor, totalDuration, humanizeName, formatTestDuration, sum } from "./status.js";
|
|
8
|
+
import { OutcomeIcon, ToolIcon } from "./MarkIcons.js";
|
|
9
|
+
import { UiClass } from "../../icons/components/UiClass.js";
|
|
9
10
|
import { UiStop } from "../../icons/components/UiStop.js";
|
|
10
11
|
import { UiRefresh } from "../../icons/components/UiRefresh.js";
|
|
11
12
|
const NAME_TONE = {
|
|
@@ -24,6 +25,7 @@ function CountBadges({ node }) {
|
|
|
24
25
|
return /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1", children: [
|
|
25
26
|
s.passed > 0 && /* @__PURE__ */ jsx(Badge, { tone: "success", variant: "solid", size: "xxs", count: s.passed }),
|
|
26
27
|
s.failed > 0 && /* @__PURE__ */ jsx(Badge, { tone: "danger", variant: "solid", size: "xxs", count: s.failed }),
|
|
28
|
+
s.warned > 0 && /* @__PURE__ */ jsx(Badge, { tone: "warning", variant: "outline", size: "xxs", count: s.warned }),
|
|
27
29
|
s.timedout > 0 && /* @__PURE__ */ jsx(Badge, { tone: "warning", variant: "solid", size: "xxs", count: s.timedout }),
|
|
28
30
|
s.skipped > 0 && /* @__PURE__ */ jsx(Badge, { tone: "warning", variant: "soft", size: "xxs", count: s.skipped }),
|
|
29
31
|
s.running > 0 && /* @__PURE__ */ jsx(Badge, { tone: "info", variant: "solid", size: "xxs", count: s.running }),
|
|
@@ -35,7 +37,7 @@ function TestTreeNode({ node, selected }) {
|
|
|
35
37
|
const runner = useTestRunner();
|
|
36
38
|
const hasChildren = (((_a = node.children) == null ? void 0 : _a.length) ?? 0) > 0;
|
|
37
39
|
const status = testStatus(node);
|
|
38
|
-
const
|
|
40
|
+
const outcome = outcomeFor(node);
|
|
39
41
|
const fwAdapter = runner.adapters.resolveFrameworkIcon(node, runner);
|
|
40
42
|
const fwNode = (_b = fwAdapter == null ? void 0 : fwAdapter.renderFrameworkIcon) == null ? void 0 : _b.call(fwAdapter, { node, runner });
|
|
41
43
|
const leadingAdapter = runner.adapters.resolveRowLeading(node, runner);
|
|
@@ -44,24 +46,30 @@ function TestTreeNode({ node, selected }) {
|
|
|
44
46
|
const canStop = !!runner.onStop && !!node.can_stop && !!node.task_id;
|
|
45
47
|
const message = status && MESSAGE_STATUSES.has(status) ? (node.message ?? "").trim() : "";
|
|
46
48
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
47
|
-
/* @__PURE__ */ jsx(Icon, { icon:
|
|
48
|
-
fwNode != null ? /* @__PURE__ */ jsx("span", { className: "flex shrink-0 items-center text-sm
|
|
49
|
+
outcome ? /* @__PURE__ */ jsx(OutcomeIcon, { outcome }) : /* @__PURE__ */ jsx(Icon, { icon: UiClass, className: "shrink-0 text-muted-foreground" }),
|
|
50
|
+
fwNode != null ? /* @__PURE__ */ jsx("span", { className: "flex shrink-0 items-center text-sm", children: fwNode }) : /* @__PURE__ */ jsx(ToolIcon, { tool: node.framework, className: "text-sm" }),
|
|
49
51
|
(_c = leadingAdapter == null ? void 0 : leadingAdapter.renderRowLeading) == null ? void 0 : _c.call(leadingAdapter, { node, runner }),
|
|
50
|
-
/* @__PURE__ */
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
52
|
+
/* @__PURE__ */ jsx(
|
|
53
|
+
"span",
|
|
54
|
+
{
|
|
55
|
+
className: cn(
|
|
56
|
+
"min-w-0 truncate",
|
|
57
|
+
selected ? "font-semibold" : "font-medium",
|
|
58
|
+
status && NAME_TONE[status] || "text-foreground"
|
|
59
|
+
),
|
|
60
|
+
title: message || void 0,
|
|
61
|
+
children: humanizeName(node.name, node.framework)
|
|
62
|
+
}
|
|
63
|
+
),
|
|
64
|
+
message ? /* @__PURE__ */ jsx(
|
|
65
|
+
"span",
|
|
66
|
+
{
|
|
67
|
+
className: "min-w-0 flex-1 shrink-[100] truncate text-xs text-muted-foreground",
|
|
68
|
+
title: message,
|
|
69
|
+
"data-row-message": "",
|
|
70
|
+
children: message
|
|
71
|
+
}
|
|
72
|
+
) : /* @__PURE__ */ jsx("span", { className: "flex-1" }),
|
|
65
73
|
node.progress && node.progress.total > 0 && !node.passed && !node.failed && /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1 text-xs text-blue-600 dark:text-blue-400", children: [
|
|
66
74
|
node.progress.phase && /* @__PURE__ */ jsx("span", { children: node.progress.phase }),
|
|
67
75
|
/* @__PURE__ */ jsxs("span", { className: "tabular-nums", children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestTreeNode.js","sources":["../../../src/data/test-runner/TestTreeNode.tsx"],"sourcesContent":["import { Icon } from \"../Icon\";\nimport { Badge } from \"../Badge\";\nimport { IconButton } from \"../../components/IconButton\";\nimport { UiRefresh, UiStop } from \"../../icons\";\nimport { cn } from \"../../lib/utils\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport {\n formatTestDuration,\n humanizeName,\n
|
|
1
|
+
{"version":3,"file":"TestTreeNode.js","sources":["../../../src/data/test-runner/TestTreeNode.tsx"],"sourcesContent":["import { Icon } from \"../Icon\";\nimport { Badge } from \"../Badge\";\nimport { IconButton } from \"../../components/IconButton\";\nimport { UiClass, UiRefresh, UiStop } from \"../../icons\";\nimport { cn } from \"../../lib/utils\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport {\n formatTestDuration,\n humanizeName,\n outcomeFor,\n sum,\n testStatus,\n totalDuration,\n} from \"./status\";\nimport { OutcomeIcon, ToolIcon } from \"./MarkIcons\";\n\nconst NAME_TONE: Record<string, string> = {\n failed: \"text-red-600 dark:text-red-400\",\n timedout: \"text-amber-600 dark:text-amber-400\",\n warned: \"text-amber-600 dark:text-amber-400\",\n running: \"text-blue-600 dark:text-blue-400\",\n skipped: \"text-yellow-700 dark:text-yellow-500\",\n pending: \"text-muted-foreground\",\n passed: \"text-foreground\",\n};\n\nconst MESSAGE_STATUSES = new Set([\"failed\", \"timedout\", \"warned\", \"skipped\"]);\n\n/** Per-status roll-up count badges shown on a container row. */\nfunction CountBadges({ node }: { node: Test }) {\n const s = sum(node);\n if (s.total === 0) return null;\n return (\n <span className=\"flex shrink-0 items-center gap-1\">\n {s.passed > 0 && <Badge tone=\"success\" variant=\"solid\" size=\"xxs\" count={s.passed} />}\n {s.failed > 0 && <Badge tone=\"danger\" variant=\"solid\" size=\"xxs\" count={s.failed} />}\n {s.warned > 0 && <Badge tone=\"warning\" variant=\"outline\" size=\"xxs\" count={s.warned} />}\n {s.timedout > 0 && <Badge tone=\"warning\" variant=\"solid\" size=\"xxs\" count={s.timedout} />}\n {s.skipped > 0 && <Badge tone=\"warning\" variant=\"soft\" size=\"xxs\" count={s.skipped} />}\n {s.running > 0 && <Badge tone=\"info\" variant=\"solid\" size=\"xxs\" count={s.running} />}\n {s.pending > 0 && <Badge tone=\"neutral\" variant=\"soft\" size=\"xxs\" count={s.pending} />}\n </span>\n );\n}\n\n/**\n * Renders one test tree row: status icon, optional adapter decoration + framework\n * icon, status-colored name, duration, per-status count badges, and (when the\n * runner exposes the handlers) rerun/stop buttons. Designed as the `renderRow`\n * for the clicky `Tree`.\n */\nexport function TestTreeNode({ node, selected }: { node: Test; selected: boolean }) {\n const runner = useTestRunner();\n const hasChildren = (node.children?.length ?? 0) > 0;\n const status = testStatus(node);\n const outcome = outcomeFor(node);\n const fwAdapter = runner.adapters.resolveFrameworkIcon(node, runner);\n const fwNode = fwAdapter?.renderFrameworkIcon?.({ node, runner });\n const leadingAdapter = runner.adapters.resolveRowLeading(node, runner);\n const dur = node.duration || (hasChildren ? totalDuration(node) : 0);\n const canRerun = !!runner.onRerun && node.framework !== \"task\";\n const canStop = !!runner.onStop && !!node.can_stop && !!node.task_id;\n // A verdict line under the name for rows that need explaining; green,\n // running, and queued rows stay single-line.\n const message = status && MESSAGE_STATUSES.has(status) ? (node.message ?? \"\").trim() : \"\";\n\n return (\n <>\n {outcome ? (\n <OutcomeIcon outcome={outcome} />\n ) : (\n <Icon icon={UiClass} className=\"shrink-0 text-muted-foreground\" />\n )}\n\n {fwNode != null ? (\n <span className=\"flex shrink-0 items-center text-sm\">{fwNode}</span>\n ) : (\n <ToolIcon tool={node.framework} className=\"text-sm\" />\n )}\n\n {leadingAdapter?.renderRowLeading?.({ node, runner })}\n\n <span\n className={cn(\n \"min-w-0 truncate\",\n selected ? \"font-semibold\" : \"font-medium\",\n (status && NAME_TONE[status]) || \"text-foreground\",\n )}\n title={message || undefined}\n >\n {humanizeName(node.name, node.framework)}\n </span>\n {/* The verdict trails the name on the same line and gives way first. */}\n {message ? (\n <span\n className=\"min-w-0 flex-1 shrink-[100] truncate text-xs text-muted-foreground\"\n title={message}\n data-row-message=\"\"\n >\n {message}\n </span>\n ) : (\n <span className=\"flex-1\" />\n )}\n\n {node.progress && node.progress.total > 0 && !node.passed && !node.failed && (\n <span className=\"flex shrink-0 items-center gap-1 text-xs text-blue-600 dark:text-blue-400\">\n {node.progress.phase && <span>{node.progress.phase}</span>}\n <span className=\"tabular-nums\">\n {node.progress.done}/{node.progress.total}\n </span>\n </span>\n )}\n\n {dur > 0 && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{formatTestDuration(dur)}</span>\n )}\n\n {hasChildren && <CountBadges node={node} />}\n\n {canStop && (\n <IconButton\n icon={UiStop}\n label=\"Stop\"\n disabled={runner.busy.stop}\n onClick={(e) => {\n e.stopPropagation();\n runner.onStop!(node);\n }}\n />\n )}\n\n {canRerun && (\n <IconButton\n icon={UiRefresh}\n label=\"Rerun\"\n disabled={runner.busy.rerun}\n onClick={(e) => {\n e.stopPropagation();\n runner.onRerun!(node);\n }}\n />\n )}\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
6
|
+
const copy = require("./copy.cjs");
|
|
6
7
|
class TestNodeAdapterRegistry {
|
|
7
8
|
constructor(adapters = []) {
|
|
8
9
|
__publicField(this, "adapters");
|
|
@@ -42,6 +43,16 @@ class TestNodeAdapterRegistry {
|
|
|
42
43
|
}
|
|
43
44
|
return tabs;
|
|
44
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Merge `copy` sections from every matching adapter, de-duplicated by fact
|
|
48
|
+
* label, section title and item label — the first contributor wins.
|
|
49
|
+
*/
|
|
50
|
+
resolveCopy(node, runner) {
|
|
51
|
+
const ctx = { node, runner };
|
|
52
|
+
return copy.mergeCopySections(
|
|
53
|
+
this.adapters.flatMap((a) => a.copy && a.match(node, runner) ? [a.copy(ctx)] : [])
|
|
54
|
+
);
|
|
55
|
+
}
|
|
45
56
|
/** True when the resolved detail adapter owns its own scroll region. */
|
|
46
57
|
ownsScroll(node, runner) {
|
|
47
58
|
const a = this.resolveDetail(node, runner);
|