@tianshu-ai/tianshu 0.3.0
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/LICENSE +200 -0
- package/README.md +284 -0
- package/README.zh-CN.md +136 -0
- package/bin/tianshu.mjs +32 -0
- package/package.json +60 -0
- package/packages/plugin-sdk/dist/agent-loop.d.ts +96 -0
- package/packages/plugin-sdk/dist/agent-loop.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/agent-loop.js +11 -0
- package/packages/plugin-sdk/dist/agent-loop.js.map +1 -0
- package/packages/plugin-sdk/dist/capabilities.d.ts +48 -0
- package/packages/plugin-sdk/dist/capabilities.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/capabilities.js +61 -0
- package/packages/plugin-sdk/dist/capabilities.js.map +1 -0
- package/packages/plugin-sdk/dist/catalog.d.ts +60 -0
- package/packages/plugin-sdk/dist/catalog.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/catalog.js +11 -0
- package/packages/plugin-sdk/dist/catalog.js.map +1 -0
- package/packages/plugin-sdk/dist/client.d.ts +171 -0
- package/packages/plugin-sdk/dist/client.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/client.js +96 -0
- package/packages/plugin-sdk/dist/client.js.map +1 -0
- package/packages/plugin-sdk/dist/index.d.ts +9 -0
- package/packages/plugin-sdk/dist/index.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/index.js +19 -0
- package/packages/plugin-sdk/dist/index.js.map +1 -0
- package/packages/plugin-sdk/dist/lsp.d.ts +32 -0
- package/packages/plugin-sdk/dist/lsp.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/lsp.js +19 -0
- package/packages/plugin-sdk/dist/lsp.js.map +1 -0
- package/packages/plugin-sdk/dist/manifest.d.ts +423 -0
- package/packages/plugin-sdk/dist/manifest.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/manifest.js +7 -0
- package/packages/plugin-sdk/dist/manifest.js.map +1 -0
- package/packages/plugin-sdk/dist/mcp-client.d.ts +74 -0
- package/packages/plugin-sdk/dist/mcp-client.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/mcp-client.js +226 -0
- package/packages/plugin-sdk/dist/mcp-client.js.map +1 -0
- package/packages/plugin-sdk/dist/mcp-fetch.d.ts +10 -0
- package/packages/plugin-sdk/dist/mcp-fetch.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/mcp-fetch.js +130 -0
- package/packages/plugin-sdk/dist/mcp-fetch.js.map +1 -0
- package/packages/plugin-sdk/dist/mcp-toolset.d.ts +128 -0
- package/packages/plugin-sdk/dist/mcp-toolset.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/mcp-toolset.js +246 -0
- package/packages/plugin-sdk/dist/mcp-toolset.js.map +1 -0
- package/packages/plugin-sdk/dist/server.d.ts +486 -0
- package/packages/plugin-sdk/dist/server.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/server.js +10 -0
- package/packages/plugin-sdk/dist/server.js.map +1 -0
- package/packages/plugin-sdk/dist/session-inbox.d.ts +56 -0
- package/packages/plugin-sdk/dist/session-inbox.d.ts.map +1 -0
- package/packages/plugin-sdk/dist/session-inbox.js +12 -0
- package/packages/plugin-sdk/dist/session-inbox.js.map +1 -0
- package/packages/plugin-sdk/package.json +36 -0
- package/packages/server/builtinConfig/plugins/README.md +1 -0
- package/packages/server/builtinConfig/plugins/files/manifest.json +100 -0
- package/packages/server/builtinConfig/plugins/files/skills/files-workspace-layout.md +29 -0
- package/packages/server/builtinConfig/plugins/microsandbox/manifest.json +177 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-browser-howto.md +155 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-build-use.md +201 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-config.md +38 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-exec-howto.md +144 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-libreoffice.md +159 -0
- package/packages/server/builtinConfig/plugins/microsandbox/skills/microsandbox-main-orchestration.md +75 -0
- package/packages/server/builtinConfig/plugins/microsandbox/templates/README.md +26 -0
- package/packages/server/builtinConfig/plugins/microsandbox/templates/browser.yaml +105 -0
- package/packages/server/builtinConfig/plugins/microsandbox/templates/task-runner-with-browser.yaml +80 -0
- package/packages/server/builtinConfig/plugins/microsandbox/templates/task-runner.yaml +80 -0
- package/packages/server/builtinConfig/plugins/web-search/manifest.json +65 -0
- package/packages/server/builtinConfig/plugins/web-search/skills/web-search-howto.md +69 -0
- package/packages/server/builtinConfig/plugins/workboard/agent-seeds/echo-demo/agent.json +7 -0
- package/packages/server/builtinConfig/plugins/workboard/agent-seeds/llm-default/SOUL.md +53 -0
- package/packages/server/builtinConfig/plugins/workboard/agent-seeds/llm-default/agent.json +7 -0
- package/packages/server/builtinConfig/plugins/workboard/manifest.json +180 -0
- package/packages/server/builtinConfig/plugins/workboard/skills/large-input-large-output.md +185 -0
- package/packages/server/builtinConfig/plugins/workboard/skills/workboard-howto.md +166 -0
- package/packages/server/builtinConfig/plugins/workboard/skills/worker-creator.md +267 -0
- package/packages/server/builtinConfig/plugins/workboard/skills/worker-fleet.md +431 -0
- package/packages/server/dist/catalog.d.ts +52 -0
- package/packages/server/dist/catalog.d.ts.map +1 -0
- package/packages/server/dist/catalog.js +189 -0
- package/packages/server/dist/catalog.js.map +1 -0
- package/packages/server/dist/chat/active-harnesses.d.ts +34 -0
- package/packages/server/dist/chat/active-harnesses.d.ts.map +1 -0
- package/packages/server/dist/chat/active-harnesses.js +118 -0
- package/packages/server/dist/chat/active-harnesses.js.map +1 -0
- package/packages/server/dist/chat/agent-loop.d.ts +64 -0
- package/packages/server/dist/chat/agent-loop.d.ts.map +1 -0
- package/packages/server/dist/chat/agent-loop.js +597 -0
- package/packages/server/dist/chat/agent-loop.js.map +1 -0
- package/packages/server/dist/chat/agent-tool-adapter.d.ts +33 -0
- package/packages/server/dist/chat/agent-tool-adapter.d.ts.map +1 -0
- package/packages/server/dist/chat/agent-tool-adapter.js +260 -0
- package/packages/server/dist/chat/agent-tool-adapter.js.map +1 -0
- package/packages/server/dist/chat/compact.d.ts +52 -0
- package/packages/server/dist/chat/compact.d.ts.map +1 -0
- package/packages/server/dist/chat/compact.js +248 -0
- package/packages/server/dist/chat/compact.js.map +1 -0
- package/packages/server/dist/chat/dump-system-prompt.d.ts +17 -0
- package/packages/server/dist/chat/dump-system-prompt.d.ts.map +1 -0
- package/packages/server/dist/chat/dump-system-prompt.js +58 -0
- package/packages/server/dist/chat/dump-system-prompt.js.map +1 -0
- package/packages/server/dist/chat/handler.d.ts +186 -0
- package/packages/server/dist/chat/handler.d.ts.map +1 -0
- package/packages/server/dist/chat/handler.js +1248 -0
- package/packages/server/dist/chat/handler.js.map +1 -0
- package/packages/server/dist/chat/image-fit.d.ts +34 -0
- package/packages/server/dist/chat/image-fit.d.ts.map +1 -0
- package/packages/server/dist/chat/image-fit.js +157 -0
- package/packages/server/dist/chat/image-fit.js.map +1 -0
- package/packages/server/dist/chat/messages.d.ts +118 -0
- package/packages/server/dist/chat/messages.d.ts.map +1 -0
- package/packages/server/dist/chat/messages.js +341 -0
- package/packages/server/dist/chat/messages.js.map +1 -0
- package/packages/server/dist/chat/session-inbox.d.ts +114 -0
- package/packages/server/dist/chat/session-inbox.d.ts.map +1 -0
- package/packages/server/dist/chat/session-inbox.js +418 -0
- package/packages/server/dist/chat/session-inbox.js.map +1 -0
- package/packages/server/dist/chat/sqlite-session-repo.d.ts +26 -0
- package/packages/server/dist/chat/sqlite-session-repo.d.ts.map +1 -0
- package/packages/server/dist/chat/sqlite-session-repo.js +132 -0
- package/packages/server/dist/chat/sqlite-session-repo.js.map +1 -0
- package/packages/server/dist/chat/sqlite-session-storage.d.ts +83 -0
- package/packages/server/dist/chat/sqlite-session-storage.d.ts.map +1 -0
- package/packages/server/dist/chat/sqlite-session-storage.js +418 -0
- package/packages/server/dist/chat/sqlite-session-storage.js.map +1 -0
- package/packages/server/dist/chat/stub-execution-env.d.ts +3 -0
- package/packages/server/dist/chat/stub-execution-env.d.ts.map +1 -0
- package/packages/server/dist/chat/stub-execution-env.js +87 -0
- package/packages/server/dist/chat/stub-execution-env.js.map +1 -0
- package/packages/server/dist/chat/token-estimate.d.ts +11 -0
- package/packages/server/dist/chat/token-estimate.d.ts.map +1 -0
- package/packages/server/dist/chat/token-estimate.js +67 -0
- package/packages/server/dist/chat/token-estimate.js.map +1 -0
- package/packages/server/dist/chat/ws-protocol.d.ts +244 -0
- package/packages/server/dist/chat/ws-protocol.d.ts.map +1 -0
- package/packages/server/dist/chat/ws-protocol.js +193 -0
- package/packages/server/dist/chat/ws-protocol.js.map +1 -0
- package/packages/server/dist/cli.d.ts +9 -0
- package/packages/server/dist/cli.d.ts.map +1 -0
- package/packages/server/dist/cli.js +329 -0
- package/packages/server/dist/cli.js.map +1 -0
- package/packages/server/dist/core/agent-seeds.d.ts +25 -0
- package/packages/server/dist/core/agent-seeds.d.ts.map +1 -0
- package/packages/server/dist/core/agent-seeds.js +69 -0
- package/packages/server/dist/core/agent-seeds.js.map +1 -0
- package/packages/server/dist/core/config.d.ts +172 -0
- package/packages/server/dist/core/config.d.ts.map +1 -0
- package/packages/server/dist/core/config.js +155 -0
- package/packages/server/dist/core/config.js.map +1 -0
- package/packages/server/dist/core/db-pool.d.ts +32 -0
- package/packages/server/dist/core/db-pool.d.ts.map +1 -0
- package/packages/server/dist/core/db-pool.js +108 -0
- package/packages/server/dist/core/db-pool.js.map +1 -0
- package/packages/server/dist/core/dev-mode.d.ts +13 -0
- package/packages/server/dist/core/dev-mode.d.ts.map +1 -0
- package/packages/server/dist/core/dev-mode.js +51 -0
- package/packages/server/dist/core/dev-mode.js.map +1 -0
- package/packages/server/dist/core/global-ops.d.ts +54 -0
- package/packages/server/dist/core/global-ops.d.ts.map +1 -0
- package/packages/server/dist/core/global-ops.js +143 -0
- package/packages/server/dist/core/global-ops.js.map +1 -0
- package/packages/server/dist/core/identity-resolvers.d.ts +102 -0
- package/packages/server/dist/core/identity-resolvers.d.ts.map +1 -0
- package/packages/server/dist/core/identity-resolvers.js +176 -0
- package/packages/server/dist/core/identity-resolvers.js.map +1 -0
- package/packages/server/dist/core/index.d.ts +13 -0
- package/packages/server/dist/core/index.d.ts.map +1 -0
- package/packages/server/dist/core/index.js +18 -0
- package/packages/server/dist/core/index.js.map +1 -0
- package/packages/server/dist/core/llm.d.ts +45 -0
- package/packages/server/dist/core/llm.d.ts.map +1 -0
- package/packages/server/dist/core/llm.js +140 -0
- package/packages/server/dist/core/llm.js.map +1 -0
- package/packages/server/dist/core/mcp-manager.d.ts +47 -0
- package/packages/server/dist/core/mcp-manager.d.ts.map +1 -0
- package/packages/server/dist/core/mcp-manager.js +129 -0
- package/packages/server/dist/core/mcp-manager.js.map +1 -0
- package/packages/server/dist/core/middleware.d.ts +31 -0
- package/packages/server/dist/core/middleware.d.ts.map +1 -0
- package/packages/server/dist/core/middleware.js +102 -0
- package/packages/server/dist/core/middleware.js.map +1 -0
- package/packages/server/dist/core/migrations/001-initial.d.ts +4 -0
- package/packages/server/dist/core/migrations/001-initial.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/001-initial.js +66 -0
- package/packages/server/dist/core/migrations/001-initial.js.map +1 -0
- package/packages/server/dist/core/migrations/002-task-dependencies.d.ts +4 -0
- package/packages/server/dist/core/migrations/002-task-dependencies.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/002-task-dependencies.js +20 -0
- package/packages/server/dist/core/migrations/002-task-dependencies.js.map +1 -0
- package/packages/server/dist/core/migrations/003-session-tree.d.ts +4 -0
- package/packages/server/dist/core/migrations/003-session-tree.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/003-session-tree.js +96 -0
- package/packages/server/dist/core/migrations/003-session-tree.js.map +1 -0
- package/packages/server/dist/core/migrations/003-worker-agents.d.ts +4 -0
- package/packages/server/dist/core/migrations/003-worker-agents.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/003-worker-agents.js +65 -0
- package/packages/server/dist/core/migrations/003-worker-agents.js.map +1 -0
- package/packages/server/dist/core/migrations/004-rebuild-message-chain.d.ts +4 -0
- package/packages/server/dist/core/migrations/004-rebuild-message-chain.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/004-rebuild-message-chain.js +52 -0
- package/packages/server/dist/core/migrations/004-rebuild-message-chain.js.map +1 -0
- package/packages/server/dist/core/migrations/005-task-status-rename.d.ts +4 -0
- package/packages/server/dist/core/migrations/005-task-status-rename.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/005-task-status-rename.js +64 -0
- package/packages/server/dist/core/migrations/005-task-status-rename.js.map +1 -0
- package/packages/server/dist/core/migrations/006-task-labels.d.ts +4 -0
- package/packages/server/dist/core/migrations/006-task-labels.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/006-task-labels.js +43 -0
- package/packages/server/dist/core/migrations/006-task-labels.js.map +1 -0
- package/packages/server/dist/core/migrations/007-session-inbox.d.ts +4 -0
- package/packages/server/dist/core/migrations/007-session-inbox.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/007-session-inbox.js +67 -0
- package/packages/server/dist/core/migrations/007-session-inbox.js.map +1 -0
- package/packages/server/dist/core/migrations/008-task-intervention.d.ts +4 -0
- package/packages/server/dist/core/migrations/008-task-intervention.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/008-task-intervention.js +60 -0
- package/packages/server/dist/core/migrations/008-task-intervention.js.map +1 -0
- package/packages/server/dist/core/migrations/index.d.ts +12 -0
- package/packages/server/dist/core/migrations/index.d.ts.map +1 -0
- package/packages/server/dist/core/migrations/index.js +58 -0
- package/packages/server/dist/core/migrations/index.js.map +1 -0
- package/packages/server/dist/core/paths.d.ts +53 -0
- package/packages/server/dist/core/paths.d.ts.map +1 -0
- package/packages/server/dist/core/paths.js +125 -0
- package/packages/server/dist/core/paths.js.map +1 -0
- package/packages/server/dist/core/plugins/builtin-loader.d.ts +56 -0
- package/packages/server/dist/core/plugins/builtin-loader.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/builtin-loader.js +153 -0
- package/packages/server/dist/core/plugins/builtin-loader.js.map +1 -0
- package/packages/server/dist/core/plugins/discovery.d.ts +28 -0
- package/packages/server/dist/core/plugins/discovery.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/discovery.js +97 -0
- package/packages/server/dist/core/plugins/discovery.js.map +1 -0
- package/packages/server/dist/core/plugins/index.d.ts +6 -0
- package/packages/server/dist/core/plugins/index.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/index.js +6 -0
- package/packages/server/dist/core/plugins/index.js.map +1 -0
- package/packages/server/dist/core/plugins/manifest.d.ts +9 -0
- package/packages/server/dist/core/plugins/manifest.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/manifest.js +584 -0
- package/packages/server/dist/core/plugins/manifest.js.map +1 -0
- package/packages/server/dist/core/plugins/registry.d.ts +269 -0
- package/packages/server/dist/core/plugins/registry.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/registry.js +1003 -0
- package/packages/server/dist/core/plugins/registry.js.map +1 -0
- package/packages/server/dist/core/plugins/secrets.d.ts +46 -0
- package/packages/server/dist/core/plugins/secrets.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/secrets.js +174 -0
- package/packages/server/dist/core/plugins/secrets.js.map +1 -0
- package/packages/server/dist/core/plugins/skills.d.ts +131 -0
- package/packages/server/dist/core/plugins/skills.d.ts.map +1 -0
- package/packages/server/dist/core/plugins/skills.js +389 -0
- package/packages/server/dist/core/plugins/skills.js.map +1 -0
- package/packages/server/dist/core/templates.d.ts +28 -0
- package/packages/server/dist/core/templates.d.ts.map +1 -0
- package/packages/server/dist/core/templates.js +103 -0
- package/packages/server/dist/core/templates.js.map +1 -0
- package/packages/server/dist/core/tenant-context.d.ts +18 -0
- package/packages/server/dist/core/tenant-context.d.ts.map +1 -0
- package/packages/server/dist/core/tenant-context.js +42 -0
- package/packages/server/dist/core/tenant-context.js.map +1 -0
- package/packages/server/dist/core/tenant-id.d.ts +8 -0
- package/packages/server/dist/core/tenant-id.d.ts.map +1 -0
- package/packages/server/dist/core/tenant-id.js +53 -0
- package/packages/server/dist/core/tenant-id.js.map +1 -0
- package/packages/server/dist/core/tenant-skills.d.ts +29 -0
- package/packages/server/dist/core/tenant-skills.d.ts.map +1 -0
- package/packages/server/dist/core/tenant-skills.js +77 -0
- package/packages/server/dist/core/tenant-skills.js.map +1 -0
- package/packages/server/dist/core/worker-agents-fs.d.ts +44 -0
- package/packages/server/dist/core/worker-agents-fs.d.ts.map +1 -0
- package/packages/server/dist/core/worker-agents-fs.js +86 -0
- package/packages/server/dist/core/worker-agents-fs.js.map +1 -0
- package/packages/server/dist/core/worker-agents.d.ts +77 -0
- package/packages/server/dist/core/worker-agents.d.ts.map +1 -0
- package/packages/server/dist/core/worker-agents.js +191 -0
- package/packages/server/dist/core/worker-agents.js.map +1 -0
- package/packages/server/dist/index.d.ts +2 -0
- package/packages/server/dist/index.d.ts.map +1 -0
- package/packages/server/dist/index.js +623 -0
- package/packages/server/dist/index.js.map +1 -0
- package/packages/server/dist/lsp/client.d.ts +53 -0
- package/packages/server/dist/lsp/client.d.ts.map +1 -0
- package/packages/server/dist/lsp/client.js +258 -0
- package/packages/server/dist/lsp/client.js.map +1 -0
- package/packages/server/dist/lsp/format.d.ts +13 -0
- package/packages/server/dist/lsp/format.d.ts.map +1 -0
- package/packages/server/dist/lsp/format.js +55 -0
- package/packages/server/dist/lsp/format.js.map +1 -0
- package/packages/server/dist/lsp/index.d.ts +20 -0
- package/packages/server/dist/lsp/index.d.ts.map +1 -0
- package/packages/server/dist/lsp/index.js +32 -0
- package/packages/server/dist/lsp/index.js.map +1 -0
- package/packages/server/dist/lsp/language-registry.d.ts +29 -0
- package/packages/server/dist/lsp/language-registry.d.ts.map +1 -0
- package/packages/server/dist/lsp/language-registry.js +62 -0
- package/packages/server/dist/lsp/language-registry.js.map +1 -0
- package/packages/server/dist/lsp/manager.d.ts +77 -0
- package/packages/server/dist/lsp/manager.d.ts.map +1 -0
- package/packages/server/dist/lsp/manager.js +300 -0
- package/packages/server/dist/lsp/manager.js.map +1 -0
- package/packages/server/dist/plugins-routes.d.ts +96 -0
- package/packages/server/dist/plugins-routes.d.ts.map +1 -0
- package/packages/server/dist/plugins-routes.js +627 -0
- package/packages/server/dist/plugins-routes.js.map +1 -0
- package/packages/server/dist/setup/checks/config.d.ts +9 -0
- package/packages/server/dist/setup/checks/config.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/config.js +66 -0
- package/packages/server/dist/setup/checks/config.js.map +1 -0
- package/packages/server/dist/setup/checks/db.d.ts +6 -0
- package/packages/server/dist/setup/checks/db.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/db.js +79 -0
- package/packages/server/dist/setup/checks/db.js.map +1 -0
- package/packages/server/dist/setup/checks/known-models.d.ts +18 -0
- package/packages/server/dist/setup/checks/known-models.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/known-models.js +119 -0
- package/packages/server/dist/setup/checks/known-models.js.map +1 -0
- package/packages/server/dist/setup/checks/network.d.ts +11 -0
- package/packages/server/dist/setup/checks/network.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/network.js +176 -0
- package/packages/server/dist/setup/checks/network.js.map +1 -0
- package/packages/server/dist/setup/checks/plugins.d.ts +9 -0
- package/packages/server/dist/setup/checks/plugins.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/plugins.js +194 -0
- package/packages/server/dist/setup/checks/plugins.js.map +1 -0
- package/packages/server/dist/setup/checks/providers.d.ts +12 -0
- package/packages/server/dist/setup/checks/providers.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/providers.js +368 -0
- package/packages/server/dist/setup/checks/providers.js.map +1 -0
- package/packages/server/dist/setup/checks/runtime.d.ts +3 -0
- package/packages/server/dist/setup/checks/runtime.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/runtime.js +44 -0
- package/packages/server/dist/setup/checks/runtime.js.map +1 -0
- package/packages/server/dist/setup/checks/sandbox.d.ts +9 -0
- package/packages/server/dist/setup/checks/sandbox.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/sandbox.js +110 -0
- package/packages/server/dist/setup/checks/sandbox.js.map +1 -0
- package/packages/server/dist/setup/checks/tenants.d.ts +9 -0
- package/packages/server/dist/setup/checks/tenants.d.ts.map +1 -0
- package/packages/server/dist/setup/checks/tenants.js +509 -0
- package/packages/server/dist/setup/checks/tenants.js.map +1 -0
- package/packages/server/dist/setup/cli-agent.d.ts +39 -0
- package/packages/server/dist/setup/cli-agent.d.ts.map +1 -0
- package/packages/server/dist/setup/cli-agent.js +1353 -0
- package/packages/server/dist/setup/cli-agent.js.map +1 -0
- package/packages/server/dist/setup/doctor.d.ts +32 -0
- package/packages/server/dist/setup/doctor.d.ts.map +1 -0
- package/packages/server/dist/setup/doctor.js +80 -0
- package/packages/server/dist/setup/doctor.js.map +1 -0
- package/packages/server/dist/setup/launchd.d.ts +107 -0
- package/packages/server/dist/setup/launchd.d.ts.map +1 -0
- package/packages/server/dist/setup/launchd.js +309 -0
- package/packages/server/dist/setup/launchd.js.map +1 -0
- package/packages/server/dist/setup/load-env.d.ts +21 -0
- package/packages/server/dist/setup/load-env.d.ts.map +1 -0
- package/packages/server/dist/setup/load-env.js +88 -0
- package/packages/server/dist/setup/load-env.js.map +1 -0
- package/packages/server/dist/setup/probe-default-model.d.ts +28 -0
- package/packages/server/dist/setup/probe-default-model.d.ts.map +1 -0
- package/packages/server/dist/setup/probe-default-model.js +133 -0
- package/packages/server/dist/setup/probe-default-model.js.map +1 -0
- package/packages/server/dist/setup/render.d.ts +28 -0
- package/packages/server/dist/setup/render.d.ts.map +1 -0
- package/packages/server/dist/setup/render.js +60 -0
- package/packages/server/dist/setup/render.js.map +1 -0
- package/packages/server/dist/setup/repo-root.d.ts +3 -0
- package/packages/server/dist/setup/repo-root.d.ts.map +1 -0
- package/packages/server/dist/setup/repo-root.js +43 -0
- package/packages/server/dist/setup/repo-root.js.map +1 -0
- package/packages/server/dist/setup/service.d.ts +60 -0
- package/packages/server/dist/setup/service.d.ts.map +1 -0
- package/packages/server/dist/setup/service.js +345 -0
- package/packages/server/dist/setup/service.js.map +1 -0
- package/packages/server/dist/setup/start-server.d.ts +23 -0
- package/packages/server/dist/setup/start-server.d.ts.map +1 -0
- package/packages/server/dist/setup/start-server.js +465 -0
- package/packages/server/dist/setup/start-server.js.map +1 -0
- package/packages/server/dist/setup/wizard.d.ts +59 -0
- package/packages/server/dist/setup/wizard.d.ts.map +1 -0
- package/packages/server/dist/setup/wizard.js +556 -0
- package/packages/server/dist/setup/wizard.js.map +1 -0
- package/packages/server/dist/tools/edit-file.d.ts +13 -0
- package/packages/server/dist/tools/edit-file.d.ts.map +1 -0
- package/packages/server/dist/tools/edit-file.js +90 -0
- package/packages/server/dist/tools/edit-file.js.map +1 -0
- package/packages/server/dist/tools/glob.d.ts +12 -0
- package/packages/server/dist/tools/glob.d.ts.map +1 -0
- package/packages/server/dist/tools/glob.js +82 -0
- package/packages/server/dist/tools/glob.js.map +1 -0
- package/packages/server/dist/tools/index.d.ts +82 -0
- package/packages/server/dist/tools/index.d.ts.map +1 -0
- package/packages/server/dist/tools/index.js +72 -0
- package/packages/server/dist/tools/index.js.map +1 -0
- package/packages/server/dist/tools/list-dir.d.ts +24 -0
- package/packages/server/dist/tools/list-dir.d.ts.map +1 -0
- package/packages/server/dist/tools/list-dir.js +99 -0
- package/packages/server/dist/tools/list-dir.js.map +1 -0
- package/packages/server/dist/tools/path-helper.d.ts +15 -0
- package/packages/server/dist/tools/path-helper.d.ts.map +1 -0
- package/packages/server/dist/tools/path-helper.js +72 -0
- package/packages/server/dist/tools/path-helper.js.map +1 -0
- package/packages/server/dist/tools/read-file.d.ts +17 -0
- package/packages/server/dist/tools/read-file.d.ts.map +1 -0
- package/packages/server/dist/tools/read-file.js +94 -0
- package/packages/server/dist/tools/read-file.js.map +1 -0
- package/packages/server/dist/tools/sandbox.d.ts +57 -0
- package/packages/server/dist/tools/sandbox.d.ts.map +1 -0
- package/packages/server/dist/tools/sandbox.js +291 -0
- package/packages/server/dist/tools/sandbox.js.map +1 -0
- package/packages/server/dist/tools/write-file.d.ts +12 -0
- package/packages/server/dist/tools/write-file.d.ts.map +1 -0
- package/packages/server/dist/tools/write-file.js +67 -0
- package/packages/server/dist/tools/write-file.js.map +1 -0
- package/packages/server/dist/worker-agents-routes.d.ts +11 -0
- package/packages/server/dist/worker-agents-routes.d.ts.map +1 -0
- package/packages/server/dist/worker-agents-routes.js +253 -0
- package/packages/server/dist/worker-agents-routes.js.map +1 -0
- package/packages/server/package.json +41 -0
- package/packages/web/dist/assets/index-DH-gJ09_.js +60 -0
- package/packages/web/dist/assets/index-xU4lYYqY.css +2 -0
- package/packages/web/dist/index.html +14 -0
- package/packages/web/package.json +36 -0
- package/plugins/README.md +64 -0
- package/plugins/files/dist/client.d.ts +5 -0
- package/plugins/files/dist/client.d.ts.map +1 -0
- package/plugins/files/dist/client.js +354 -0
- package/plugins/files/dist/client.js.map +1 -0
- package/plugins/files/dist/server.d.ts +32 -0
- package/plugins/files/dist/server.d.ts.map +1 -0
- package/plugins/files/dist/server.js +514 -0
- package/plugins/files/dist/server.js.map +1 -0
- package/plugins/files/dist/tools/edit-file.d.ts +29 -0
- package/plugins/files/dist/tools/edit-file.d.ts.map +1 -0
- package/plugins/files/dist/tools/edit-file.js +230 -0
- package/plugins/files/dist/tools/edit-file.js.map +1 -0
- package/plugins/files/dist/tools/edit-file.prompt.md +36 -0
- package/plugins/files/dist/tools/glob.d.ts +12 -0
- package/plugins/files/dist/tools/glob.d.ts.map +1 -0
- package/plugins/files/dist/tools/glob.js +84 -0
- package/plugins/files/dist/tools/glob.js.map +1 -0
- package/plugins/files/dist/tools/index.d.ts +13 -0
- package/plugins/files/dist/tools/index.d.ts.map +1 -0
- package/plugins/files/dist/tools/index.js +158 -0
- package/plugins/files/dist/tools/index.js.map +1 -0
- package/plugins/files/dist/tools/list-dir.d.ts +24 -0
- package/plugins/files/dist/tools/list-dir.d.ts.map +1 -0
- package/plugins/files/dist/tools/list-dir.js +104 -0
- package/plugins/files/dist/tools/list-dir.js.map +1 -0
- package/plugins/files/dist/tools/load-prompt.d.ts +5 -0
- package/plugins/files/dist/tools/load-prompt.d.ts.map +1 -0
- package/plugins/files/dist/tools/load-prompt.js +39 -0
- package/plugins/files/dist/tools/load-prompt.js.map +1 -0
- package/plugins/files/dist/tools/path-helper.d.ts +32 -0
- package/plugins/files/dist/tools/path-helper.d.ts.map +1 -0
- package/plugins/files/dist/tools/path-helper.js +113 -0
- package/plugins/files/dist/tools/path-helper.js.map +1 -0
- package/plugins/files/dist/tools/read-file.d.ts +17 -0
- package/plugins/files/dist/tools/read-file.d.ts.map +1 -0
- package/plugins/files/dist/tools/read-file.js +109 -0
- package/plugins/files/dist/tools/read-file.js.map +1 -0
- package/plugins/files/dist/tools/read-tracker.d.ts +28 -0
- package/plugins/files/dist/tools/read-tracker.d.ts.map +1 -0
- package/plugins/files/dist/tools/read-tracker.js +135 -0
- package/plugins/files/dist/tools/read-tracker.js.map +1 -0
- package/plugins/files/dist/tools/replacers.d.ts +27 -0
- package/plugins/files/dist/tools/replacers.d.ts.map +1 -0
- package/plugins/files/dist/tools/replacers.js +221 -0
- package/plugins/files/dist/tools/replacers.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-delete.d.ts +12 -0
- package/plugins/files/dist/tools/tenant-config-delete.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-delete.js +70 -0
- package/plugins/files/dist/tools/tenant-config-delete.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-edit.d.ts +25 -0
- package/plugins/files/dist/tools/tenant-config-edit.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-edit.js +142 -0
- package/plugins/files/dist/tools/tenant-config-edit.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-glob.d.ts +12 -0
- package/plugins/files/dist/tools/tenant-config-glob.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-glob.js +64 -0
- package/plugins/files/dist/tools/tenant-config-glob.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-helper.d.ts +64 -0
- package/plugins/files/dist/tools/tenant-config-helper.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-helper.js +162 -0
- package/plugins/files/dist/tools/tenant-config-helper.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-list.d.ts +20 -0
- package/plugins/files/dist/tools/tenant-config-list.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-list.js +95 -0
- package/plugins/files/dist/tools/tenant-config-list.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-read.d.ts +17 -0
- package/plugins/files/dist/tools/tenant-config-read.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-read.js +87 -0
- package/plugins/files/dist/tools/tenant-config-read.js.map +1 -0
- package/plugins/files/dist/tools/tenant-config-write.d.ts +14 -0
- package/plugins/files/dist/tools/tenant-config-write.d.ts.map +1 -0
- package/plugins/files/dist/tools/tenant-config-write.js +78 -0
- package/plugins/files/dist/tools/tenant-config-write.js.map +1 -0
- package/plugins/files/dist/tools/text-shape.d.ts +20 -0
- package/plugins/files/dist/tools/text-shape.d.ts.map +1 -0
- package/plugins/files/dist/tools/text-shape.js +57 -0
- package/plugins/files/dist/tools/text-shape.js.map +1 -0
- package/plugins/files/dist/tools/write-file.d.ts +12 -0
- package/plugins/files/dist/tools/write-file.d.ts.map +1 -0
- package/plugins/files/dist/tools/write-file.js +89 -0
- package/plugins/files/dist/tools/write-file.js.map +1 -0
- package/plugins/files/dist/tools/write-file.prompt.md +14 -0
- package/plugins/files/manifest.json +100 -0
- package/plugins/files/package.json +39 -0
- package/plugins/files/skills/files-workspace-layout.md +29 -0
- package/plugins/microsandbox/dist/admin/browser-routes.d.ts +41 -0
- package/plugins/microsandbox/dist/admin/browser-routes.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin/browser-routes.js +208 -0
- package/plugins/microsandbox/dist/admin/browser-routes.js.map +1 -0
- package/plugins/microsandbox/dist/admin/preview-exec.d.ts +38 -0
- package/plugins/microsandbox/dist/admin/preview-exec.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin/preview-exec.js +185 -0
- package/plugins/microsandbox/dist/admin/preview-exec.js.map +1 -0
- package/plugins/microsandbox/dist/admin/routes.d.ts +35 -0
- package/plugins/microsandbox/dist/admin/routes.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin/routes.js +728 -0
- package/plugins/microsandbox/dist/admin/routes.js.map +1 -0
- package/plugins/microsandbox/dist/admin/sandboxfile-io.d.ts +11 -0
- package/plugins/microsandbox/dist/admin/sandboxfile-io.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin/sandboxfile-io.js +72 -0
- package/plugins/microsandbox/dist/admin/sandboxfile-io.js.map +1 -0
- package/plugins/microsandbox/dist/admin/templates.d.ts +16 -0
- package/plugins/microsandbox/dist/admin/templates.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin/templates.js +66 -0
- package/plugins/microsandbox/dist/admin/templates.js.map +1 -0
- package/plugins/microsandbox/dist/admin.d.ts +5 -0
- package/plugins/microsandbox/dist/admin.d.ts.map +1 -0
- package/plugins/microsandbox/dist/admin.js +256 -0
- package/plugins/microsandbox/dist/admin.js.map +1 -0
- package/plugins/microsandbox/dist/build/builder.d.ts +69 -0
- package/plugins/microsandbox/dist/build/builder.d.ts.map +1 -0
- package/plugins/microsandbox/dist/build/builder.js +257 -0
- package/plugins/microsandbox/dist/build/builder.js.map +1 -0
- package/plugins/microsandbox/dist/build/metadata.d.ts +27 -0
- package/plugins/microsandbox/dist/build/metadata.d.ts.map +1 -0
- package/plugins/microsandbox/dist/build/metadata.js +55 -0
- package/plugins/microsandbox/dist/build/metadata.js.map +1 -0
- package/plugins/microsandbox/dist/build/pointer.d.ts +51 -0
- package/plugins/microsandbox/dist/build/pointer.d.ts.map +1 -0
- package/plugins/microsandbox/dist/build/pointer.js +130 -0
- package/plugins/microsandbox/dist/build/pointer.js.map +1 -0
- package/plugins/microsandbox/dist/build/sandboxfile.d.ts +15 -0
- package/plugins/microsandbox/dist/build/sandboxfile.d.ts.map +1 -0
- package/plugins/microsandbox/dist/build/sandboxfile.js +176 -0
- package/plugins/microsandbox/dist/build/sandboxfile.js.map +1 -0
- package/plugins/microsandbox/dist/client.d.ts +5 -0
- package/plugins/microsandbox/dist/client.d.ts.map +1 -0
- package/plugins/microsandbox/dist/client.js +941 -0
- package/plugins/microsandbox/dist/client.js.map +1 -0
- package/plugins/microsandbox/dist/runner/browser.d.ts +50 -0
- package/plugins/microsandbox/dist/runner/browser.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/browser.js +142 -0
- package/plugins/microsandbox/dist/runner/browser.js.map +1 -0
- package/plugins/microsandbox/dist/runner/free-port.d.ts +6 -0
- package/plugins/microsandbox/dist/runner/free-port.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/free-port.js +53 -0
- package/plugins/microsandbox/dist/runner/free-port.js.map +1 -0
- package/plugins/microsandbox/dist/runner/index.d.ts +28 -0
- package/plugins/microsandbox/dist/runner/index.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/index.js +72 -0
- package/plugins/microsandbox/dist/runner/index.js.map +1 -0
- package/plugins/microsandbox/dist/runner/microsandbox.d.ts +64 -0
- package/plugins/microsandbox/dist/runner/microsandbox.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/microsandbox.js +668 -0
- package/plugins/microsandbox/dist/runner/microsandbox.js.map +1 -0
- package/plugins/microsandbox/dist/runner/nullable.d.ts +36 -0
- package/plugins/microsandbox/dist/runner/nullable.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/nullable.js +82 -0
- package/plugins/microsandbox/dist/runner/nullable.js.map +1 -0
- package/plugins/microsandbox/dist/runner/pool.d.ts +97 -0
- package/plugins/microsandbox/dist/runner/pool.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/pool.js +494 -0
- package/plugins/microsandbox/dist/runner/pool.js.map +1 -0
- package/plugins/microsandbox/dist/runner/types.d.ts +33 -0
- package/plugins/microsandbox/dist/runner/types.d.ts.map +1 -0
- package/plugins/microsandbox/dist/runner/types.js +79 -0
- package/plugins/microsandbox/dist/runner/types.js.map +1 -0
- package/plugins/microsandbox/dist/server.d.ts +7 -0
- package/plugins/microsandbox/dist/server.d.ts.map +1 -0
- package/plugins/microsandbox/dist/server.js +276 -0
- package/plugins/microsandbox/dist/server.js.map +1 -0
- package/plugins/microsandbox/dist/tools/browser.d.ts +25 -0
- package/plugins/microsandbox/dist/tools/browser.d.ts.map +1 -0
- package/plugins/microsandbox/dist/tools/browser.js +78 -0
- package/plugins/microsandbox/dist/tools/browser.js.map +1 -0
- package/plugins/microsandbox/dist/tools/build.d.ts +5 -0
- package/plugins/microsandbox/dist/tools/build.d.ts.map +1 -0
- package/plugins/microsandbox/dist/tools/build.js +243 -0
- package/plugins/microsandbox/dist/tools/build.js.map +1 -0
- package/plugins/microsandbox/dist/tools/index.d.ts +9 -0
- package/plugins/microsandbox/dist/tools/index.d.ts.map +1 -0
- package/plugins/microsandbox/dist/tools/index.js +430 -0
- package/plugins/microsandbox/dist/tools/index.js.map +1 -0
- package/plugins/microsandbox/dist/tools/mcp-client.d.ts +63 -0
- package/plugins/microsandbox/dist/tools/mcp-client.d.ts.map +1 -0
- package/plugins/microsandbox/dist/tools/mcp-client.js +226 -0
- package/plugins/microsandbox/dist/tools/mcp-client.js.map +1 -0
- package/plugins/microsandbox/manifest.json +177 -0
- package/plugins/microsandbox/package.json +38 -0
- package/plugins/microsandbox/skills/microsandbox-browser-howto.md +155 -0
- package/plugins/microsandbox/skills/microsandbox-build-use.md +201 -0
- package/plugins/microsandbox/skills/microsandbox-config.md +38 -0
- package/plugins/microsandbox/skills/microsandbox-exec-howto.md +144 -0
- package/plugins/microsandbox/skills/microsandbox-libreoffice.md +159 -0
- package/plugins/microsandbox/templates/README.md +26 -0
- package/plugins/web-search/dist/server.d.ts +4 -0
- package/plugins/web-search/dist/server.d.ts.map +1 -0
- package/plugins/web-search/dist/server.js +73 -0
- package/plugins/web-search/dist/server.js.map +1 -0
- package/plugins/web-search/dist/tools/health.d.ts +31 -0
- package/plugins/web-search/dist/tools/health.d.ts.map +1 -0
- package/plugins/web-search/dist/tools/health.js +59 -0
- package/plugins/web-search/dist/tools/health.js.map +1 -0
- package/plugins/web-search/dist/tools/index.d.ts +3 -0
- package/plugins/web-search/dist/tools/index.d.ts.map +1 -0
- package/plugins/web-search/dist/tools/index.js +2 -0
- package/plugins/web-search/dist/tools/index.js.map +1 -0
- package/plugins/web-search/dist/tools/providers.d.ts +43 -0
- package/plugins/web-search/dist/tools/providers.d.ts.map +1 -0
- package/plugins/web-search/dist/tools/providers.js +140 -0
- package/plugins/web-search/dist/tools/providers.js.map +1 -0
- package/plugins/web-search/dist/tools/web-search.d.ts +15 -0
- package/plugins/web-search/dist/tools/web-search.d.ts.map +1 -0
- package/plugins/web-search/dist/tools/web-search.js +244 -0
- package/plugins/web-search/dist/tools/web-search.js.map +1 -0
- package/plugins/web-search/manifest.json +65 -0
- package/plugins/web-search/node_modules/@esbuild/darwin-arm64/README.md +3 -0
- package/plugins/web-search/node_modules/@esbuild/darwin-arm64/package.json +20 -0
- package/plugins/web-search/node_modules/@vitest/expect/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/expect/README.md +21 -0
- package/plugins/web-search/node_modules/@vitest/expect/dist/index.d.ts +808 -0
- package/plugins/web-search/node_modules/@vitest/expect/dist/index.js +1799 -0
- package/plugins/web-search/node_modules/@vitest/expect/package.json +46 -0
- package/plugins/web-search/node_modules/@vitest/mocker/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/mocker/README.md +5 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/auto-register.d.ts +2 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/auto-register.js +9 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/browser.d.ts +53 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/browser.js +91 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/chunk-interceptor-native.js +15 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/chunk-mocker.js +1602 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/chunk-pathe.M-eThtNZ.js +174 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/chunk-registry.js +182 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/chunk-utils.js +16 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/index.d.ts +21 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/index.js +174 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/mocker.d-Ce9_ySj5.d.ts +83 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/node.d.ts +821 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/node.js +1306 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/redirect.d.ts +3 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/redirect.js +75 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/register.d.ts +9 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/register.js +41 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/registry.d-D765pazg.d.ts +87 -0
- package/plugins/web-search/node_modules/@vitest/mocker/dist/types.d-D_aRZRdy.d.ts +8 -0
- package/plugins/web-search/node_modules/@vitest/mocker/package.json +82 -0
- package/plugins/web-search/node_modules/@vitest/pretty-format/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/pretty-format/dist/index.d.ts +119 -0
- package/plugins/web-search/node_modules/@vitest/pretty-format/dist/index.js +1387 -0
- package/plugins/web-search/node_modules/@vitest/pretty-format/package.json +44 -0
- package/plugins/web-search/node_modules/@vitest/runner/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/runner/README.md +5 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/chunk-hooks.js +2254 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/index.d.ts +261 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/index.js +6 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/tasks.d-CkscK4of.d.ts +558 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/types.d.ts +163 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/types.js +1 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/utils.d.ts +47 -0
- package/plugins/web-search/node_modules/@vitest/runner/dist/utils.js +6 -0
- package/plugins/web-search/node_modules/@vitest/runner/package.json +49 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/README.md +84 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/environment.d-DHdQ1Csl.d.ts +22 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/environment.d.ts +16 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/environment.js +40 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/index.d.ts +137 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/index.js +2305 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/manager.d.ts +18 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/manager.js +73 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/dist/rawSnapshot.d-lFsMJFUd.d.ts +61 -0
- package/plugins/web-search/node_modules/@vitest/snapshot/package.json +54 -0
- package/plugins/web-search/node_modules/@vitest/spy/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/spy/README.md +3 -0
- package/plugins/web-search/node_modules/@vitest/spy/dist/index.d.ts +356 -0
- package/plugins/web-search/node_modules/@vitest/spy/dist/index.js +191 -0
- package/plugins/web-search/node_modules/@vitest/spy/package.json +38 -0
- package/plugins/web-search/node_modules/@vitest/utils/LICENSE +21 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.js +158 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/diff.d.ts +104 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/diff.js +2185 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/error.d.ts +9 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/error.js +162 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/helpers.d.ts +56 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/helpers.js +251 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/index.d.ts +57 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/index.js +633 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/source-map.d.ts +139 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/source-map.js +996 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/types.d-BCElaP-c.d.ts +53 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/types.d.ts +53 -0
- package/plugins/web-search/node_modules/@vitest/utils/dist/types.js +1 -0
- package/plugins/web-search/node_modules/@vitest/utils/package.json +77 -0
- package/plugins/web-search/node_modules/chai/LICENSE +21 -0
- package/plugins/web-search/node_modules/chai/README.md +162 -0
- package/plugins/web-search/node_modules/chai/package.json +74 -0
- package/plugins/web-search/node_modules/esbuild/README.md +3 -0
- package/plugins/web-search/node_modules/esbuild/package.json +49 -0
- package/plugins/web-search/node_modules/std-env/README.md +118 -0
- package/plugins/web-search/node_modules/std-env/dist/index.cjs +1 -0
- package/plugins/web-search/node_modules/std-env/dist/index.d.cts +92 -0
- package/plugins/web-search/node_modules/std-env/dist/index.d.mts +92 -0
- package/plugins/web-search/node_modules/std-env/dist/index.d.ts +92 -0
- package/plugins/web-search/node_modules/std-env/dist/index.mjs +1 -0
- package/plugins/web-search/node_modules/std-env/package.json +46 -0
- package/plugins/web-search/node_modules/tinyexec/LICENSE +21 -0
- package/plugins/web-search/node_modules/tinyexec/README.md +256 -0
- package/plugins/web-search/node_modules/tinyexec/dist/main.cjs +575 -0
- package/plugins/web-search/node_modules/tinyexec/dist/main.d.cts +70 -0
- package/plugins/web-search/node_modules/tinyexec/dist/main.d.ts +70 -0
- package/plugins/web-search/node_modules/tinyexec/dist/main.js +578 -0
- package/plugins/web-search/node_modules/tinyexec/package.json +66 -0
- package/plugins/web-search/node_modules/tinyrainbow/README.md +28 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/browser.d.ts +8 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/browser.js +20 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.js +90 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/index-8b61d5bc.d.ts +59 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/node.d.ts +8 -0
- package/plugins/web-search/node_modules/tinyrainbow/dist/node.js +22 -0
- package/plugins/web-search/node_modules/tinyrainbow/package.json +37 -0
- package/plugins/web-search/node_modules/typescript/README.md +50 -0
- package/plugins/web-search/node_modules/typescript/package.json +120 -0
- package/plugins/web-search/node_modules/vite/README.md +20 -0
- package/plugins/web-search/node_modules/vite/dist/client/client.mjs +1106 -0
- package/plugins/web-search/node_modules/vite/dist/client/env.mjs +19 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/build.js +4 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/build2.js +5538 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/chunk.js +48 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/config.js +36065 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/config2.js +4 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/dist.js +6758 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/lib.js +377 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/logger.js +329 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/moduleRunnerTransport.d.ts +96 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/optimizer.js +4 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/postcss-import.js +479 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/preview.js +4 -0
- package/plugins/web-search/node_modules/vite/dist/node/chunks/server.js +4 -0
- package/plugins/web-search/node_modules/vite/dist/node/cli.js +698 -0
- package/plugins/web-search/node_modules/vite/dist/node/index.d.ts +3717 -0
- package/plugins/web-search/node_modules/vite/dist/node/index.js +30 -0
- package/plugins/web-search/node_modules/vite/dist/node/module-runner.d.ts +311 -0
- package/plugins/web-search/node_modules/vite/dist/node/module-runner.js +1160 -0
- package/plugins/web-search/node_modules/vite/package.json +199 -0
- package/plugins/web-search/node_modules/vite/types/package.json +4 -0
- package/plugins/web-search/node_modules/vitest/README.md +7 -0
- package/plugins/web-search/node_modules/vitest/dist/browser.d.ts +34 -0
- package/plugins/web-search/node_modules/vitest/dist/browser.js +8 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/_commonjsHelpers.BFTU3MAI.js +7 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/base.DfmxU-tU.js +38 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/benchmark.CYdenmiT.js +37 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/benchmark.d.BwvBVTda.d.ts +24 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/cac.0BJqEUeA.js +1469 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/cli-api.DWGBtMmz.js +10660 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/config.d.BKdhh7Zx.d.ts +224 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/console.CtFJOzRO.js +153 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/constants.DnKduX2e.js +44 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/coverage.DVF1vEu8.js +25 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/coverage.DfSpMS-b.js +4350 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/coverage.d.S9RMNXIe.d.ts +35 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/creator.GK6I-cL4.js +640 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/date.Bq6ZW5rf.js +73 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/defaults.B7q_naMc.js +115 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/env.D4Lgay0q.js +8 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/environment.d.cL3nLXbE.d.ts +119 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js +708 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/git.BVQ8w_Sw.js +72 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/global.d.MAmajcmJ.d.ts +136 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/globals.DEHgCU4V.js +26 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.B521nVV-.js +157 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.BCWujgDG.js +231 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.CdQS2e2Q.js +37 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.CmSc2RE5.js +587 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.CwejwG0H.js +105 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.D3XRDfWc.js +213 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.VByaPkjc.js +2183 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/index.X0nbfr6-.js +6584 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/inspector.C914Efll.js +57 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/mocker.d.BE_2ls6u.d.ts +17 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/node.fjCdwEIl.js +15 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/reporters.d.BuRON0I0.d.ts +3168 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/rpc.-pEldfrD.js +83 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/runBaseTests.9Ij9_de-.js +129 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/setup-common.Dd054P77.js +60 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/suite.d.FvehnV49.d.ts +10 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/typechecker.DRKU1-1g.js +874 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/utils.CAioKnHs.js +61 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/utils.XdZDrNZV.js +65 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/vi.bdSIJ99Y.js +4015 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/vite.d.BnOPPc46.d.ts +25 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/vm.BThCzidc.js +756 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/worker.d.CUgIPz9V.d.ts +176 -0
- package/plugins/web-search/node_modules/vitest/dist/chunks/worker.d.uzWsCv9X.d.ts +8 -0
- package/plugins/web-search/node_modules/vitest/dist/cli.js +27 -0
- package/plugins/web-search/node_modules/vitest/dist/config.cjs +148 -0
- package/plugins/web-search/node_modules/vitest/dist/config.d.ts +100 -0
- package/plugins/web-search/node_modules/vitest/dist/config.js +21 -0
- package/plugins/web-search/node_modules/vitest/dist/coverage.d.ts +108 -0
- package/plugins/web-search/node_modules/vitest/dist/coverage.js +34 -0
- package/plugins/web-search/node_modules/vitest/dist/environments.d.ts +26 -0
- package/plugins/web-search/node_modules/vitest/dist/environments.js +2 -0
- package/plugins/web-search/node_modules/vitest/dist/execute.d.ts +150 -0
- package/plugins/web-search/node_modules/vitest/dist/execute.js +13 -0
- package/plugins/web-search/node_modules/vitest/dist/index.d.ts +651 -0
- package/plugins/web-search/node_modules/vitest/dist/index.js +18 -0
- package/plugins/web-search/node_modules/vitest/dist/mocker.d.ts +1 -0
- package/plugins/web-search/node_modules/vitest/dist/mocker.js +1 -0
- package/plugins/web-search/node_modules/vitest/dist/node.d.ts +158 -0
- package/plugins/web-search/node_modules/vitest/dist/node.js +105 -0
- package/plugins/web-search/node_modules/vitest/dist/path.js +7 -0
- package/plugins/web-search/node_modules/vitest/dist/reporters.d.ts +25 -0
- package/plugins/web-search/node_modules/vitest/dist/reporters.js +23 -0
- package/plugins/web-search/node_modules/vitest/dist/runners.d.ts +46 -0
- package/plugins/web-search/node_modules/vitest/dist/runners.js +235 -0
- package/plugins/web-search/node_modules/vitest/dist/snapshot.d.ts +9 -0
- package/plugins/web-search/node_modules/vitest/dist/snapshot.js +4 -0
- package/plugins/web-search/node_modules/vitest/dist/spy.js +1 -0
- package/plugins/web-search/node_modules/vitest/dist/suite.d.ts +5 -0
- package/plugins/web-search/node_modules/vitest/dist/suite.js +5 -0
- package/plugins/web-search/node_modules/vitest/dist/worker.js +124 -0
- package/plugins/web-search/node_modules/vitest/dist/workers/forks.js +43 -0
- package/plugins/web-search/node_modules/vitest/dist/workers/runVmTests.js +90 -0
- package/plugins/web-search/node_modules/vitest/dist/workers/threads.js +31 -0
- package/plugins/web-search/node_modules/vitest/dist/workers/vmForks.js +47 -0
- package/plugins/web-search/node_modules/vitest/dist/workers/vmThreads.js +37 -0
- package/plugins/web-search/node_modules/vitest/dist/workers.d.ts +40 -0
- package/plugins/web-search/node_modules/vitest/dist/workers.js +30 -0
- package/plugins/web-search/node_modules/vitest/package.json +207 -0
- package/plugins/web-search/package.json +30 -0
- package/plugins/web-search/skills/web-search-howto.md +69 -0
- package/plugins/workboard/agent-seeds/echo-demo/agent.json +7 -0
- package/plugins/workboard/agent-seeds/llm-default/SOUL.md +53 -0
- package/plugins/workboard/agent-seeds/llm-default/agent.json +7 -0
- package/plugins/workboard/dist/client.d.ts +5 -0
- package/plugins/workboard/dist/client.d.ts.map +1 -0
- package/plugins/workboard/dist/client.js +895 -0
- package/plugins/workboard/dist/client.js.map +1 -0
- package/plugins/workboard/dist/db/agents.d.ts +100 -0
- package/plugins/workboard/dist/db/agents.d.ts.map +1 -0
- package/plugins/workboard/dist/db/agents.js +280 -0
- package/plugins/workboard/dist/db/agents.js.map +1 -0
- package/plugins/workboard/dist/db/schema.d.ts +3 -0
- package/plugins/workboard/dist/db/schema.d.ts.map +1 -0
- package/plugins/workboard/dist/db/schema.js +31 -0
- package/plugins/workboard/dist/db/schema.js.map +1 -0
- package/plugins/workboard/dist/db/session-history.d.ts +28 -0
- package/plugins/workboard/dist/db/session-history.d.ts.map +1 -0
- package/plugins/workboard/dist/db/session-history.js +224 -0
- package/plugins/workboard/dist/db/session-history.js.map +1 -0
- package/plugins/workboard/dist/db/tasks.d.ts +260 -0
- package/plugins/workboard/dist/db/tasks.d.ts.map +1 -0
- package/plugins/workboard/dist/db/tasks.js +451 -0
- package/plugins/workboard/dist/db/tasks.js.map +1 -0
- package/plugins/workboard/dist/db/worker-agents.d.ts +16 -0
- package/plugins/workboard/dist/db/worker-agents.d.ts.map +1 -0
- package/plugins/workboard/dist/db/worker-agents.js +62 -0
- package/plugins/workboard/dist/db/worker-agents.js.map +1 -0
- package/plugins/workboard/dist/effective-skills.d.ts +13 -0
- package/plugins/workboard/dist/effective-skills.d.ts.map +1 -0
- package/plugins/workboard/dist/effective-skills.js +126 -0
- package/plugins/workboard/dist/effective-skills.js.map +1 -0
- package/plugins/workboard/dist/fs-worker-agents.d.ts +35 -0
- package/plugins/workboard/dist/fs-worker-agents.d.ts.map +1 -0
- package/plugins/workboard/dist/fs-worker-agents.js +199 -0
- package/plugins/workboard/dist/fs-worker-agents.js.map +1 -0
- package/plugins/workboard/dist/migrate-worker-agents.d.ts +11 -0
- package/plugins/workboard/dist/migrate-worker-agents.d.ts.map +1 -0
- package/plugins/workboard/dist/migrate-worker-agents.js +89 -0
- package/plugins/workboard/dist/migrate-worker-agents.js.map +1 -0
- package/plugins/workboard/dist/routes/handlers.d.ts +106 -0
- package/plugins/workboard/dist/routes/handlers.d.ts.map +1 -0
- package/plugins/workboard/dist/routes/handlers.js +668 -0
- package/plugins/workboard/dist/routes/handlers.js.map +1 -0
- package/plugins/workboard/dist/server.d.ts +6 -0
- package/plugins/workboard/dist/server.d.ts.map +1 -0
- package/plugins/workboard/dist/server.js +368 -0
- package/plugins/workboard/dist/server.js.map +1 -0
- package/plugins/workboard/dist/tools/index.d.ts +70 -0
- package/plugins/workboard/dist/tools/index.d.ts.map +1 -0
- package/plugins/workboard/dist/tools/index.js +963 -0
- package/plugins/workboard/dist/tools/index.js.map +1 -0
- package/plugins/workboard/dist/types.d.ts +27 -0
- package/plugins/workboard/dist/types.d.ts.map +1 -0
- package/plugins/workboard/dist/types.js +16 -0
- package/plugins/workboard/dist/types.js.map +1 -0
- package/plugins/workboard/dist/worker/pool.d.ts +220 -0
- package/plugins/workboard/dist/worker/pool.d.ts.map +1 -0
- package/plugins/workboard/dist/worker/pool.js +866 -0
- package/plugins/workboard/dist/worker/pool.js.map +1 -0
- package/plugins/workboard/dist/worker/tool-policy.d.ts +27 -0
- package/plugins/workboard/dist/worker/tool-policy.d.ts.map +1 -0
- package/plugins/workboard/dist/worker/tool-policy.js +76 -0
- package/plugins/workboard/dist/worker/tool-policy.js.map +1 -0
- package/plugins/workboard/dist/worker-agents-page.d.ts +4 -0
- package/plugins/workboard/dist/worker-agents-page.d.ts.map +1 -0
- package/plugins/workboard/dist/worker-agents-page.js +193 -0
- package/plugins/workboard/dist/worker-agents-page.js.map +1 -0
- package/plugins/workboard/manifest.json +180 -0
- package/plugins/workboard/package.json +37 -0
- package/plugins/workboard/skills/large-input-large-output.md +185 -0
- package/plugins/workboard/skills/workboard-howto.md +166 -0
- package/plugins/workboard/skills/worker-creator.md +267 -0
- package/plugins/workboard/skills/worker-fleet.md +431 -0
|
@@ -0,0 +1,2183 @@
|
|
|
1
|
+
import { performance as performance$1 } from 'node:perf_hooks';
|
|
2
|
+
import { getTestName, getFullName, hasFailed, getTests, getSuites, getTasks } from '@vitest/runner/utils';
|
|
3
|
+
import { slash, toArray, isPrimitive, inspect, positionToOffset, lineSplitRE } from '@vitest/utils';
|
|
4
|
+
import { parseStacktrace, parseErrorStacktrace } from '@vitest/utils/source-map';
|
|
5
|
+
import { isAbsolute, relative, dirname, basename, resolve, normalize } from 'pathe';
|
|
6
|
+
import c from 'tinyrainbow';
|
|
7
|
+
import { i as isTTY } from './env.D4Lgay0q.js';
|
|
8
|
+
import { h as hasFailedSnapshot, g as getOutputFile, T as TypeCheckError } from './typechecker.DRKU1-1g.js';
|
|
9
|
+
import { stripVTControlCharacters } from 'node:util';
|
|
10
|
+
import { existsSync, readFileSync, promises } from 'node:fs';
|
|
11
|
+
import { mkdir, writeFile, readdir, stat, readFile } from 'node:fs/promises';
|
|
12
|
+
import { Console } from 'node:console';
|
|
13
|
+
import { Writable } from 'node:stream';
|
|
14
|
+
import { createRequire } from 'node:module';
|
|
15
|
+
import { hostname } from 'node:os';
|
|
16
|
+
|
|
17
|
+
const F_RIGHT = "→";
|
|
18
|
+
const F_DOWN = "↓";
|
|
19
|
+
const F_DOWN_RIGHT = "↳";
|
|
20
|
+
const F_POINTER = "❯";
|
|
21
|
+
const F_DOT = "·";
|
|
22
|
+
const F_CHECK = "✓";
|
|
23
|
+
const F_CROSS = "×";
|
|
24
|
+
const F_LONG_DASH = "⎯";
|
|
25
|
+
const F_TREE_NODE_MIDDLE = "├──";
|
|
26
|
+
const F_TREE_NODE_END = "└──";
|
|
27
|
+
|
|
28
|
+
const pointer = c.yellow(F_POINTER);
|
|
29
|
+
const skipped = c.dim(c.gray(F_DOWN));
|
|
30
|
+
const benchmarkPass = c.green(F_DOT);
|
|
31
|
+
const testPass = c.green(F_CHECK);
|
|
32
|
+
const taskFail = c.red(F_CROSS);
|
|
33
|
+
const suiteFail = c.red(F_POINTER);
|
|
34
|
+
const pending$1 = c.gray("·");
|
|
35
|
+
const labelDefaultColors = [
|
|
36
|
+
c.bgYellow,
|
|
37
|
+
c.bgCyan,
|
|
38
|
+
c.bgGreen,
|
|
39
|
+
c.bgMagenta
|
|
40
|
+
];
|
|
41
|
+
function getCols(delta = 0) {
|
|
42
|
+
let length = process.stdout?.columns;
|
|
43
|
+
if (!length || Number.isNaN(length)) length = 30;
|
|
44
|
+
return Math.max(length + delta, 0);
|
|
45
|
+
}
|
|
46
|
+
function errorBanner(message) {
|
|
47
|
+
return divider(c.bold(c.bgRed(` ${message} `)), null, null, c.red);
|
|
48
|
+
}
|
|
49
|
+
function divider(text, left, right, color) {
|
|
50
|
+
const cols = getCols();
|
|
51
|
+
const c = color || ((text) => text);
|
|
52
|
+
if (text) {
|
|
53
|
+
const textLength = stripVTControlCharacters(text).length;
|
|
54
|
+
if (left == null && right != null) left = cols - textLength - right;
|
|
55
|
+
else {
|
|
56
|
+
left = left ?? Math.floor((cols - textLength) / 2);
|
|
57
|
+
right = cols - textLength - left;
|
|
58
|
+
}
|
|
59
|
+
left = Math.max(0, left);
|
|
60
|
+
right = Math.max(0, right);
|
|
61
|
+
return `${c(F_LONG_DASH.repeat(left))}${text}${c(F_LONG_DASH.repeat(right))}`;
|
|
62
|
+
}
|
|
63
|
+
return F_LONG_DASH.repeat(cols);
|
|
64
|
+
}
|
|
65
|
+
function formatTestPath(root, path) {
|
|
66
|
+
if (isAbsolute(path)) path = relative(root, path);
|
|
67
|
+
const dir = dirname(path);
|
|
68
|
+
const ext = path.match(/(\.(spec|test)\.[cm]?[tj]sx?)$/)?.[0] || "";
|
|
69
|
+
const base = basename(path, ext);
|
|
70
|
+
return slash(c.dim(`${dir}/`) + c.bold(base)) + c.dim(ext);
|
|
71
|
+
}
|
|
72
|
+
function renderSnapshotSummary(rootDir, snapshots) {
|
|
73
|
+
const summary = [];
|
|
74
|
+
if (snapshots.added) summary.push(c.bold(c.green(`${snapshots.added} written`)));
|
|
75
|
+
if (snapshots.unmatched) summary.push(c.bold(c.red(`${snapshots.unmatched} failed`)));
|
|
76
|
+
if (snapshots.updated) summary.push(c.bold(c.green(`${snapshots.updated} updated `)));
|
|
77
|
+
if (snapshots.filesRemoved) if (snapshots.didUpdate) summary.push(c.bold(c.green(`${snapshots.filesRemoved} files removed `)));
|
|
78
|
+
else summary.push(c.bold(c.yellow(`${snapshots.filesRemoved} files obsolete `)));
|
|
79
|
+
if (snapshots.filesRemovedList && snapshots.filesRemovedList.length) {
|
|
80
|
+
const [head, ...tail] = snapshots.filesRemovedList;
|
|
81
|
+
summary.push(`${c.gray(F_DOWN_RIGHT)} ${formatTestPath(rootDir, head)}`);
|
|
82
|
+
tail.forEach((key) => {
|
|
83
|
+
summary.push(` ${c.gray(F_DOT)} ${formatTestPath(rootDir, key)}`);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (snapshots.unchecked) {
|
|
87
|
+
if (snapshots.didUpdate) summary.push(c.bold(c.green(`${snapshots.unchecked} removed`)));
|
|
88
|
+
else summary.push(c.bold(c.yellow(`${snapshots.unchecked} obsolete`)));
|
|
89
|
+
snapshots.uncheckedKeysByFile.forEach((uncheckedFile) => {
|
|
90
|
+
summary.push(`${c.gray(F_DOWN_RIGHT)} ${formatTestPath(rootDir, uncheckedFile.filePath)}`);
|
|
91
|
+
uncheckedFile.keys.forEach((key) => summary.push(` ${c.gray(F_DOT)} ${key}`));
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return summary;
|
|
95
|
+
}
|
|
96
|
+
function countTestErrors(tasks) {
|
|
97
|
+
return tasks.reduce((c, i) => c + (i.result?.errors?.length || 0), 0);
|
|
98
|
+
}
|
|
99
|
+
function getStateString$1(tasks, name = "tests", showTotal = true) {
|
|
100
|
+
if (tasks.length === 0) return c.dim(`no ${name}`);
|
|
101
|
+
const passed = tasks.filter((i) => i.result?.state === "pass");
|
|
102
|
+
const failed = tasks.filter((i) => i.result?.state === "fail");
|
|
103
|
+
const skipped = tasks.filter((i) => i.mode === "skip");
|
|
104
|
+
const todo = tasks.filter((i) => i.mode === "todo");
|
|
105
|
+
return [
|
|
106
|
+
failed.length ? c.bold(c.red(`${failed.length} failed`)) : null,
|
|
107
|
+
passed.length ? c.bold(c.green(`${passed.length} passed`)) : null,
|
|
108
|
+
skipped.length ? c.yellow(`${skipped.length} skipped`) : null,
|
|
109
|
+
todo.length ? c.gray(`${todo.length} todo`) : null
|
|
110
|
+
].filter(Boolean).join(c.dim(" | ")) + (showTotal ? c.gray(` (${tasks.length})`) : "");
|
|
111
|
+
}
|
|
112
|
+
function getStateSymbol(task) {
|
|
113
|
+
if (task.mode === "skip" || task.mode === "todo") return skipped;
|
|
114
|
+
if (!task.result) return pending$1;
|
|
115
|
+
if (task.result.state === "run" || task.result.state === "queued") {
|
|
116
|
+
if (task.type === "suite") return pointer;
|
|
117
|
+
}
|
|
118
|
+
if (task.result.state === "pass") return task.meta?.benchmark ? benchmarkPass : testPass;
|
|
119
|
+
if (task.result.state === "fail") return task.type === "suite" ? suiteFail : taskFail;
|
|
120
|
+
return " ";
|
|
121
|
+
}
|
|
122
|
+
function formatTimeString(date) {
|
|
123
|
+
return date.toTimeString().split(" ")[0];
|
|
124
|
+
}
|
|
125
|
+
function formatTime(time) {
|
|
126
|
+
if (time > 1e3) return `${(time / 1e3).toFixed(2)}s`;
|
|
127
|
+
return `${Math.round(time)}ms`;
|
|
128
|
+
}
|
|
129
|
+
function formatProjectName(project, suffix = " ") {
|
|
130
|
+
if (!project?.name) return "";
|
|
131
|
+
if (!c.isColorSupported) return `|${project.name}|${suffix}`;
|
|
132
|
+
let background = project.color && c[`bg${capitalize(project.color)}`];
|
|
133
|
+
if (!background) {
|
|
134
|
+
const index = project.name.split("").reduce((acc, v, idx) => acc + v.charCodeAt(0) + idx, 0);
|
|
135
|
+
background = labelDefaultColors[index % labelDefaultColors.length];
|
|
136
|
+
}
|
|
137
|
+
return c.black(background(` ${project.name} `)) + suffix;
|
|
138
|
+
}
|
|
139
|
+
function withLabel(color, label, message) {
|
|
140
|
+
const bgColor = `bg${color.charAt(0).toUpperCase()}${color.slice(1)}`;
|
|
141
|
+
return `${c.bold(c[bgColor](` ${label} `))} ${message ? c[color](message) : ""}`;
|
|
142
|
+
}
|
|
143
|
+
function padSummaryTitle(str) {
|
|
144
|
+
return c.dim(`${str.padStart(11)} `);
|
|
145
|
+
}
|
|
146
|
+
function truncateString(text, maxLength) {
|
|
147
|
+
const plainText = stripVTControlCharacters(text);
|
|
148
|
+
if (plainText.length <= maxLength) return text;
|
|
149
|
+
return `${plainText.slice(0, maxLength - 1)}…`;
|
|
150
|
+
}
|
|
151
|
+
function capitalize(text) {
|
|
152
|
+
return `${text[0].toUpperCase()}${text.slice(1)}`;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
var utils = /*#__PURE__*/Object.freeze({
|
|
156
|
+
__proto__: null,
|
|
157
|
+
benchmarkPass: benchmarkPass,
|
|
158
|
+
countTestErrors: countTestErrors,
|
|
159
|
+
divider: divider,
|
|
160
|
+
errorBanner: errorBanner,
|
|
161
|
+
formatProjectName: formatProjectName,
|
|
162
|
+
formatTestPath: formatTestPath,
|
|
163
|
+
formatTime: formatTime,
|
|
164
|
+
formatTimeString: formatTimeString,
|
|
165
|
+
getStateString: getStateString$1,
|
|
166
|
+
getStateSymbol: getStateSymbol,
|
|
167
|
+
padSummaryTitle: padSummaryTitle,
|
|
168
|
+
pending: pending$1,
|
|
169
|
+
pointer: pointer,
|
|
170
|
+
renderSnapshotSummary: renderSnapshotSummary,
|
|
171
|
+
skipped: skipped,
|
|
172
|
+
suiteFail: suiteFail,
|
|
173
|
+
taskFail: taskFail,
|
|
174
|
+
testPass: testPass,
|
|
175
|
+
truncateString: truncateString,
|
|
176
|
+
withLabel: withLabel
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
const BADGE_PADDING = " ";
|
|
180
|
+
class BaseReporter {
|
|
181
|
+
start = 0;
|
|
182
|
+
end = 0;
|
|
183
|
+
watchFilters;
|
|
184
|
+
failedUnwatchedFiles = [];
|
|
185
|
+
isTTY;
|
|
186
|
+
ctx = void 0;
|
|
187
|
+
renderSucceed = false;
|
|
188
|
+
verbose = false;
|
|
189
|
+
_filesInWatchMode = /* @__PURE__ */ new Map();
|
|
190
|
+
_timeStart = formatTimeString(/* @__PURE__ */ new Date());
|
|
191
|
+
constructor(options = {}) {
|
|
192
|
+
this.isTTY = options.isTTY ?? isTTY;
|
|
193
|
+
}
|
|
194
|
+
onInit(ctx) {
|
|
195
|
+
this.ctx = ctx;
|
|
196
|
+
this.ctx.logger.printBanner();
|
|
197
|
+
this.start = performance$1.now();
|
|
198
|
+
}
|
|
199
|
+
log(...messages) {
|
|
200
|
+
this.ctx.logger.log(...messages);
|
|
201
|
+
}
|
|
202
|
+
error(...messages) {
|
|
203
|
+
this.ctx.logger.error(...messages);
|
|
204
|
+
}
|
|
205
|
+
relative(path) {
|
|
206
|
+
return relative(this.ctx.config.root, path);
|
|
207
|
+
}
|
|
208
|
+
onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
|
|
209
|
+
this.end = performance$1.now();
|
|
210
|
+
if (!files.length && !errors.length) this.ctx.logger.printNoTestFound(this.ctx.filenamePattern);
|
|
211
|
+
else this.reportSummary(files, errors);
|
|
212
|
+
}
|
|
213
|
+
onTestCaseResult(testCase) {
|
|
214
|
+
if (testCase.result().state === "failed") this.logFailedTask(testCase.task);
|
|
215
|
+
}
|
|
216
|
+
onTestSuiteResult(testSuite) {
|
|
217
|
+
if (testSuite.state() === "failed") this.logFailedTask(testSuite.task);
|
|
218
|
+
}
|
|
219
|
+
onTestModuleEnd(testModule) {
|
|
220
|
+
if (testModule.state() === "failed") this.logFailedTask(testModule.task);
|
|
221
|
+
this.printTestModule(testModule);
|
|
222
|
+
}
|
|
223
|
+
logFailedTask(task) {
|
|
224
|
+
if (this.ctx.config.silent === "passed-only") for (const log of task.logs || []) this.onUserConsoleLog(log, "failed");
|
|
225
|
+
}
|
|
226
|
+
printTestModule(testModule) {
|
|
227
|
+
const moduleState = testModule.state();
|
|
228
|
+
if (moduleState === "queued" || moduleState === "pending") return;
|
|
229
|
+
let testsCount = 0;
|
|
230
|
+
let failedCount = 0;
|
|
231
|
+
let skippedCount = 0;
|
|
232
|
+
// delaying logs to calculate the test stats first
|
|
233
|
+
// which minimizes the amount of for loops
|
|
234
|
+
const logs = [];
|
|
235
|
+
const originalLog = this.log.bind(this);
|
|
236
|
+
this.log = (msg) => logs.push(msg);
|
|
237
|
+
const visit = (suiteState, children) => {
|
|
238
|
+
for (const child of children) if (child.type === "suite") {
|
|
239
|
+
const suiteState = child.state();
|
|
240
|
+
// Skipped suites are hidden when --hideSkippedTests, print otherwise
|
|
241
|
+
if (!this.ctx.config.hideSkippedTests || suiteState !== "skipped") this.printTestSuite(child);
|
|
242
|
+
visit(suiteState, child.children);
|
|
243
|
+
} else {
|
|
244
|
+
const testResult = child.result();
|
|
245
|
+
testsCount++;
|
|
246
|
+
if (testResult.state === "failed") failedCount++;
|
|
247
|
+
else if (testResult.state === "skipped") skippedCount++;
|
|
248
|
+
if (this.ctx.config.hideSkippedTests && suiteState === "skipped")
|
|
249
|
+
// Skipped suites are hidden when --hideSkippedTests
|
|
250
|
+
continue;
|
|
251
|
+
this.printTestCase(moduleState, child);
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
try {
|
|
255
|
+
visit(moduleState, testModule.children);
|
|
256
|
+
} finally {
|
|
257
|
+
this.log = originalLog;
|
|
258
|
+
}
|
|
259
|
+
this.log(this.getModuleLog(testModule, {
|
|
260
|
+
tests: testsCount,
|
|
261
|
+
failed: failedCount,
|
|
262
|
+
skipped: skippedCount
|
|
263
|
+
}));
|
|
264
|
+
logs.forEach((log) => this.log(log));
|
|
265
|
+
}
|
|
266
|
+
printTestCase(moduleState, test) {
|
|
267
|
+
const testResult = test.result();
|
|
268
|
+
const { duration, retryCount, repeatCount } = test.diagnostic() || {};
|
|
269
|
+
const padding = this.getTestIndentation(test.task);
|
|
270
|
+
let suffix = this.getDurationPrefix(test.task);
|
|
271
|
+
if (retryCount != null && retryCount > 0) suffix += c.yellow(` (retry x${retryCount})`);
|
|
272
|
+
if (repeatCount != null && repeatCount > 0) suffix += c.yellow(` (repeat x${repeatCount})`);
|
|
273
|
+
if (testResult.state === "failed") {
|
|
274
|
+
this.log(c.red(` ${padding}${taskFail} ${this.getTestName(test.task, c.dim(" > "))}`) + suffix);
|
|
275
|
+
// print short errors, full errors will be at the end in summary
|
|
276
|
+
testResult.errors.forEach((error) => {
|
|
277
|
+
const message = this.formatShortError(error);
|
|
278
|
+
if (message) this.log(c.red(` ${padding}${message}`));
|
|
279
|
+
});
|
|
280
|
+
} else if (duration && duration > this.ctx.config.slowTestThreshold) this.log(` ${padding}${c.yellow(c.dim(F_CHECK))} ${this.getTestName(test.task, c.dim(" > "))} ${suffix}`);
|
|
281
|
+
else if (this.ctx.config.hideSkippedTests && testResult.state === "skipped") ; else if (testResult.state === "skipped" && testResult.note) this.log(` ${padding}${getStateSymbol(test.task)} ${this.getTestName(test.task, c.dim(" > "))}${c.dim(c.gray(` [${testResult.note}]`))}`);
|
|
282
|
+
else if (this.renderSucceed || moduleState === "failed") this.log(` ${padding}${getStateSymbol(test.task)} ${this.getTestName(test.task, c.dim(" > "))}${suffix}`);
|
|
283
|
+
}
|
|
284
|
+
getModuleLog(testModule, counts) {
|
|
285
|
+
let state = c.dim(`${counts.tests} test${counts.tests > 1 ? "s" : ""}`);
|
|
286
|
+
if (counts.failed) state += c.dim(" | ") + c.red(`${counts.failed} failed`);
|
|
287
|
+
if (counts.skipped) state += c.dim(" | ") + c.yellow(`${counts.skipped} skipped`);
|
|
288
|
+
let suffix = c.dim("(") + state + c.dim(")") + this.getDurationPrefix(testModule.task);
|
|
289
|
+
const diagnostic = testModule.diagnostic();
|
|
290
|
+
if (diagnostic.heap != null) suffix += c.magenta(` ${Math.floor(diagnostic.heap / 1024 / 1024)} MB heap used`);
|
|
291
|
+
let title = getStateSymbol(testModule.task);
|
|
292
|
+
if (testModule.meta().typecheck) title += ` ${c.bgBlue(c.bold(" TS "))}`;
|
|
293
|
+
if (testModule.project.name) title += ` ${formatProjectName(testModule.project, "")}`;
|
|
294
|
+
return ` ${title} ${testModule.task.name} ${suffix}`;
|
|
295
|
+
}
|
|
296
|
+
printTestSuite(_suite) {
|
|
297
|
+
// Suite name is included in getTestName by default
|
|
298
|
+
}
|
|
299
|
+
getTestName(test, separator) {
|
|
300
|
+
return getTestName(test, separator);
|
|
301
|
+
}
|
|
302
|
+
getFullName(test, separator) {
|
|
303
|
+
return getFullName(test, separator);
|
|
304
|
+
}
|
|
305
|
+
formatShortError(error) {
|
|
306
|
+
return `${F_RIGHT} ${error.message}`;
|
|
307
|
+
}
|
|
308
|
+
getTestIndentation(_test) {
|
|
309
|
+
return " ";
|
|
310
|
+
}
|
|
311
|
+
printAnnotations(test, console, padding = 0) {
|
|
312
|
+
const annotations = test.annotations();
|
|
313
|
+
if (!annotations.length) return;
|
|
314
|
+
const PADDING = " ".repeat(padding);
|
|
315
|
+
annotations.forEach(({ location, type, message }) => {
|
|
316
|
+
if (location) {
|
|
317
|
+
const file = relative(test.project.config.root, location.file);
|
|
318
|
+
this[console](`${PADDING}${c.blue(F_POINTER)} ${c.gray(`${file}:${location.line}:${location.column}`)} ${c.bold(type)}`);
|
|
319
|
+
} else this[console](`${PADDING}${c.blue(F_POINTER)} ${c.bold(type)}`);
|
|
320
|
+
this[console](`${PADDING} ${c.blue(F_DOWN_RIGHT)} ${message}`);
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
getDurationPrefix(task) {
|
|
324
|
+
if (!task.result?.duration) return "";
|
|
325
|
+
const color = task.result.duration > this.ctx.config.slowTestThreshold ? c.yellow : c.green;
|
|
326
|
+
return color(` ${Math.round(task.result.duration)}${c.dim("ms")}`);
|
|
327
|
+
}
|
|
328
|
+
onWatcherStart(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
|
|
329
|
+
const failed = errors.length > 0 || hasFailed(files);
|
|
330
|
+
if (failed) this.log(withLabel("red", "FAIL", "Tests failed. Watching for file changes..."));
|
|
331
|
+
else if (this.ctx.isCancelling) this.log(withLabel("red", "CANCELLED", "Test run cancelled. Watching for file changes..."));
|
|
332
|
+
else this.log(withLabel("green", "PASS", "Waiting for file changes..."));
|
|
333
|
+
const hints = [c.dim("press ") + c.bold("h") + c.dim(" to show help")];
|
|
334
|
+
if (hasFailedSnapshot(files)) hints.unshift(c.dim("press ") + c.bold(c.yellow("u")) + c.dim(" to update snapshot"));
|
|
335
|
+
else hints.push(c.dim("press ") + c.bold("q") + c.dim(" to quit"));
|
|
336
|
+
this.log(BADGE_PADDING + hints.join(c.dim(", ")));
|
|
337
|
+
}
|
|
338
|
+
onWatcherRerun(files, trigger) {
|
|
339
|
+
this.watchFilters = files;
|
|
340
|
+
this.failedUnwatchedFiles = this.ctx.state.getTestModules().filter((testModule) => !files.includes(testModule.task.filepath) && testModule.state() === "failed");
|
|
341
|
+
// Update re-run count for each file
|
|
342
|
+
files.forEach((filepath) => {
|
|
343
|
+
let reruns = this._filesInWatchMode.get(filepath) ?? 0;
|
|
344
|
+
this._filesInWatchMode.set(filepath, ++reruns);
|
|
345
|
+
});
|
|
346
|
+
let banner = trigger ? c.dim(`${this.relative(trigger)} `) : "";
|
|
347
|
+
if (files.length === 1) {
|
|
348
|
+
const rerun = this._filesInWatchMode.get(files[0]) ?? 1;
|
|
349
|
+
banner += c.blue(`x${rerun} `);
|
|
350
|
+
}
|
|
351
|
+
this.ctx.logger.clearFullScreen();
|
|
352
|
+
this.log(withLabel("blue", "RERUN", banner));
|
|
353
|
+
if (this.ctx.configOverride.project) this.log(BADGE_PADDING + c.dim(" Project name: ") + c.blue(toArray(this.ctx.configOverride.project).join(", ")));
|
|
354
|
+
if (this.ctx.filenamePattern) this.log(BADGE_PADDING + c.dim(" Filename pattern: ") + c.blue(this.ctx.filenamePattern.join(", ")));
|
|
355
|
+
if (this.ctx.configOverride.testNamePattern) this.log(BADGE_PADDING + c.dim(" Test name pattern: ") + c.blue(String(this.ctx.configOverride.testNamePattern)));
|
|
356
|
+
this.log("");
|
|
357
|
+
for (const testModule of this.failedUnwatchedFiles) this.printTestModule(testModule);
|
|
358
|
+
this._timeStart = formatTimeString(/* @__PURE__ */ new Date());
|
|
359
|
+
this.start = performance$1.now();
|
|
360
|
+
}
|
|
361
|
+
onUserConsoleLog(log, taskState) {
|
|
362
|
+
if (!this.shouldLog(log, taskState)) return;
|
|
363
|
+
const output = log.type === "stdout" ? this.ctx.logger.outputStream : this.ctx.logger.errorStream;
|
|
364
|
+
const write = (msg) => output.write(msg);
|
|
365
|
+
let headerText = "unknown test";
|
|
366
|
+
const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : void 0;
|
|
367
|
+
if (task) headerText = this.getFullName(task, c.dim(" > "));
|
|
368
|
+
else if (log.taskId && log.taskId !== "__vitest__unknown_test__") headerText = log.taskId;
|
|
369
|
+
write(c.gray(log.type + c.dim(` | ${headerText}\n`)) + log.content);
|
|
370
|
+
if (log.origin) {
|
|
371
|
+
// browser logs don't have an extra end of line at the end like Node.js does
|
|
372
|
+
if (log.browser) write("\n");
|
|
373
|
+
const project = task ? this.ctx.getProjectByName(task.file.projectName || "") : this.ctx.getRootProject();
|
|
374
|
+
const stack = log.browser ? project.browser?.parseStacktrace(log.origin) || [] : parseStacktrace(log.origin);
|
|
375
|
+
const highlight = task && stack.find((i) => i.file === task.file.filepath);
|
|
376
|
+
for (const frame of stack) {
|
|
377
|
+
const color = frame === highlight ? c.cyan : c.gray;
|
|
378
|
+
const path = relative(project.config.root, frame.file);
|
|
379
|
+
const positions = [frame.method, `${path}:${c.dim(`${frame.line}:${frame.column}`)}`].filter(Boolean).join(" ");
|
|
380
|
+
write(color(` ${c.dim(F_POINTER)} ${positions}\n`));
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
write("\n");
|
|
384
|
+
}
|
|
385
|
+
onTestRemoved(trigger) {
|
|
386
|
+
this.log(c.yellow("Test removed...") + (trigger ? c.dim(` [ ${this.relative(trigger)} ]\n`) : ""));
|
|
387
|
+
}
|
|
388
|
+
shouldLog(log, taskState) {
|
|
389
|
+
if (this.ctx.config.silent === true) return false;
|
|
390
|
+
if (this.ctx.config.silent === "passed-only" && taskState !== "failed") return false;
|
|
391
|
+
const shouldLog = this.ctx.config.onConsoleLog?.(log.content, log.type);
|
|
392
|
+
if (shouldLog === false) return shouldLog;
|
|
393
|
+
return true;
|
|
394
|
+
}
|
|
395
|
+
onServerRestart(reason) {
|
|
396
|
+
this.log(c.bold(c.magenta(reason === "config" ? "\nRestarting due to config changes..." : "\nRestarting Vitest...")));
|
|
397
|
+
}
|
|
398
|
+
reportSummary(files, errors) {
|
|
399
|
+
this.printErrorsSummary(files, errors);
|
|
400
|
+
if (this.ctx.config.mode === "benchmark") this.reportBenchmarkSummary(files);
|
|
401
|
+
else this.reportTestSummary(files, errors);
|
|
402
|
+
}
|
|
403
|
+
reportTestSummary(files, errors) {
|
|
404
|
+
this.log();
|
|
405
|
+
const affectedFiles = [...this.failedUnwatchedFiles.map((m) => m.task), ...files];
|
|
406
|
+
const tests = getTests(affectedFiles);
|
|
407
|
+
const snapshotOutput = renderSnapshotSummary(this.ctx.config.root, this.ctx.snapshot.summary);
|
|
408
|
+
for (const [index, snapshot] of snapshotOutput.entries()) {
|
|
409
|
+
const title = index === 0 ? "Snapshots" : "";
|
|
410
|
+
this.log(`${padSummaryTitle(title)} ${snapshot}`);
|
|
411
|
+
}
|
|
412
|
+
if (snapshotOutput.length > 1) this.log();
|
|
413
|
+
this.log(padSummaryTitle("Test Files"), getStateString$1(affectedFiles));
|
|
414
|
+
this.log(padSummaryTitle("Tests"), getStateString$1(tests));
|
|
415
|
+
if (this.ctx.projects.some((c) => c.config.typecheck.enabled)) {
|
|
416
|
+
const failed = tests.filter((t) => t.meta?.typecheck && t.result?.errors?.length);
|
|
417
|
+
this.log(padSummaryTitle("Type Errors"), failed.length ? c.bold(c.red(`${failed.length} failed`)) : c.dim("no errors"));
|
|
418
|
+
}
|
|
419
|
+
if (errors.length) this.log(padSummaryTitle("Errors"), c.bold(c.red(`${errors.length} error${errors.length > 1 ? "s" : ""}`)));
|
|
420
|
+
this.log(padSummaryTitle("Start at"), this._timeStart);
|
|
421
|
+
const collectTime = sum(files, (file) => file.collectDuration);
|
|
422
|
+
const testsTime = sum(files, (file) => file.result?.duration);
|
|
423
|
+
const setupTime = sum(files, (file) => file.setupDuration);
|
|
424
|
+
if (this.watchFilters) this.log(padSummaryTitle("Duration"), formatTime(collectTime + testsTime + setupTime));
|
|
425
|
+
else {
|
|
426
|
+
const blobs = this.ctx.state.blobs;
|
|
427
|
+
// Execution time is either sum of all runs of `--merge-reports` or the current run's time
|
|
428
|
+
const executionTime = blobs?.executionTimes ? sum(blobs.executionTimes, (time) => time) : this.end - this.start;
|
|
429
|
+
const environmentTime = sum(files, (file) => file.environmentLoad);
|
|
430
|
+
const prepareTime = sum(files, (file) => file.prepareDuration);
|
|
431
|
+
const transformTime = sum(this.ctx.projects, (project) => project.vitenode.getTotalDuration());
|
|
432
|
+
const typecheck = sum(this.ctx.projects, (project) => project.typechecker?.getResult().time);
|
|
433
|
+
const timers = [
|
|
434
|
+
`transform ${formatTime(transformTime)}`,
|
|
435
|
+
`setup ${formatTime(setupTime)}`,
|
|
436
|
+
`collect ${formatTime(collectTime)}`,
|
|
437
|
+
`tests ${formatTime(testsTime)}`,
|
|
438
|
+
`environment ${formatTime(environmentTime)}`,
|
|
439
|
+
`prepare ${formatTime(prepareTime)}`,
|
|
440
|
+
typecheck && `typecheck ${formatTime(typecheck)}`
|
|
441
|
+
].filter(Boolean).join(", ");
|
|
442
|
+
this.log(padSummaryTitle("Duration"), formatTime(executionTime) + c.dim(` (${timers})`));
|
|
443
|
+
if (blobs?.executionTimes) this.log(padSummaryTitle("Per blob") + blobs.executionTimes.map((time) => ` ${formatTime(time)}`).join(""));
|
|
444
|
+
}
|
|
445
|
+
this.log();
|
|
446
|
+
}
|
|
447
|
+
printErrorsSummary(files, errors) {
|
|
448
|
+
const suites = getSuites(files);
|
|
449
|
+
const tests = getTests(files);
|
|
450
|
+
const failedSuites = suites.filter((i) => i.result?.errors);
|
|
451
|
+
const failedTests = tests.filter((i) => i.result?.state === "fail");
|
|
452
|
+
const failedTotal = countTestErrors(failedSuites) + countTestErrors(failedTests);
|
|
453
|
+
let current = 1;
|
|
454
|
+
const errorDivider = () => this.error(`${c.red(c.dim(divider(`[${current++}/${failedTotal}]`, void 0, 1)))}\n`);
|
|
455
|
+
if (failedSuites.length) {
|
|
456
|
+
this.error(`\n${errorBanner(`Failed Suites ${failedSuites.length}`)}\n`);
|
|
457
|
+
this.printTaskErrors(failedSuites, errorDivider);
|
|
458
|
+
}
|
|
459
|
+
if (failedTests.length) {
|
|
460
|
+
this.error(`\n${errorBanner(`Failed Tests ${failedTests.length}`)}\n`);
|
|
461
|
+
this.printTaskErrors(failedTests, errorDivider);
|
|
462
|
+
}
|
|
463
|
+
if (errors.length) {
|
|
464
|
+
this.ctx.logger.printUnhandledErrors(errors);
|
|
465
|
+
this.error();
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
reportBenchmarkSummary(files) {
|
|
469
|
+
const benches = getTests(files);
|
|
470
|
+
const topBenches = benches.filter((i) => i.result?.benchmark?.rank === 1);
|
|
471
|
+
this.log(`\n${withLabel("cyan", "BENCH", "Summary\n")}`);
|
|
472
|
+
for (const bench of topBenches) {
|
|
473
|
+
const group = bench.suite || bench.file;
|
|
474
|
+
if (!group) continue;
|
|
475
|
+
const groupName = this.getFullName(group, c.dim(" > "));
|
|
476
|
+
const project = this.ctx.projects.find((p) => p.name === bench.file.projectName);
|
|
477
|
+
this.log(` ${formatProjectName(project)}${bench.name}${c.dim(` - ${groupName}`)}`);
|
|
478
|
+
const siblings = group.tasks.filter((i) => i.meta.benchmark && i.result?.benchmark && i !== bench).sort((a, b) => a.result.benchmark.rank - b.result.benchmark.rank);
|
|
479
|
+
for (const sibling of siblings) {
|
|
480
|
+
const number = (sibling.result.benchmark.mean / bench.result.benchmark.mean).toFixed(2);
|
|
481
|
+
this.log(c.green(` ${number}x `) + c.gray("faster than ") + sibling.name);
|
|
482
|
+
}
|
|
483
|
+
this.log("");
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
printTaskErrors(tasks, errorDivider) {
|
|
487
|
+
const errorsQueue = [];
|
|
488
|
+
for (const task of tasks)
|
|
489
|
+
// Merge identical errors
|
|
490
|
+
task.result?.errors?.forEach((error) => {
|
|
491
|
+
let previous;
|
|
492
|
+
if (error?.stack) previous = errorsQueue.find((i) => {
|
|
493
|
+
if (i[0]?.stack !== error.stack) return false;
|
|
494
|
+
const currentProjectName = task?.projectName || task.file?.projectName || "";
|
|
495
|
+
const projectName = i[1][0]?.projectName || i[1][0].file?.projectName || "";
|
|
496
|
+
const currentAnnotations = task.type === "test" && task.annotations;
|
|
497
|
+
const itemAnnotations = i[1][0].type === "test" && i[1][0].annotations;
|
|
498
|
+
return projectName === currentProjectName && deepEqual(currentAnnotations, itemAnnotations);
|
|
499
|
+
});
|
|
500
|
+
if (previous) previous[1].push(task);
|
|
501
|
+
else errorsQueue.push([error, [task]]);
|
|
502
|
+
});
|
|
503
|
+
for (const [error, tasks] of errorsQueue) {
|
|
504
|
+
for (const task of tasks) {
|
|
505
|
+
const filepath = task?.filepath || "";
|
|
506
|
+
const projectName = task?.projectName || task.file?.projectName || "";
|
|
507
|
+
const project = this.ctx.projects.find((p) => p.name === projectName);
|
|
508
|
+
let name = this.getFullName(task, c.dim(" > "));
|
|
509
|
+
if (filepath) name += c.dim(` [ ${this.relative(filepath)} ]`);
|
|
510
|
+
this.ctx.logger.error(`${c.bgRed(c.bold(" FAIL "))} ${formatProjectName(project)}${name}`);
|
|
511
|
+
}
|
|
512
|
+
const screenshotPaths = tasks.map((t) => t.meta?.failScreenshotPath).filter((screenshot) => screenshot != null);
|
|
513
|
+
this.ctx.logger.printError(error, {
|
|
514
|
+
project: this.ctx.getProjectByName(tasks[0].file.projectName || ""),
|
|
515
|
+
verbose: this.verbose,
|
|
516
|
+
screenshotPaths,
|
|
517
|
+
task: tasks[0]
|
|
518
|
+
});
|
|
519
|
+
if (tasks[0].type === "test" && tasks[0].annotations.length) {
|
|
520
|
+
const test = this.ctx.state.getReportedEntity(tasks[0]);
|
|
521
|
+
this.printAnnotations(test, "error", 1);
|
|
522
|
+
this.error();
|
|
523
|
+
}
|
|
524
|
+
errorDivider();
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
function deepEqual(a, b) {
|
|
529
|
+
if (a === b) return true;
|
|
530
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
531
|
+
const keysA = Object.keys(a);
|
|
532
|
+
const keysB = Object.keys(b);
|
|
533
|
+
if (keysA.length !== keysB.length) return false;
|
|
534
|
+
for (const key of keysA) if (!keysB.includes(key) || !deepEqual(a[key], b[key])) return false;
|
|
535
|
+
return true;
|
|
536
|
+
}
|
|
537
|
+
function sum(items, cb) {
|
|
538
|
+
return items.reduce((total, next) => {
|
|
539
|
+
return total + Math.max(cb(next) || 0, 0);
|
|
540
|
+
}, 0);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
class BasicReporter extends BaseReporter {
|
|
544
|
+
constructor() {
|
|
545
|
+
super();
|
|
546
|
+
this.isTTY = false;
|
|
547
|
+
}
|
|
548
|
+
onInit(ctx) {
|
|
549
|
+
super.onInit(ctx);
|
|
550
|
+
ctx.logger.deprecate(`'basic' reporter is deprecated and will be removed in Vitest v3.\nRemove 'basic' from 'reporters' option. To match 'basic' reporter 100%, use configuration:\n${JSON.stringify({ test: { reporters: [["default", { summary: false }]] } }, null, 2)}`);
|
|
551
|
+
}
|
|
552
|
+
reportSummary(files, errors) {
|
|
553
|
+
// non-tty mode doesn't add a new line
|
|
554
|
+
this.ctx.logger.log();
|
|
555
|
+
return super.reportSummary(files, errors);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/// <reference types="../types/index.d.ts" />
|
|
560
|
+
|
|
561
|
+
// (c) 2020-present Andrea Giammarchi
|
|
562
|
+
|
|
563
|
+
const {parse: $parse, stringify: $stringify} = JSON;
|
|
564
|
+
const {keys} = Object;
|
|
565
|
+
|
|
566
|
+
const Primitive = String; // it could be Number
|
|
567
|
+
const primitive = 'string'; // it could be 'number'
|
|
568
|
+
|
|
569
|
+
const ignore = {};
|
|
570
|
+
const object = 'object';
|
|
571
|
+
|
|
572
|
+
const noop = (_, value) => value;
|
|
573
|
+
|
|
574
|
+
const primitives = value => (
|
|
575
|
+
value instanceof Primitive ? Primitive(value) : value
|
|
576
|
+
);
|
|
577
|
+
|
|
578
|
+
const Primitives = (_, value) => (
|
|
579
|
+
typeof value === primitive ? new Primitive(value) : value
|
|
580
|
+
);
|
|
581
|
+
|
|
582
|
+
const revive = (input, parsed, output, $) => {
|
|
583
|
+
const lazy = [];
|
|
584
|
+
for (let ke = keys(output), {length} = ke, y = 0; y < length; y++) {
|
|
585
|
+
const k = ke[y];
|
|
586
|
+
const value = output[k];
|
|
587
|
+
if (value instanceof Primitive) {
|
|
588
|
+
const tmp = input[value];
|
|
589
|
+
if (typeof tmp === object && !parsed.has(tmp)) {
|
|
590
|
+
parsed.add(tmp);
|
|
591
|
+
output[k] = ignore;
|
|
592
|
+
lazy.push({k, a: [input, parsed, tmp, $]});
|
|
593
|
+
}
|
|
594
|
+
else
|
|
595
|
+
output[k] = $.call(output, k, tmp);
|
|
596
|
+
}
|
|
597
|
+
else if (output[k] !== ignore)
|
|
598
|
+
output[k] = $.call(output, k, value);
|
|
599
|
+
}
|
|
600
|
+
for (let {length} = lazy, i = 0; i < length; i++) {
|
|
601
|
+
const {k, a} = lazy[i];
|
|
602
|
+
output[k] = $.call(output, k, revive.apply(null, a));
|
|
603
|
+
}
|
|
604
|
+
return output;
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
const set = (known, input, value) => {
|
|
608
|
+
const index = Primitive(input.push(value) - 1);
|
|
609
|
+
known.set(value, index);
|
|
610
|
+
return index;
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Converts a specialized flatted string into a JS value.
|
|
615
|
+
* @param {string} text
|
|
616
|
+
* @param {(this: any, key: string, value: any) => any} [reviver]
|
|
617
|
+
* @returns {any}
|
|
618
|
+
*/
|
|
619
|
+
const parse = (text, reviver) => {
|
|
620
|
+
const input = $parse(text, Primitives).map(primitives);
|
|
621
|
+
const value = input[0];
|
|
622
|
+
const $ = reviver || noop;
|
|
623
|
+
const tmp = typeof value === object && value ?
|
|
624
|
+
revive(input, new Set, value, $) :
|
|
625
|
+
value;
|
|
626
|
+
return $.call({'': tmp}, '', tmp);
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* Converts a JS value into a specialized flatted string.
|
|
631
|
+
* @param {any} value
|
|
632
|
+
* @param {((this: any, key: string, value: any) => any) | (string | number)[] | null | undefined} [replacer]
|
|
633
|
+
* @param {string | number | undefined} [space]
|
|
634
|
+
* @returns {string}
|
|
635
|
+
*/
|
|
636
|
+
const stringify = (value, replacer, space) => {
|
|
637
|
+
const $ = replacer && typeof replacer === object ?
|
|
638
|
+
(k, v) => (k === '' || -1 < replacer.indexOf(k) ? v : void 0) :
|
|
639
|
+
(replacer || noop);
|
|
640
|
+
const known = new Map;
|
|
641
|
+
const input = [];
|
|
642
|
+
const output = [];
|
|
643
|
+
let i = +set(known, input, $.call({'': value}, '', value));
|
|
644
|
+
let firstRun = !i;
|
|
645
|
+
while (i < input.length) {
|
|
646
|
+
firstRun = true;
|
|
647
|
+
output[i] = $stringify(input[i++], replace, space);
|
|
648
|
+
}
|
|
649
|
+
return '[' + output.join(',') + ']';
|
|
650
|
+
function replace(key, value) {
|
|
651
|
+
if (firstRun) {
|
|
652
|
+
firstRun = !firstRun;
|
|
653
|
+
return value;
|
|
654
|
+
}
|
|
655
|
+
const after = $.call(this, key, value);
|
|
656
|
+
switch (typeof after) {
|
|
657
|
+
case object:
|
|
658
|
+
if (after === null) return after;
|
|
659
|
+
case primitive:
|
|
660
|
+
return known.get(after) || set(known, input, after);
|
|
661
|
+
}
|
|
662
|
+
return after;
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
|
|
666
|
+
class BlobReporter {
|
|
667
|
+
start = 0;
|
|
668
|
+
ctx;
|
|
669
|
+
options;
|
|
670
|
+
constructor(options) {
|
|
671
|
+
this.options = options;
|
|
672
|
+
}
|
|
673
|
+
onInit(ctx) {
|
|
674
|
+
if (ctx.config.watch) throw new Error("Blob reporter is not supported in watch mode");
|
|
675
|
+
this.ctx = ctx;
|
|
676
|
+
this.start = performance.now();
|
|
677
|
+
}
|
|
678
|
+
async onFinished(files = [], errors = [], coverage) {
|
|
679
|
+
const executionTime = performance.now() - this.start;
|
|
680
|
+
let outputFile = this.options.outputFile ?? getOutputFile(this.ctx.config, "blob");
|
|
681
|
+
if (!outputFile) {
|
|
682
|
+
const shard = this.ctx.config.shard;
|
|
683
|
+
outputFile = shard ? `.vitest-reports/blob-${shard.index}-${shard.count}.json` : ".vitest-reports/blob.json";
|
|
684
|
+
}
|
|
685
|
+
const modules = this.ctx.projects.map((project) => {
|
|
686
|
+
return [project.name, [...project.vite.moduleGraph.idToModuleMap.entries()].map((mod) => {
|
|
687
|
+
if (!mod[1].file) return null;
|
|
688
|
+
return [
|
|
689
|
+
mod[0],
|
|
690
|
+
mod[1].file,
|
|
691
|
+
mod[1].url
|
|
692
|
+
];
|
|
693
|
+
}).filter((x) => x != null)];
|
|
694
|
+
});
|
|
695
|
+
const report = [
|
|
696
|
+
this.ctx.version,
|
|
697
|
+
files,
|
|
698
|
+
errors,
|
|
699
|
+
modules,
|
|
700
|
+
coverage,
|
|
701
|
+
executionTime
|
|
702
|
+
];
|
|
703
|
+
const reportFile = resolve(this.ctx.config.root, outputFile);
|
|
704
|
+
await writeBlob(report, reportFile);
|
|
705
|
+
this.ctx.logger.log("blob report written to", reportFile);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
async function writeBlob(content, filename) {
|
|
709
|
+
const report = stringify(content);
|
|
710
|
+
const dir = dirname(filename);
|
|
711
|
+
if (!existsSync(dir)) await mkdir(dir, { recursive: true });
|
|
712
|
+
await writeFile(filename, report, "utf-8");
|
|
713
|
+
}
|
|
714
|
+
async function readBlobs(currentVersion, blobsDirectory, projectsArray) {
|
|
715
|
+
// using process.cwd() because --merge-reports can only be used in CLI
|
|
716
|
+
const resolvedDir = resolve(process.cwd(), blobsDirectory);
|
|
717
|
+
const blobsFiles = await readdir(resolvedDir);
|
|
718
|
+
const promises = blobsFiles.map(async (filename) => {
|
|
719
|
+
const fullPath = resolve(resolvedDir, filename);
|
|
720
|
+
const stats = await stat(fullPath);
|
|
721
|
+
if (!stats.isFile()) throw new TypeError(`vitest.mergeReports() expects all paths in "${blobsDirectory}" to be files generated by the blob reporter, but "${filename}" is not a file`);
|
|
722
|
+
const content = await readFile(fullPath, "utf-8");
|
|
723
|
+
const [version, files, errors, moduleKeys, coverage, executionTime] = parse(content);
|
|
724
|
+
if (!version) throw new TypeError(`vitest.mergeReports() expects all paths in "${blobsDirectory}" to be files generated by the blob reporter, but "${filename}" is not a valid blob file`);
|
|
725
|
+
return {
|
|
726
|
+
version,
|
|
727
|
+
files,
|
|
728
|
+
errors,
|
|
729
|
+
moduleKeys,
|
|
730
|
+
coverage,
|
|
731
|
+
file: filename,
|
|
732
|
+
executionTime
|
|
733
|
+
};
|
|
734
|
+
});
|
|
735
|
+
const blobs = await Promise.all(promises);
|
|
736
|
+
if (!blobs.length) throw new Error(`vitest.mergeReports() requires at least one blob file in "${blobsDirectory}" directory, but none were found`);
|
|
737
|
+
const versions = new Set(blobs.map((blob) => blob.version));
|
|
738
|
+
if (versions.size > 1) throw new Error(`vitest.mergeReports() requires all blob files to be generated by the same Vitest version, received\n\n${blobs.map((b) => `- "${b.file}" uses v${b.version}`).join("\n")}`);
|
|
739
|
+
if (!versions.has(currentVersion)) throw new Error(`the blobs in "${blobsDirectory}" were generated by a different version of Vitest. Expected v${currentVersion}, but received v${blobs[0].version}`);
|
|
740
|
+
// fake module graph - it is used to check if module is imported, but we don't use values inside
|
|
741
|
+
const projects = Object.fromEntries(projectsArray.map((p) => [p.name, p]));
|
|
742
|
+
blobs.forEach((blob) => {
|
|
743
|
+
blob.moduleKeys.forEach(([projectName, moduleIds]) => {
|
|
744
|
+
const project = projects[projectName];
|
|
745
|
+
if (!project) return;
|
|
746
|
+
moduleIds.forEach(([moduleId, file, url]) => {
|
|
747
|
+
const moduleNode = project.vite.moduleGraph.createFileOnlyEntry(file);
|
|
748
|
+
moduleNode.url = url;
|
|
749
|
+
moduleNode.id = moduleId;
|
|
750
|
+
project.vite.moduleGraph.idToModuleMap.set(moduleId, moduleNode);
|
|
751
|
+
});
|
|
752
|
+
});
|
|
753
|
+
});
|
|
754
|
+
const files = blobs.flatMap((blob) => blob.files).sort((f1, f2) => {
|
|
755
|
+
const time1 = f1.result?.startTime || 0;
|
|
756
|
+
const time2 = f2.result?.startTime || 0;
|
|
757
|
+
return time1 - time2;
|
|
758
|
+
});
|
|
759
|
+
const errors = blobs.flatMap((blob) => blob.errors);
|
|
760
|
+
const coverages = blobs.map((blob) => blob.coverage);
|
|
761
|
+
const executionTimes = blobs.map((blob) => blob.executionTime);
|
|
762
|
+
return {
|
|
763
|
+
files,
|
|
764
|
+
errors,
|
|
765
|
+
coverages,
|
|
766
|
+
executionTimes
|
|
767
|
+
};
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
const DEFAULT_RENDER_INTERVAL_MS = 1e3;
|
|
771
|
+
const ESC = "\x1B[";
|
|
772
|
+
const CLEAR_LINE = `${ESC}K`;
|
|
773
|
+
const MOVE_CURSOR_ONE_ROW_UP = `${ESC}1A`;
|
|
774
|
+
const SYNC_START = `${ESC}?2026h`;
|
|
775
|
+
const SYNC_END = `${ESC}?2026l`;
|
|
776
|
+
/**
|
|
777
|
+
* Renders content of `getWindow` at the bottom of the terminal and
|
|
778
|
+
* forwards all other intercepted `stdout` and `stderr` logs above it.
|
|
779
|
+
*/
|
|
780
|
+
class WindowRenderer {
|
|
781
|
+
options;
|
|
782
|
+
streams;
|
|
783
|
+
buffer = [];
|
|
784
|
+
renderInterval = void 0;
|
|
785
|
+
renderScheduled = false;
|
|
786
|
+
windowHeight = 0;
|
|
787
|
+
finished = false;
|
|
788
|
+
cleanups = [];
|
|
789
|
+
constructor(options) {
|
|
790
|
+
this.options = {
|
|
791
|
+
interval: DEFAULT_RENDER_INTERVAL_MS,
|
|
792
|
+
...options
|
|
793
|
+
};
|
|
794
|
+
this.streams = {
|
|
795
|
+
output: options.logger.outputStream.write.bind(options.logger.outputStream),
|
|
796
|
+
error: options.logger.errorStream.write.bind(options.logger.errorStream)
|
|
797
|
+
};
|
|
798
|
+
this.cleanups.push(this.interceptStream(process.stdout, "output"), this.interceptStream(process.stderr, "error"));
|
|
799
|
+
// Write buffered content on unexpected exits, e.g. direct `process.exit()` calls
|
|
800
|
+
this.options.logger.onTerminalCleanup(() => {
|
|
801
|
+
this.flushBuffer();
|
|
802
|
+
this.stop();
|
|
803
|
+
});
|
|
804
|
+
this.start();
|
|
805
|
+
}
|
|
806
|
+
start() {
|
|
807
|
+
this.finished = false;
|
|
808
|
+
this.renderInterval = setInterval(() => this.schedule(), this.options.interval).unref();
|
|
809
|
+
}
|
|
810
|
+
stop() {
|
|
811
|
+
this.cleanups.splice(0).map((fn) => fn());
|
|
812
|
+
clearInterval(this.renderInterval);
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Write all buffered output and stop buffering.
|
|
816
|
+
* All intercepted writes are forwarded to actual write after this.
|
|
817
|
+
*/
|
|
818
|
+
finish() {
|
|
819
|
+
this.finished = true;
|
|
820
|
+
this.flushBuffer();
|
|
821
|
+
clearInterval(this.renderInterval);
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Queue new render update
|
|
825
|
+
*/
|
|
826
|
+
schedule() {
|
|
827
|
+
if (!this.renderScheduled) {
|
|
828
|
+
this.renderScheduled = true;
|
|
829
|
+
this.flushBuffer();
|
|
830
|
+
setTimeout(() => {
|
|
831
|
+
this.renderScheduled = false;
|
|
832
|
+
}, 100).unref();
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
flushBuffer() {
|
|
836
|
+
if (this.buffer.length === 0) return this.render();
|
|
837
|
+
let current;
|
|
838
|
+
// Concatenate same types into a single render
|
|
839
|
+
for (const next of this.buffer.splice(0)) {
|
|
840
|
+
if (!current) {
|
|
841
|
+
current = next;
|
|
842
|
+
continue;
|
|
843
|
+
}
|
|
844
|
+
if (current.type !== next.type) {
|
|
845
|
+
this.render(current.message, current.type);
|
|
846
|
+
current = next;
|
|
847
|
+
continue;
|
|
848
|
+
}
|
|
849
|
+
current.message += next.message;
|
|
850
|
+
}
|
|
851
|
+
if (current) this.render(current?.message, current?.type);
|
|
852
|
+
}
|
|
853
|
+
render(message, type = "output") {
|
|
854
|
+
if (this.finished) {
|
|
855
|
+
this.clearWindow();
|
|
856
|
+
return this.write(message || "", type);
|
|
857
|
+
}
|
|
858
|
+
const windowContent = this.options.getWindow();
|
|
859
|
+
const rowCount = getRenderedRowCount(windowContent, this.options.logger.getColumns());
|
|
860
|
+
let padding = this.windowHeight - rowCount;
|
|
861
|
+
if (padding > 0 && message) padding -= getRenderedRowCount([message], this.options.logger.getColumns());
|
|
862
|
+
this.write(SYNC_START);
|
|
863
|
+
this.clearWindow();
|
|
864
|
+
if (message) this.write(message, type);
|
|
865
|
+
if (padding > 0) this.write("\n".repeat(padding));
|
|
866
|
+
this.write(windowContent.join("\n"));
|
|
867
|
+
this.write(SYNC_END);
|
|
868
|
+
this.windowHeight = rowCount + Math.max(0, padding);
|
|
869
|
+
}
|
|
870
|
+
clearWindow() {
|
|
871
|
+
if (this.windowHeight === 0) return;
|
|
872
|
+
this.write(CLEAR_LINE);
|
|
873
|
+
for (let i = 1; i < this.windowHeight; i++) this.write(`${MOVE_CURSOR_ONE_ROW_UP}${CLEAR_LINE}`);
|
|
874
|
+
this.windowHeight = 0;
|
|
875
|
+
}
|
|
876
|
+
interceptStream(stream, type) {
|
|
877
|
+
const original = stream.write;
|
|
878
|
+
// @ts-expect-error -- not sure how 2 overloads should be typed
|
|
879
|
+
stream.write = (chunk, _, callback) => {
|
|
880
|
+
if (chunk) if (this.finished) this.write(chunk.toString(), type);
|
|
881
|
+
else this.buffer.push({
|
|
882
|
+
type,
|
|
883
|
+
message: chunk.toString()
|
|
884
|
+
});
|
|
885
|
+
callback?.();
|
|
886
|
+
};
|
|
887
|
+
return function restore() {
|
|
888
|
+
stream.write = original;
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
write(message, type = "output") {
|
|
892
|
+
this.streams[type](message);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
/** Calculate the actual row count needed to render `rows` into `stream` */
|
|
896
|
+
function getRenderedRowCount(rows, columns) {
|
|
897
|
+
let count = 0;
|
|
898
|
+
for (const row of rows) {
|
|
899
|
+
const text = stripVTControlCharacters(row);
|
|
900
|
+
count += Math.max(1, Math.ceil(text.length / columns));
|
|
901
|
+
}
|
|
902
|
+
return count;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
const DURATION_UPDATE_INTERVAL_MS = 100;
|
|
906
|
+
const FINISHED_TEST_CLEANUP_TIME_MS = 1e3;
|
|
907
|
+
/**
|
|
908
|
+
* Reporter extension that renders summary and forwards all other logs above itself.
|
|
909
|
+
* Intended to be used by other reporters, not as a standalone reporter.
|
|
910
|
+
*/
|
|
911
|
+
class SummaryReporter {
|
|
912
|
+
ctx;
|
|
913
|
+
options;
|
|
914
|
+
renderer;
|
|
915
|
+
modules = emptyCounters();
|
|
916
|
+
tests = emptyCounters();
|
|
917
|
+
maxParallelTests = 0;
|
|
918
|
+
/** Currently running test modules, may include finished test modules too */
|
|
919
|
+
runningModules = /* @__PURE__ */ new Map();
|
|
920
|
+
/** ID of finished `this.runningModules` that are currently being shown */
|
|
921
|
+
finishedModules = /* @__PURE__ */ new Map();
|
|
922
|
+
startTime = "";
|
|
923
|
+
currentTime = 0;
|
|
924
|
+
duration = 0;
|
|
925
|
+
durationInterval = void 0;
|
|
926
|
+
onInit(ctx, options = {}) {
|
|
927
|
+
this.ctx = ctx;
|
|
928
|
+
this.options = {
|
|
929
|
+
verbose: false,
|
|
930
|
+
...options
|
|
931
|
+
};
|
|
932
|
+
this.renderer = new WindowRenderer({
|
|
933
|
+
logger: ctx.logger,
|
|
934
|
+
getWindow: () => this.createSummary()
|
|
935
|
+
});
|
|
936
|
+
this.ctx.onClose(() => {
|
|
937
|
+
clearInterval(this.durationInterval);
|
|
938
|
+
this.renderer.stop();
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
onTestRunStart(specifications) {
|
|
942
|
+
this.runningModules.clear();
|
|
943
|
+
this.finishedModules.clear();
|
|
944
|
+
this.modules = emptyCounters();
|
|
945
|
+
this.tests = emptyCounters();
|
|
946
|
+
this.startTimers();
|
|
947
|
+
this.renderer.start();
|
|
948
|
+
this.modules.total = specifications.length;
|
|
949
|
+
}
|
|
950
|
+
onTestRunEnd() {
|
|
951
|
+
this.runningModules.clear();
|
|
952
|
+
this.finishedModules.clear();
|
|
953
|
+
this.renderer.finish();
|
|
954
|
+
clearInterval(this.durationInterval);
|
|
955
|
+
}
|
|
956
|
+
onTestModuleQueued(module) {
|
|
957
|
+
// When new test module starts, take the place of previously finished test module, if any
|
|
958
|
+
if (this.finishedModules.size) {
|
|
959
|
+
const finished = this.finishedModules.keys().next().value;
|
|
960
|
+
this.removeTestModule(finished);
|
|
961
|
+
}
|
|
962
|
+
this.runningModules.set(module.id, initializeStats(module));
|
|
963
|
+
this.renderer.schedule();
|
|
964
|
+
}
|
|
965
|
+
onTestModuleCollected(module) {
|
|
966
|
+
let stats = this.runningModules.get(module.id);
|
|
967
|
+
if (!stats) {
|
|
968
|
+
stats = initializeStats(module);
|
|
969
|
+
this.runningModules.set(module.id, stats);
|
|
970
|
+
}
|
|
971
|
+
const total = Array.from(module.children.allTests()).length;
|
|
972
|
+
this.tests.total += total;
|
|
973
|
+
stats.total = total;
|
|
974
|
+
this.maxParallelTests = Math.max(this.maxParallelTests, this.runningModules.size);
|
|
975
|
+
this.renderer.schedule();
|
|
976
|
+
}
|
|
977
|
+
onHookStart(options) {
|
|
978
|
+
const stats = this.getHookStats(options);
|
|
979
|
+
if (!stats) return;
|
|
980
|
+
const hook = {
|
|
981
|
+
name: options.name,
|
|
982
|
+
visible: false,
|
|
983
|
+
startTime: performance.now(),
|
|
984
|
+
onFinish: () => {}
|
|
985
|
+
};
|
|
986
|
+
stats.hook?.onFinish?.();
|
|
987
|
+
stats.hook = hook;
|
|
988
|
+
const timeout = setTimeout(() => {
|
|
989
|
+
hook.visible = true;
|
|
990
|
+
}, this.ctx.config.slowTestThreshold).unref();
|
|
991
|
+
hook.onFinish = () => clearTimeout(timeout);
|
|
992
|
+
}
|
|
993
|
+
onHookEnd(options) {
|
|
994
|
+
const stats = this.getHookStats(options);
|
|
995
|
+
if (stats?.hook?.name !== options.name) return;
|
|
996
|
+
stats.hook.onFinish();
|
|
997
|
+
stats.hook.visible = false;
|
|
998
|
+
}
|
|
999
|
+
onTestCaseReady(test) {
|
|
1000
|
+
// Track slow running tests only on verbose mode
|
|
1001
|
+
if (!this.options.verbose) return;
|
|
1002
|
+
const stats = this.runningModules.get(test.module.id);
|
|
1003
|
+
if (!stats || stats.tests.has(test.id)) return;
|
|
1004
|
+
const slowTest = {
|
|
1005
|
+
name: test.name,
|
|
1006
|
+
visible: false,
|
|
1007
|
+
startTime: performance.now(),
|
|
1008
|
+
onFinish: () => {}
|
|
1009
|
+
};
|
|
1010
|
+
const timeout = setTimeout(() => {
|
|
1011
|
+
slowTest.visible = true;
|
|
1012
|
+
}, this.ctx.config.slowTestThreshold).unref();
|
|
1013
|
+
slowTest.onFinish = () => {
|
|
1014
|
+
slowTest.hook?.onFinish();
|
|
1015
|
+
clearTimeout(timeout);
|
|
1016
|
+
};
|
|
1017
|
+
stats.tests.set(test.id, slowTest);
|
|
1018
|
+
}
|
|
1019
|
+
onTestCaseResult(test) {
|
|
1020
|
+
const stats = this.runningModules.get(test.module.id);
|
|
1021
|
+
if (!stats) return;
|
|
1022
|
+
stats.tests.get(test.id)?.onFinish();
|
|
1023
|
+
stats.tests.delete(test.id);
|
|
1024
|
+
stats.completed++;
|
|
1025
|
+
const result = test.result();
|
|
1026
|
+
if (result?.state === "passed") this.tests.passed++;
|
|
1027
|
+
else if (result?.state === "failed") this.tests.failed++;
|
|
1028
|
+
else if (!result?.state || result?.state === "skipped") this.tests.skipped++;
|
|
1029
|
+
this.renderer.schedule();
|
|
1030
|
+
}
|
|
1031
|
+
onTestModuleEnd(module) {
|
|
1032
|
+
const state = module.state();
|
|
1033
|
+
this.modules.completed++;
|
|
1034
|
+
if (state === "passed") this.modules.passed++;
|
|
1035
|
+
else if (state === "failed") this.modules.failed++;
|
|
1036
|
+
else if (module.task.mode === "todo" && state === "skipped") this.modules.todo++;
|
|
1037
|
+
else if (state === "skipped") this.modules.skipped++;
|
|
1038
|
+
const left = this.modules.total - this.modules.completed;
|
|
1039
|
+
// Keep finished tests visible in summary for a while if there are more tests left.
|
|
1040
|
+
// When a new test starts in onTestModuleQueued it will take this ones place.
|
|
1041
|
+
// This reduces flickering by making summary more stable.
|
|
1042
|
+
if (left > this.maxParallelTests) this.finishedModules.set(module.id, setTimeout(() => {
|
|
1043
|
+
this.removeTestModule(module.id);
|
|
1044
|
+
}, FINISHED_TEST_CLEANUP_TIME_MS).unref());
|
|
1045
|
+
else
|
|
1046
|
+
// Run is about to end as there are less tests left than whole run had parallel at max.
|
|
1047
|
+
// Remove finished test immediately.
|
|
1048
|
+
this.removeTestModule(module.id);
|
|
1049
|
+
this.renderer.schedule();
|
|
1050
|
+
}
|
|
1051
|
+
getHookStats({ entity }) {
|
|
1052
|
+
// Track slow running hooks only on verbose mode
|
|
1053
|
+
if (!this.options.verbose) return;
|
|
1054
|
+
const module = entity.type === "module" ? entity : entity.module;
|
|
1055
|
+
const stats = this.runningModules.get(module.id);
|
|
1056
|
+
if (!stats) return;
|
|
1057
|
+
return entity.type === "test" ? stats.tests.get(entity.id) : stats;
|
|
1058
|
+
}
|
|
1059
|
+
createSummary() {
|
|
1060
|
+
const summary = [""];
|
|
1061
|
+
for (const testFile of Array.from(this.runningModules.values()).sort(sortRunningModules)) {
|
|
1062
|
+
const typecheck = testFile.typecheck ? `${c.bgBlue(c.bold(" TS "))} ` : "";
|
|
1063
|
+
summary.push(c.bold(c.yellow(` ${F_POINTER} `)) + formatProjectName({
|
|
1064
|
+
name: testFile.projectName,
|
|
1065
|
+
color: testFile.projectColor
|
|
1066
|
+
}) + typecheck + testFile.filename + c.dim(!testFile.completed && !testFile.total ? " [queued]" : ` ${testFile.completed}/${testFile.total}`));
|
|
1067
|
+
const slowTasks = [testFile.hook, ...Array.from(testFile.tests.values())].filter((t) => t != null && t.visible);
|
|
1068
|
+
for (const [index, task] of slowTasks.entries()) {
|
|
1069
|
+
const elapsed = this.currentTime - task.startTime;
|
|
1070
|
+
const icon = index === slowTasks.length - 1 ? F_TREE_NODE_END : F_TREE_NODE_MIDDLE;
|
|
1071
|
+
summary.push(c.bold(c.yellow(` ${icon} `)) + task.name + c.bold(c.yellow(` ${formatTime(Math.max(0, elapsed))}`)));
|
|
1072
|
+
if (task.hook?.visible) summary.push(c.bold(c.yellow(` ${F_TREE_NODE_END} `)) + task.hook.name);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
if (this.runningModules.size > 0) summary.push("");
|
|
1076
|
+
summary.push(padSummaryTitle("Test Files") + getStateString(this.modules));
|
|
1077
|
+
summary.push(padSummaryTitle("Tests") + getStateString(this.tests));
|
|
1078
|
+
summary.push(padSummaryTitle("Start at") + this.startTime);
|
|
1079
|
+
summary.push(padSummaryTitle("Duration") + formatTime(this.duration));
|
|
1080
|
+
summary.push("");
|
|
1081
|
+
return summary;
|
|
1082
|
+
}
|
|
1083
|
+
startTimers() {
|
|
1084
|
+
const start = performance.now();
|
|
1085
|
+
this.startTime = formatTimeString(/* @__PURE__ */ new Date());
|
|
1086
|
+
this.durationInterval = setInterval(() => {
|
|
1087
|
+
this.currentTime = performance.now();
|
|
1088
|
+
this.duration = this.currentTime - start;
|
|
1089
|
+
}, DURATION_UPDATE_INTERVAL_MS).unref();
|
|
1090
|
+
}
|
|
1091
|
+
removeTestModule(id) {
|
|
1092
|
+
if (!id) return;
|
|
1093
|
+
const testFile = this.runningModules.get(id);
|
|
1094
|
+
testFile?.hook?.onFinish();
|
|
1095
|
+
testFile?.tests?.forEach((test) => test.onFinish());
|
|
1096
|
+
this.runningModules.delete(id);
|
|
1097
|
+
clearTimeout(this.finishedModules.get(id));
|
|
1098
|
+
this.finishedModules.delete(id);
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
function emptyCounters() {
|
|
1102
|
+
return {
|
|
1103
|
+
completed: 0,
|
|
1104
|
+
passed: 0,
|
|
1105
|
+
failed: 0,
|
|
1106
|
+
skipped: 0,
|
|
1107
|
+
todo: 0,
|
|
1108
|
+
total: 0
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
function getStateString(entry) {
|
|
1112
|
+
return [
|
|
1113
|
+
entry.failed ? c.bold(c.red(`${entry.failed} failed`)) : null,
|
|
1114
|
+
c.bold(c.green(`${entry.passed} passed`)),
|
|
1115
|
+
entry.skipped ? c.yellow(`${entry.skipped} skipped`) : null,
|
|
1116
|
+
entry.todo ? c.gray(`${entry.todo} todo`) : null
|
|
1117
|
+
].filter(Boolean).join(c.dim(" | ")) + c.gray(` (${entry.total})`);
|
|
1118
|
+
}
|
|
1119
|
+
function sortRunningModules(a, b) {
|
|
1120
|
+
if ((a.projectName || "") > (b.projectName || "")) return 1;
|
|
1121
|
+
if ((a.projectName || "") < (b.projectName || "")) return -1;
|
|
1122
|
+
return a.filename.localeCompare(b.filename);
|
|
1123
|
+
}
|
|
1124
|
+
function initializeStats(module) {
|
|
1125
|
+
return {
|
|
1126
|
+
total: 0,
|
|
1127
|
+
completed: 0,
|
|
1128
|
+
filename: module.task.name,
|
|
1129
|
+
projectName: module.project.name,
|
|
1130
|
+
projectColor: module.project.color,
|
|
1131
|
+
tests: /* @__PURE__ */ new Map(),
|
|
1132
|
+
typecheck: !!module.task.meta.typecheck
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
class DefaultReporter extends BaseReporter {
|
|
1137
|
+
options;
|
|
1138
|
+
summary;
|
|
1139
|
+
constructor(options = {}) {
|
|
1140
|
+
super(options);
|
|
1141
|
+
this.options = {
|
|
1142
|
+
summary: true,
|
|
1143
|
+
...options
|
|
1144
|
+
};
|
|
1145
|
+
if (!this.isTTY) this.options.summary = false;
|
|
1146
|
+
if (this.options.summary) this.summary = new SummaryReporter();
|
|
1147
|
+
}
|
|
1148
|
+
onTestRunStart(specifications) {
|
|
1149
|
+
if (this.isTTY) {
|
|
1150
|
+
if (this.renderSucceed === void 0) this.renderSucceed = !!this.renderSucceed;
|
|
1151
|
+
if (this.renderSucceed !== true) this.renderSucceed = specifications.length <= 1;
|
|
1152
|
+
}
|
|
1153
|
+
this.summary?.onTestRunStart(specifications);
|
|
1154
|
+
}
|
|
1155
|
+
onTestModuleQueued(file) {
|
|
1156
|
+
this.summary?.onTestModuleQueued(file);
|
|
1157
|
+
}
|
|
1158
|
+
onTestModuleCollected(module) {
|
|
1159
|
+
this.summary?.onTestModuleCollected(module);
|
|
1160
|
+
}
|
|
1161
|
+
onTestModuleEnd(module) {
|
|
1162
|
+
super.onTestModuleEnd(module);
|
|
1163
|
+
this.summary?.onTestModuleEnd(module);
|
|
1164
|
+
}
|
|
1165
|
+
onTestCaseReady(test) {
|
|
1166
|
+
this.summary?.onTestCaseReady(test);
|
|
1167
|
+
}
|
|
1168
|
+
onTestCaseResult(test) {
|
|
1169
|
+
super.onTestCaseResult(test);
|
|
1170
|
+
this.summary?.onTestCaseResult(test);
|
|
1171
|
+
}
|
|
1172
|
+
onHookStart(hook) {
|
|
1173
|
+
this.summary?.onHookStart(hook);
|
|
1174
|
+
}
|
|
1175
|
+
onHookEnd(hook) {
|
|
1176
|
+
this.summary?.onHookEnd(hook);
|
|
1177
|
+
}
|
|
1178
|
+
onInit(ctx) {
|
|
1179
|
+
super.onInit(ctx);
|
|
1180
|
+
this.summary?.onInit(ctx, { verbose: this.verbose });
|
|
1181
|
+
}
|
|
1182
|
+
onTestRunEnd() {
|
|
1183
|
+
this.summary?.onTestRunEnd();
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
class DotReporter extends BaseReporter {
|
|
1188
|
+
renderer;
|
|
1189
|
+
tests = /* @__PURE__ */ new Map();
|
|
1190
|
+
finishedTests = /* @__PURE__ */ new Set();
|
|
1191
|
+
onInit(ctx) {
|
|
1192
|
+
super.onInit(ctx);
|
|
1193
|
+
if (this.isTTY) {
|
|
1194
|
+
this.renderer = new WindowRenderer({
|
|
1195
|
+
logger: ctx.logger,
|
|
1196
|
+
getWindow: () => this.createSummary()
|
|
1197
|
+
});
|
|
1198
|
+
this.ctx.onClose(() => this.renderer?.stop());
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
// Ignore default logging of base reporter
|
|
1202
|
+
printTestModule() {}
|
|
1203
|
+
onWatcherRerun(files, trigger) {
|
|
1204
|
+
this.tests.clear();
|
|
1205
|
+
this.renderer?.start();
|
|
1206
|
+
super.onWatcherRerun(files, trigger);
|
|
1207
|
+
}
|
|
1208
|
+
onFinished(files, errors) {
|
|
1209
|
+
if (this.isTTY) {
|
|
1210
|
+
const finalLog = formatTests(Array.from(this.tests.values()));
|
|
1211
|
+
this.ctx.logger.log(finalLog);
|
|
1212
|
+
} else this.ctx.logger.log();
|
|
1213
|
+
this.tests.clear();
|
|
1214
|
+
this.renderer?.finish();
|
|
1215
|
+
super.onFinished(files, errors);
|
|
1216
|
+
}
|
|
1217
|
+
onTestModuleCollected(module) {
|
|
1218
|
+
for (const test of module.children.allTests())
|
|
1219
|
+
// Dot reporter marks pending tests as running
|
|
1220
|
+
this.onTestCaseReady(test);
|
|
1221
|
+
}
|
|
1222
|
+
onTestCaseReady(test) {
|
|
1223
|
+
if (this.finishedTests.has(test.id)) return;
|
|
1224
|
+
this.tests.set(test.id, test.result().state || "run");
|
|
1225
|
+
this.renderer?.schedule();
|
|
1226
|
+
}
|
|
1227
|
+
onTestCaseResult(test) {
|
|
1228
|
+
const result = test.result().state;
|
|
1229
|
+
// On non-TTY the finished tests are printed immediately
|
|
1230
|
+
if (!this.isTTY && result !== "pending") this.ctx.logger.outputStream.write(formatTests([result]));
|
|
1231
|
+
super.onTestCaseResult(test);
|
|
1232
|
+
this.finishedTests.add(test.id);
|
|
1233
|
+
this.tests.set(test.id, result || "skipped");
|
|
1234
|
+
this.renderer?.schedule();
|
|
1235
|
+
}
|
|
1236
|
+
onTestModuleEnd(testModule) {
|
|
1237
|
+
super.onTestModuleEnd(testModule);
|
|
1238
|
+
if (!this.isTTY) return;
|
|
1239
|
+
const columns = this.ctx.logger.getColumns();
|
|
1240
|
+
if (this.tests.size < columns) return;
|
|
1241
|
+
const finishedTests = Array.from(this.tests).filter((entry) => entry[1] !== "pending");
|
|
1242
|
+
if (finishedTests.length < columns) return;
|
|
1243
|
+
// Remove finished tests from state and render them in static output
|
|
1244
|
+
const states = [];
|
|
1245
|
+
let count = 0;
|
|
1246
|
+
for (const [id, state] of finishedTests) {
|
|
1247
|
+
if (count++ >= columns) break;
|
|
1248
|
+
this.tests.delete(id);
|
|
1249
|
+
states.push(state);
|
|
1250
|
+
}
|
|
1251
|
+
this.ctx.logger.log(formatTests(states));
|
|
1252
|
+
this.renderer?.schedule();
|
|
1253
|
+
}
|
|
1254
|
+
createSummary() {
|
|
1255
|
+
return [formatTests(Array.from(this.tests.values())), ""];
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
// These are compared with reference equality in formatTests
|
|
1259
|
+
const pass = {
|
|
1260
|
+
char: "·",
|
|
1261
|
+
color: c.green
|
|
1262
|
+
};
|
|
1263
|
+
const fail = {
|
|
1264
|
+
char: "x",
|
|
1265
|
+
color: c.red
|
|
1266
|
+
};
|
|
1267
|
+
const pending = {
|
|
1268
|
+
char: "*",
|
|
1269
|
+
color: c.yellow
|
|
1270
|
+
};
|
|
1271
|
+
const skip = {
|
|
1272
|
+
char: "-",
|
|
1273
|
+
color: (char) => c.dim(c.gray(char))
|
|
1274
|
+
};
|
|
1275
|
+
function getIcon(state) {
|
|
1276
|
+
switch (state) {
|
|
1277
|
+
case "passed": return pass;
|
|
1278
|
+
case "failed": return fail;
|
|
1279
|
+
case "skipped": return skip;
|
|
1280
|
+
default: return pending;
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
/**
|
|
1284
|
+
* Format test states into string while keeping ANSI escapes at minimal.
|
|
1285
|
+
* Sibling icons with same color are merged into a single c.color() call.
|
|
1286
|
+
*/
|
|
1287
|
+
function formatTests(states) {
|
|
1288
|
+
let currentIcon = pending;
|
|
1289
|
+
let count = 0;
|
|
1290
|
+
let output = "";
|
|
1291
|
+
for (const state of states) {
|
|
1292
|
+
const icon = getIcon(state);
|
|
1293
|
+
if (currentIcon === icon) {
|
|
1294
|
+
count++;
|
|
1295
|
+
continue;
|
|
1296
|
+
}
|
|
1297
|
+
output += currentIcon.color(currentIcon.char.repeat(count));
|
|
1298
|
+
// Start tracking new group
|
|
1299
|
+
count = 1;
|
|
1300
|
+
currentIcon = icon;
|
|
1301
|
+
}
|
|
1302
|
+
output += currentIcon.color(currentIcon.char.repeat(count));
|
|
1303
|
+
return output;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
// use Logger with custom Console to capture entire error printing
|
|
1307
|
+
function capturePrintError(error, ctx, options) {
|
|
1308
|
+
let output = "";
|
|
1309
|
+
const writable = new Writable({ write(chunk, _encoding, callback) {
|
|
1310
|
+
output += String(chunk);
|
|
1311
|
+
callback();
|
|
1312
|
+
} });
|
|
1313
|
+
const console = new Console(writable);
|
|
1314
|
+
const logger = {
|
|
1315
|
+
error: console.error.bind(console),
|
|
1316
|
+
highlight: ctx.logger.highlight.bind(ctx.logger)
|
|
1317
|
+
};
|
|
1318
|
+
const result = printError(error, ctx, logger, {
|
|
1319
|
+
showCodeFrame: false,
|
|
1320
|
+
...options
|
|
1321
|
+
});
|
|
1322
|
+
return {
|
|
1323
|
+
nearest: result?.nearest,
|
|
1324
|
+
output
|
|
1325
|
+
};
|
|
1326
|
+
}
|
|
1327
|
+
function printError(error, ctx, logger, options) {
|
|
1328
|
+
const project = options.project ?? ctx.coreWorkspaceProject ?? ctx.projects[0];
|
|
1329
|
+
return printErrorInner(error, project, {
|
|
1330
|
+
logger,
|
|
1331
|
+
type: options.type,
|
|
1332
|
+
showCodeFrame: options.showCodeFrame,
|
|
1333
|
+
screenshotPaths: options.screenshotPaths,
|
|
1334
|
+
printProperties: options.verbose,
|
|
1335
|
+
parseErrorStacktrace(error) {
|
|
1336
|
+
// browser stack trace needs to be processed differently,
|
|
1337
|
+
// so there is a separate method for that
|
|
1338
|
+
if (options.task?.file.pool === "browser" && project.browser) return project.browser.parseErrorStacktrace(error, { ignoreStackEntries: options.fullStack ? [] : void 0 });
|
|
1339
|
+
// node.js stack trace already has correct source map locations
|
|
1340
|
+
return parseErrorStacktrace(error, {
|
|
1341
|
+
frameFilter: project.config.onStackTrace,
|
|
1342
|
+
ignoreStackEntries: options.fullStack ? [] : void 0
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
});
|
|
1346
|
+
}
|
|
1347
|
+
function printErrorInner(error, project, options) {
|
|
1348
|
+
const { showCodeFrame = true, type, printProperties = true } = options;
|
|
1349
|
+
const logger = options.logger;
|
|
1350
|
+
let e = error;
|
|
1351
|
+
if (isPrimitive(e)) e = {
|
|
1352
|
+
message: String(error).split(/\n/g)[0],
|
|
1353
|
+
stack: String(error)
|
|
1354
|
+
};
|
|
1355
|
+
if (!e) {
|
|
1356
|
+
const error = new Error("unknown error");
|
|
1357
|
+
e = {
|
|
1358
|
+
message: e ?? error.message,
|
|
1359
|
+
stack: error.stack
|
|
1360
|
+
};
|
|
1361
|
+
}
|
|
1362
|
+
// Error may have occurred even before the configuration was resolved
|
|
1363
|
+
if (!project) {
|
|
1364
|
+
printErrorMessage(e, logger);
|
|
1365
|
+
return;
|
|
1366
|
+
}
|
|
1367
|
+
const stacks = options.parseErrorStacktrace(e);
|
|
1368
|
+
const nearest = error instanceof TypeCheckError ? error.stacks[0] : stacks.find((stack) => {
|
|
1369
|
+
try {
|
|
1370
|
+
return project._vite && project.getModuleById(stack.file) && existsSync(stack.file);
|
|
1371
|
+
} catch {
|
|
1372
|
+
return false;
|
|
1373
|
+
}
|
|
1374
|
+
});
|
|
1375
|
+
if (type) printErrorType(type, project.vitest);
|
|
1376
|
+
printErrorMessage(e, logger);
|
|
1377
|
+
if (options.screenshotPaths?.length) {
|
|
1378
|
+
const length = options.screenshotPaths.length;
|
|
1379
|
+
logger.error(`\nFailure screenshot${length > 1 ? "s" : ""}:`);
|
|
1380
|
+
logger.error(options.screenshotPaths.map((p) => ` - ${c.dim(relative(process.cwd(), p))}`).join("\n"));
|
|
1381
|
+
if (!e.diff) logger.error();
|
|
1382
|
+
}
|
|
1383
|
+
if (e.codeFrame) logger.error(`${e.codeFrame}\n`);
|
|
1384
|
+
if ("__vitest_rollup_error__" in e) {
|
|
1385
|
+
// https://github.com/vitejs/vite/blob/95020ab49e12d143262859e095025cf02423c1d9/packages/vite/src/node/server/middlewares/error.ts#L25-L36
|
|
1386
|
+
const err = e.__vitest_rollup_error__;
|
|
1387
|
+
logger.error([
|
|
1388
|
+
err.plugin && ` Plugin: ${c.magenta(err.plugin)}`,
|
|
1389
|
+
err.id && ` File: ${c.cyan(err.id)}${err.loc ? `:${err.loc.line}:${err.loc.column}` : ""}`,
|
|
1390
|
+
err.frame && c.yellow(err.frame.split(/\r?\n/g).map((l) => ` `.repeat(2) + l).join(`\n`))
|
|
1391
|
+
].filter(Boolean).join("\n"));
|
|
1392
|
+
}
|
|
1393
|
+
// E.g. AssertionError from assert does not set showDiff but has both actual and expected properties
|
|
1394
|
+
if (e.diff) logger.error(`\n${e.diff}\n`);
|
|
1395
|
+
// if the error provide the frame
|
|
1396
|
+
if (e.frame) logger.error(c.yellow(e.frame));
|
|
1397
|
+
else {
|
|
1398
|
+
const errorProperties = printProperties ? getErrorProperties(e) : {};
|
|
1399
|
+
printStack(logger, project, stacks, nearest, errorProperties, (s) => {
|
|
1400
|
+
if (showCodeFrame && s === nearest && nearest) {
|
|
1401
|
+
const sourceCode = readFileSync(nearest.file, "utf-8");
|
|
1402
|
+
logger.error(generateCodeFrame(sourceCode.length > 1e5 ? sourceCode : logger.highlight(nearest.file, sourceCode), 4, s));
|
|
1403
|
+
}
|
|
1404
|
+
});
|
|
1405
|
+
}
|
|
1406
|
+
const testPath = e.VITEST_TEST_PATH;
|
|
1407
|
+
const testName = e.VITEST_TEST_NAME;
|
|
1408
|
+
const afterEnvTeardown = e.VITEST_AFTER_ENV_TEARDOWN;
|
|
1409
|
+
// testName has testPath inside
|
|
1410
|
+
if (testPath) logger.error(c.red(`This error originated in "${c.bold(relative(project.config.root, testPath))}" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.`));
|
|
1411
|
+
if (testName) logger.error(c.red(`The latest test that might've caused the error is "${c.bold(testName)}". It might mean one of the following:
|
|
1412
|
+
- The error was thrown, while Vitest was running this test.
|
|
1413
|
+
- If the error occurred after the test had been completed, this was the last documented test before it was thrown.`));
|
|
1414
|
+
if (afterEnvTeardown) logger.error(c.red("This error was caught after test environment was torn down. Make sure to cancel any running tasks before test finishes:\n- cancel timeouts using clearTimeout and clearInterval\n- wait for promises to resolve using the await keyword"));
|
|
1415
|
+
if (typeof e.cause === "object" && e.cause && "name" in e.cause) {
|
|
1416
|
+
e.cause.name = `Caused by: ${e.cause.name}`;
|
|
1417
|
+
printErrorInner(e.cause, project, {
|
|
1418
|
+
showCodeFrame: false,
|
|
1419
|
+
logger: options.logger,
|
|
1420
|
+
parseErrorStacktrace: options.parseErrorStacktrace
|
|
1421
|
+
});
|
|
1422
|
+
}
|
|
1423
|
+
handleImportOutsideModuleError(e.stack || "", logger);
|
|
1424
|
+
return { nearest };
|
|
1425
|
+
}
|
|
1426
|
+
function printErrorType(type, ctx) {
|
|
1427
|
+
ctx.logger.error(`\n${errorBanner(type)}`);
|
|
1428
|
+
}
|
|
1429
|
+
const skipErrorProperties = new Set([
|
|
1430
|
+
"cause",
|
|
1431
|
+
"stacks",
|
|
1432
|
+
"type",
|
|
1433
|
+
"showDiff",
|
|
1434
|
+
"ok",
|
|
1435
|
+
"operator",
|
|
1436
|
+
"diff",
|
|
1437
|
+
"codeFrame",
|
|
1438
|
+
"actual",
|
|
1439
|
+
"expected",
|
|
1440
|
+
"diffOptions",
|
|
1441
|
+
"sourceURL",
|
|
1442
|
+
"column",
|
|
1443
|
+
"line",
|
|
1444
|
+
"fileName",
|
|
1445
|
+
"lineNumber",
|
|
1446
|
+
"columnNumber",
|
|
1447
|
+
"VITEST_TEST_NAME",
|
|
1448
|
+
"VITEST_TEST_PATH",
|
|
1449
|
+
"VITEST_AFTER_ENV_TEARDOWN",
|
|
1450
|
+
"__vitest_rollup_error__",
|
|
1451
|
+
...Object.getOwnPropertyNames(Error.prototype),
|
|
1452
|
+
...Object.getOwnPropertyNames(Object.prototype)
|
|
1453
|
+
]);
|
|
1454
|
+
function getErrorProperties(e) {
|
|
1455
|
+
const errorObject = Object.create(null);
|
|
1456
|
+
if (e.name === "AssertionError") return errorObject;
|
|
1457
|
+
for (const key of Object.getOwnPropertyNames(e))
|
|
1458
|
+
// print the original stack if it was ever changed manually by the user
|
|
1459
|
+
if (key === "stack" && e[key] != null && typeof e[key] !== "string") errorObject[key] = e[key];
|
|
1460
|
+
else if (key !== "stack" && !skipErrorProperties.has(key)) errorObject[key] = e[key];
|
|
1461
|
+
return errorObject;
|
|
1462
|
+
}
|
|
1463
|
+
const esmErrors = ["Cannot use import statement outside a module", "Unexpected token 'export'"];
|
|
1464
|
+
function handleImportOutsideModuleError(stack, logger) {
|
|
1465
|
+
if (!esmErrors.some((e) => stack.includes(e))) return;
|
|
1466
|
+
const path = normalize(stack.split("\n")[0].trim());
|
|
1467
|
+
let name = path.split("/node_modules/").pop() || "";
|
|
1468
|
+
if (name?.startsWith("@")) name = name.split("/").slice(0, 2).join("/");
|
|
1469
|
+
else name = name.split("/")[0];
|
|
1470
|
+
if (name) printModuleWarningForPackage(logger, path, name);
|
|
1471
|
+
else printModuleWarningForSourceCode(logger, path);
|
|
1472
|
+
}
|
|
1473
|
+
function printModuleWarningForPackage(logger, path, name) {
|
|
1474
|
+
logger.error(c.yellow(`Module ${path} seems to be an ES Module but shipped in a CommonJS package. You might want to create an issue to the package ${c.bold(`"${name}"`)} asking them to ship the file in .mjs extension or add "type": "module" in their package.json.
|
|
1475
|
+
|
|
1476
|
+
As a temporary workaround you can try to inline the package by updating your config:
|
|
1477
|
+
|
|
1478
|
+
` + c.gray(c.dim("// vitest.config.js")) + "\n" + c.green(`export default {
|
|
1479
|
+
test: {
|
|
1480
|
+
server: {
|
|
1481
|
+
deps: {
|
|
1482
|
+
inline: [
|
|
1483
|
+
${c.yellow(c.bold(`"${name}"`))}
|
|
1484
|
+
]
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
}\n`)));
|
|
1489
|
+
}
|
|
1490
|
+
function printModuleWarningForSourceCode(logger, path) {
|
|
1491
|
+
logger.error(c.yellow(`Module ${path} seems to be an ES Module but shipped in a CommonJS package. To fix this issue, change the file extension to .mjs or add "type": "module" in your package.json.`));
|
|
1492
|
+
}
|
|
1493
|
+
function printErrorMessage(error, logger) {
|
|
1494
|
+
const errorName = error.name || "Unknown Error";
|
|
1495
|
+
if (!error.message) {
|
|
1496
|
+
logger.error(error);
|
|
1497
|
+
return;
|
|
1498
|
+
}
|
|
1499
|
+
if (error.message.length > 5e3)
|
|
1500
|
+
// Protect against infinite stack trace in tinyrainbow
|
|
1501
|
+
logger.error(`${c.red(c.bold(errorName))}: ${error.message}`);
|
|
1502
|
+
else logger.error(c.red(`${c.bold(errorName)}: ${error.message}`));
|
|
1503
|
+
}
|
|
1504
|
+
function printStack(logger, project, stack, highlight, errorProperties, onStack) {
|
|
1505
|
+
for (const frame of stack) {
|
|
1506
|
+
const color = frame === highlight ? c.cyan : c.gray;
|
|
1507
|
+
const path = relative(project.config.root, frame.file);
|
|
1508
|
+
logger.error(color(` ${c.dim(F_POINTER)} ${[frame.method, `${path}:${c.dim(`${frame.line}:${frame.column}`)}`].filter(Boolean).join(" ")}`));
|
|
1509
|
+
onStack?.(frame);
|
|
1510
|
+
}
|
|
1511
|
+
if (stack.length) logger.error();
|
|
1512
|
+
if (hasProperties(errorProperties)) {
|
|
1513
|
+
logger.error(c.red(c.dim(divider())));
|
|
1514
|
+
const propertiesString = inspect(errorProperties);
|
|
1515
|
+
logger.error(c.red(c.bold("Serialized Error:")), c.gray(propertiesString));
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
function hasProperties(obj) {
|
|
1519
|
+
// eslint-disable-next-line no-unreachable-loop
|
|
1520
|
+
for (const _key in obj) return true;
|
|
1521
|
+
return false;
|
|
1522
|
+
}
|
|
1523
|
+
function generateCodeFrame(source, indent = 0, loc, range = 2) {
|
|
1524
|
+
const start = typeof loc === "object" ? positionToOffset(source, loc.line, loc.column) : loc;
|
|
1525
|
+
const end = start;
|
|
1526
|
+
const lines = source.split(lineSplitRE);
|
|
1527
|
+
const nl = /\r\n/.test(source) ? 2 : 1;
|
|
1528
|
+
let count = 0;
|
|
1529
|
+
let res = [];
|
|
1530
|
+
const columns = process.stdout?.columns || 80;
|
|
1531
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1532
|
+
count += lines[i].length + nl;
|
|
1533
|
+
if (count >= start) {
|
|
1534
|
+
for (let j = i - range; j <= i + range || end > count; j++) {
|
|
1535
|
+
if (j < 0 || j >= lines.length) continue;
|
|
1536
|
+
const lineLength = lines[j].length;
|
|
1537
|
+
// too long, maybe it's a minified file, skip for codeframe
|
|
1538
|
+
if (stripVTControlCharacters(lines[j]).length > 200) return "";
|
|
1539
|
+
res.push(lineNo(j + 1) + truncateString(lines[j].replace(/\t/g, " "), columns - 5 - indent));
|
|
1540
|
+
if (j === i) {
|
|
1541
|
+
// push underline
|
|
1542
|
+
const pad = start - (count - lineLength) + (nl - 1);
|
|
1543
|
+
const length = Math.max(1, end > count ? lineLength - pad : end - start);
|
|
1544
|
+
res.push(lineNo() + " ".repeat(pad) + c.red("^".repeat(length)));
|
|
1545
|
+
} else if (j > i) {
|
|
1546
|
+
if (end > count) {
|
|
1547
|
+
const length = Math.max(1, Math.min(end - count, lineLength));
|
|
1548
|
+
res.push(lineNo() + c.red("^".repeat(length)));
|
|
1549
|
+
}
|
|
1550
|
+
count += lineLength + 1;
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
break;
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
if (indent) res = res.map((line) => " ".repeat(indent) + line);
|
|
1557
|
+
return res.join("\n");
|
|
1558
|
+
}
|
|
1559
|
+
function lineNo(no = "") {
|
|
1560
|
+
return c.gray(`${String(no).padStart(3, " ")}| `);
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
class GithubActionsReporter {
|
|
1564
|
+
ctx = void 0;
|
|
1565
|
+
options;
|
|
1566
|
+
constructor(options = {}) {
|
|
1567
|
+
this.options = options;
|
|
1568
|
+
}
|
|
1569
|
+
onInit(ctx) {
|
|
1570
|
+
this.ctx = ctx;
|
|
1571
|
+
}
|
|
1572
|
+
onTestCaseAnnotate(testCase, annotation) {
|
|
1573
|
+
if (!annotation.location) return;
|
|
1574
|
+
const type = getTitle(annotation.type);
|
|
1575
|
+
const formatted = formatMessage({
|
|
1576
|
+
command: getType(annotation.type),
|
|
1577
|
+
properties: {
|
|
1578
|
+
file: annotation.location.file,
|
|
1579
|
+
line: String(annotation.location.line),
|
|
1580
|
+
column: String(annotation.location.column),
|
|
1581
|
+
...type && { title: type }
|
|
1582
|
+
},
|
|
1583
|
+
message: stripVTControlCharacters(annotation.message)
|
|
1584
|
+
});
|
|
1585
|
+
this.ctx.logger.log(`\n${formatted}`);
|
|
1586
|
+
}
|
|
1587
|
+
onFinished(files = [], errors = []) {
|
|
1588
|
+
// collect all errors and associate them with projects
|
|
1589
|
+
const projectErrors = new Array();
|
|
1590
|
+
for (const error of errors) projectErrors.push({
|
|
1591
|
+
project: this.ctx.getRootProject(),
|
|
1592
|
+
title: "Unhandled error",
|
|
1593
|
+
error
|
|
1594
|
+
});
|
|
1595
|
+
for (const file of files) {
|
|
1596
|
+
const tasks = getTasks(file);
|
|
1597
|
+
const project = this.ctx.getProjectByName(file.projectName || "");
|
|
1598
|
+
for (const task of tasks) {
|
|
1599
|
+
if (task.result?.state !== "fail") continue;
|
|
1600
|
+
const title = getFullName(task, " > ");
|
|
1601
|
+
for (const error of task.result?.errors ?? []) projectErrors.push({
|
|
1602
|
+
project,
|
|
1603
|
+
title,
|
|
1604
|
+
error,
|
|
1605
|
+
file
|
|
1606
|
+
});
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
const onWritePath = this.options.onWritePath ?? defaultOnWritePath;
|
|
1610
|
+
// format errors via `printError`
|
|
1611
|
+
for (const { project, title, error, file } of projectErrors) {
|
|
1612
|
+
const result = capturePrintError(error, this.ctx, {
|
|
1613
|
+
project,
|
|
1614
|
+
task: file
|
|
1615
|
+
});
|
|
1616
|
+
const stack = result?.nearest;
|
|
1617
|
+
if (!stack) continue;
|
|
1618
|
+
const formatted = formatMessage({
|
|
1619
|
+
command: "error",
|
|
1620
|
+
properties: {
|
|
1621
|
+
file: onWritePath(stack.file),
|
|
1622
|
+
title,
|
|
1623
|
+
line: String(stack.line),
|
|
1624
|
+
column: String(stack.column)
|
|
1625
|
+
},
|
|
1626
|
+
message: stripVTControlCharacters(result.output)
|
|
1627
|
+
});
|
|
1628
|
+
this.ctx.logger.log(`\n${formatted}`);
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
const BUILT_IN_TYPES = [
|
|
1633
|
+
"notice",
|
|
1634
|
+
"error",
|
|
1635
|
+
"warning"
|
|
1636
|
+
];
|
|
1637
|
+
function getTitle(type) {
|
|
1638
|
+
if (BUILT_IN_TYPES.includes(type)) return void 0;
|
|
1639
|
+
return type;
|
|
1640
|
+
}
|
|
1641
|
+
function getType(type) {
|
|
1642
|
+
if (BUILT_IN_TYPES.includes(type)) return type;
|
|
1643
|
+
return "notice";
|
|
1644
|
+
}
|
|
1645
|
+
function defaultOnWritePath(path) {
|
|
1646
|
+
return path;
|
|
1647
|
+
}
|
|
1648
|
+
// workflow command formatting based on
|
|
1649
|
+
// https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message
|
|
1650
|
+
// https://github.com/actions/toolkit/blob/f1d9b4b985e6f0f728b4b766db73498403fd5ca3/packages/core/src/command.ts#L80-L85
|
|
1651
|
+
function formatMessage({ command, properties, message }) {
|
|
1652
|
+
let result = `::${command}`;
|
|
1653
|
+
Object.entries(properties).forEach(([k, v], i) => {
|
|
1654
|
+
result += i === 0 ? " " : ",";
|
|
1655
|
+
result += `${k}=${escapeProperty(v)}`;
|
|
1656
|
+
});
|
|
1657
|
+
result += `::${escapeData(message)}`;
|
|
1658
|
+
return result;
|
|
1659
|
+
}
|
|
1660
|
+
function escapeData(s) {
|
|
1661
|
+
return s.replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A");
|
|
1662
|
+
}
|
|
1663
|
+
function escapeProperty(s) {
|
|
1664
|
+
return s.replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A").replace(/:/g, "%3A").replace(/,/g, "%2C");
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
class HangingProcessReporter {
|
|
1668
|
+
whyRunning;
|
|
1669
|
+
onInit() {
|
|
1670
|
+
const _require = createRequire(import.meta.url);
|
|
1671
|
+
this.whyRunning = _require("why-is-node-running");
|
|
1672
|
+
}
|
|
1673
|
+
onProcessTimeout() {
|
|
1674
|
+
this.whyRunning?.();
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
const StatusMap = {
|
|
1679
|
+
fail: "failed",
|
|
1680
|
+
only: "pending",
|
|
1681
|
+
pass: "passed",
|
|
1682
|
+
run: "pending",
|
|
1683
|
+
skip: "skipped",
|
|
1684
|
+
todo: "todo",
|
|
1685
|
+
queued: "pending"
|
|
1686
|
+
};
|
|
1687
|
+
class JsonReporter {
|
|
1688
|
+
start = 0;
|
|
1689
|
+
ctx;
|
|
1690
|
+
options;
|
|
1691
|
+
constructor(options) {
|
|
1692
|
+
this.options = options;
|
|
1693
|
+
}
|
|
1694
|
+
onInit(ctx) {
|
|
1695
|
+
this.ctx = ctx;
|
|
1696
|
+
this.start = Date.now();
|
|
1697
|
+
}
|
|
1698
|
+
async logTasks(files, coverageMap) {
|
|
1699
|
+
const suites = getSuites(files);
|
|
1700
|
+
const numTotalTestSuites = suites.length;
|
|
1701
|
+
const tests = getTests(files);
|
|
1702
|
+
const numTotalTests = tests.length;
|
|
1703
|
+
const numFailedTestSuites = suites.filter((s) => s.result?.state === "fail").length;
|
|
1704
|
+
const numPendingTestSuites = suites.filter((s) => s.result?.state === "run" || s.result?.state === "queued" || s.mode === "todo").length;
|
|
1705
|
+
const numPassedTestSuites = numTotalTestSuites - numFailedTestSuites - numPendingTestSuites;
|
|
1706
|
+
const numFailedTests = tests.filter((t) => t.result?.state === "fail").length;
|
|
1707
|
+
const numPassedTests = tests.filter((t) => t.result?.state === "pass").length;
|
|
1708
|
+
const numPendingTests = tests.filter((t) => t.result?.state === "run" || t.result?.state === "queued" || t.mode === "skip" || t.result?.state === "skip").length;
|
|
1709
|
+
const numTodoTests = tests.filter((t) => t.mode === "todo").length;
|
|
1710
|
+
const testResults = [];
|
|
1711
|
+
const success = !!(files.length > 0 || this.ctx.config.passWithNoTests) && numFailedTestSuites === 0 && numFailedTests === 0;
|
|
1712
|
+
for (const file of files) {
|
|
1713
|
+
const tests = getTests([file]);
|
|
1714
|
+
let startTime = tests.reduce((prev, next) => Math.min(prev, next.result?.startTime ?? Number.POSITIVE_INFINITY), Number.POSITIVE_INFINITY);
|
|
1715
|
+
if (startTime === Number.POSITIVE_INFINITY) startTime = this.start;
|
|
1716
|
+
const endTime = tests.reduce((prev, next) => Math.max(prev, (next.result?.startTime ?? 0) + (next.result?.duration ?? 0)), startTime);
|
|
1717
|
+
const assertionResults = tests.map((t) => {
|
|
1718
|
+
const ancestorTitles = [];
|
|
1719
|
+
let iter = t.suite;
|
|
1720
|
+
while (iter) {
|
|
1721
|
+
ancestorTitles.push(iter.name);
|
|
1722
|
+
iter = iter.suite;
|
|
1723
|
+
}
|
|
1724
|
+
ancestorTitles.reverse();
|
|
1725
|
+
return {
|
|
1726
|
+
ancestorTitles,
|
|
1727
|
+
fullName: t.name ? [...ancestorTitles, t.name].join(" ") : ancestorTitles.join(" "),
|
|
1728
|
+
status: StatusMap[t.result?.state || t.mode] || "skipped",
|
|
1729
|
+
title: t.name,
|
|
1730
|
+
duration: t.result?.duration,
|
|
1731
|
+
failureMessages: t.result?.errors?.map((e) => e.stack || e.message) || [],
|
|
1732
|
+
location: t.location,
|
|
1733
|
+
meta: t.meta
|
|
1734
|
+
};
|
|
1735
|
+
});
|
|
1736
|
+
if (tests.some((t) => t.result?.state === "run" || t.result?.state === "queued")) this.ctx.logger.warn("WARNING: Some tests are still running when generating the JSON report.This is likely an internal bug in Vitest.Please report it to https://github.com/vitest-dev/vitest/issues");
|
|
1737
|
+
const hasFailedTests = tests.some((t) => t.result?.state === "fail");
|
|
1738
|
+
testResults.push({
|
|
1739
|
+
assertionResults,
|
|
1740
|
+
startTime,
|
|
1741
|
+
endTime,
|
|
1742
|
+
status: file.result?.state === "fail" || hasFailedTests ? "failed" : "passed",
|
|
1743
|
+
message: file.result?.errors?.[0]?.message ?? "",
|
|
1744
|
+
name: file.filepath
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
const result = {
|
|
1748
|
+
numTotalTestSuites,
|
|
1749
|
+
numPassedTestSuites,
|
|
1750
|
+
numFailedTestSuites,
|
|
1751
|
+
numPendingTestSuites,
|
|
1752
|
+
numTotalTests,
|
|
1753
|
+
numPassedTests,
|
|
1754
|
+
numFailedTests,
|
|
1755
|
+
numPendingTests,
|
|
1756
|
+
numTodoTests,
|
|
1757
|
+
snapshot: this.ctx.snapshot.summary,
|
|
1758
|
+
startTime: this.start,
|
|
1759
|
+
success,
|
|
1760
|
+
testResults,
|
|
1761
|
+
coverageMap
|
|
1762
|
+
};
|
|
1763
|
+
await this.writeReport(JSON.stringify(result));
|
|
1764
|
+
}
|
|
1765
|
+
async onFinished(files = this.ctx.state.getFiles(), _errors = [], coverageMap) {
|
|
1766
|
+
await this.logTasks(files, coverageMap);
|
|
1767
|
+
}
|
|
1768
|
+
/**
|
|
1769
|
+
* Writes the report to an output file if specified in the config,
|
|
1770
|
+
* or logs it to the console otherwise.
|
|
1771
|
+
* @param report
|
|
1772
|
+
*/
|
|
1773
|
+
async writeReport(report) {
|
|
1774
|
+
const outputFile = this.options.outputFile ?? getOutputFile(this.ctx.config, "json");
|
|
1775
|
+
if (outputFile) {
|
|
1776
|
+
const reportFile = resolve(this.ctx.config.root, outputFile);
|
|
1777
|
+
const outputDirectory = dirname(reportFile);
|
|
1778
|
+
if (!existsSync(outputDirectory)) await promises.mkdir(outputDirectory, { recursive: true });
|
|
1779
|
+
await promises.writeFile(reportFile, report, "utf-8");
|
|
1780
|
+
this.ctx.logger.log(`JSON report written to ${reportFile}`);
|
|
1781
|
+
} else this.ctx.logger.log(report);
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1785
|
+
class IndentedLogger {
|
|
1786
|
+
currentIndent = "";
|
|
1787
|
+
constructor(baseLog) {
|
|
1788
|
+
this.baseLog = baseLog;
|
|
1789
|
+
}
|
|
1790
|
+
indent() {
|
|
1791
|
+
this.currentIndent += " ";
|
|
1792
|
+
}
|
|
1793
|
+
unindent() {
|
|
1794
|
+
this.currentIndent = this.currentIndent.substring(0, this.currentIndent.length - 4);
|
|
1795
|
+
}
|
|
1796
|
+
log(text) {
|
|
1797
|
+
return this.baseLog(this.currentIndent + text);
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
function flattenTasks$1(task, baseName = "") {
|
|
1802
|
+
const base = baseName ? `${baseName} > ` : "";
|
|
1803
|
+
if (task.type === "suite") return task.tasks.flatMap((child) => flattenTasks$1(child, `${base}${task.name}`));
|
|
1804
|
+
else return [{
|
|
1805
|
+
...task,
|
|
1806
|
+
name: `${base}${task.name}`
|
|
1807
|
+
}];
|
|
1808
|
+
}
|
|
1809
|
+
// https://gist.github.com/john-doherty/b9195065884cdbfd2017a4756e6409cc
|
|
1810
|
+
function removeInvalidXMLCharacters(value, removeDiscouragedChars) {
|
|
1811
|
+
let regex = /([\0-\x08\v\f\x0E-\x1F\uFFFD\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/g;
|
|
1812
|
+
value = String(value || "").replace(regex, "");
|
|
1813
|
+
{
|
|
1814
|
+
// remove everything discouraged by XML 1.0 specifications
|
|
1815
|
+
regex = new RegExp(
|
|
1816
|
+
/* eslint-disable regexp/prefer-character-class, regexp/no-obscure-range, regexp/no-useless-non-capturing-group */
|
|
1817
|
+
"([\\x7F-\\x84]|[\\x86-\\x9F]|[\\uFDD0-\\uFDEF]|\\uD83F[\\uDFFE\\uDFFF]|(?:\\uD87F[\\uDFFE\\uDFFF])|\\uD8BF[\\uDFFE\\uDFFF]|\\uD8FF[\\uDFFE\\uDFFF]|(?:\\uD93F[\\uDFFE\\uDFFF])|\\uD97F[\\uDFFE\\uDFFF]|\\uD9BF[\\uDFFE\\uDFFF]|\\uD9FF[\\uDFFE\\uDFFF]|\\uDA3F[\\uDFFE\\uDFFF]|\\uDA7F[\\uDFFE\\uDFFF]|\\uDABF[\\uDFFE\\uDFFF]|(?:\\uDAFF[\\uDFFE\\uDFFF])|\\uDB3F[\\uDFFE\\uDFFF]|\\uDB7F[\\uDFFE\\uDFFF]|(?:\\uDBBF[\\uDFFE\\uDFFF])|\\uDBFF[\\uDFFE\\uDFFF](?:[\\0-\\t\\v\\f\\x0E-\\u2027\\u202A-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]))",
|
|
1818
|
+
"g"
|
|
1819
|
+
/* eslint-enable */
|
|
1820
|
+
);
|
|
1821
|
+
value = value.replace(regex, "");
|
|
1822
|
+
}
|
|
1823
|
+
return value;
|
|
1824
|
+
}
|
|
1825
|
+
function escapeXML(value) {
|
|
1826
|
+
return removeInvalidXMLCharacters(String(value).replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">"));
|
|
1827
|
+
}
|
|
1828
|
+
function executionTime(durationMS) {
|
|
1829
|
+
return (durationMS / 1e3).toLocaleString("en-US", {
|
|
1830
|
+
useGrouping: false,
|
|
1831
|
+
maximumFractionDigits: 10
|
|
1832
|
+
});
|
|
1833
|
+
}
|
|
1834
|
+
function getDuration(task) {
|
|
1835
|
+
const duration = task.result?.duration ?? 0;
|
|
1836
|
+
return executionTime(duration);
|
|
1837
|
+
}
|
|
1838
|
+
class JUnitReporter {
|
|
1839
|
+
ctx;
|
|
1840
|
+
reportFile;
|
|
1841
|
+
baseLog;
|
|
1842
|
+
logger;
|
|
1843
|
+
_timeStart = /* @__PURE__ */ new Date();
|
|
1844
|
+
fileFd;
|
|
1845
|
+
options;
|
|
1846
|
+
constructor(options) {
|
|
1847
|
+
this.options = { ...options };
|
|
1848
|
+
this.options.includeConsoleOutput ??= true;
|
|
1849
|
+
}
|
|
1850
|
+
async onInit(ctx) {
|
|
1851
|
+
this.ctx = ctx;
|
|
1852
|
+
const outputFile = this.options.outputFile ?? getOutputFile(this.ctx.config, "junit");
|
|
1853
|
+
if (outputFile) {
|
|
1854
|
+
this.reportFile = resolve(this.ctx.config.root, outputFile);
|
|
1855
|
+
const outputDirectory = dirname(this.reportFile);
|
|
1856
|
+
if (!existsSync(outputDirectory)) await promises.mkdir(outputDirectory, { recursive: true });
|
|
1857
|
+
const fileFd = await promises.open(this.reportFile, "w+");
|
|
1858
|
+
this.fileFd = fileFd;
|
|
1859
|
+
this.baseLog = async (text) => {
|
|
1860
|
+
if (!this.fileFd) this.fileFd = await promises.open(this.reportFile, "w+");
|
|
1861
|
+
await promises.writeFile(this.fileFd, `${text}\n`);
|
|
1862
|
+
};
|
|
1863
|
+
} else this.baseLog = async (text) => this.ctx.logger.log(text);
|
|
1864
|
+
this._timeStart = /* @__PURE__ */ new Date();
|
|
1865
|
+
this.logger = new IndentedLogger(this.baseLog);
|
|
1866
|
+
}
|
|
1867
|
+
async writeElement(name, attrs, children) {
|
|
1868
|
+
const pairs = [];
|
|
1869
|
+
for (const key in attrs) {
|
|
1870
|
+
const attr = attrs[key];
|
|
1871
|
+
if (attr === void 0) continue;
|
|
1872
|
+
pairs.push(`${key}="${escapeXML(attr)}"`);
|
|
1873
|
+
}
|
|
1874
|
+
await this.logger.log(`<${name}${pairs.length ? ` ${pairs.join(" ")}` : ""}>`);
|
|
1875
|
+
this.logger.indent();
|
|
1876
|
+
await children.call(this);
|
|
1877
|
+
this.logger.unindent();
|
|
1878
|
+
await this.logger.log(`</${name}>`);
|
|
1879
|
+
}
|
|
1880
|
+
async writeLogs(task, type) {
|
|
1881
|
+
if (task.logs == null || task.logs.length === 0) return;
|
|
1882
|
+
const logType = type === "err" ? "stderr" : "stdout";
|
|
1883
|
+
const logs = task.logs.filter((log) => log.type === logType);
|
|
1884
|
+
if (logs.length === 0) return;
|
|
1885
|
+
await this.writeElement(`system-${type}`, {}, async () => {
|
|
1886
|
+
for (const log of logs) await this.baseLog(escapeXML(log.content));
|
|
1887
|
+
});
|
|
1888
|
+
}
|
|
1889
|
+
async writeTasks(tasks, filename) {
|
|
1890
|
+
for (const task of tasks) {
|
|
1891
|
+
let classname = filename;
|
|
1892
|
+
const templateVars = {
|
|
1893
|
+
filename: task.file.name,
|
|
1894
|
+
filepath: task.file.filepath
|
|
1895
|
+
};
|
|
1896
|
+
if (typeof this.options.classnameTemplate === "function") classname = this.options.classnameTemplate(templateVars);
|
|
1897
|
+
else if (typeof this.options.classnameTemplate === "string") classname = this.options.classnameTemplate.replace(/\{filename\}/g, templateVars.filename).replace(/\{filepath\}/g, templateVars.filepath);
|
|
1898
|
+
else if (typeof this.options.classname === "string") classname = this.options.classname;
|
|
1899
|
+
await this.writeElement("testcase", {
|
|
1900
|
+
classname,
|
|
1901
|
+
file: this.options.addFileAttribute ? filename : void 0,
|
|
1902
|
+
name: task.name,
|
|
1903
|
+
time: getDuration(task)
|
|
1904
|
+
}, async () => {
|
|
1905
|
+
if (this.options.includeConsoleOutput) {
|
|
1906
|
+
await this.writeLogs(task, "out");
|
|
1907
|
+
await this.writeLogs(task, "err");
|
|
1908
|
+
}
|
|
1909
|
+
if (task.mode === "skip" || task.mode === "todo") await this.logger.log("<skipped/>");
|
|
1910
|
+
if (task.type === "test" && task.annotations.length) {
|
|
1911
|
+
await this.logger.log("<properties>");
|
|
1912
|
+
this.logger.indent();
|
|
1913
|
+
for (const annotation of task.annotations) {
|
|
1914
|
+
await this.logger.log(`<property name="${escapeXML(annotation.type)}" value="${escapeXML(annotation.message)}">`);
|
|
1915
|
+
await this.logger.log("</property>");
|
|
1916
|
+
}
|
|
1917
|
+
this.logger.unindent();
|
|
1918
|
+
await this.logger.log("</properties>");
|
|
1919
|
+
}
|
|
1920
|
+
if (task.result?.state === "fail") {
|
|
1921
|
+
const errors = task.result.errors || [];
|
|
1922
|
+
for (const error of errors) await this.writeElement("failure", {
|
|
1923
|
+
message: error?.message,
|
|
1924
|
+
type: error?.name
|
|
1925
|
+
}, async () => {
|
|
1926
|
+
if (!error) return;
|
|
1927
|
+
const result = capturePrintError(error, this.ctx, {
|
|
1928
|
+
project: this.ctx.getProjectByName(task.file.projectName || ""),
|
|
1929
|
+
task
|
|
1930
|
+
});
|
|
1931
|
+
await this.baseLog(escapeXML(stripVTControlCharacters(result.output.trim())));
|
|
1932
|
+
});
|
|
1933
|
+
}
|
|
1934
|
+
});
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
async onFinished(files = this.ctx.state.getFiles()) {
|
|
1938
|
+
await this.logger.log("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
|
|
1939
|
+
const transformed = files.map((file) => {
|
|
1940
|
+
const tasks = file.tasks.flatMap((task) => flattenTasks$1(task));
|
|
1941
|
+
const stats = tasks.reduce((stats, task) => {
|
|
1942
|
+
return {
|
|
1943
|
+
passed: stats.passed + Number(task.result?.state === "pass"),
|
|
1944
|
+
failures: stats.failures + Number(task.result?.state === "fail"),
|
|
1945
|
+
skipped: stats.skipped + Number(task.mode === "skip" || task.mode === "todo")
|
|
1946
|
+
};
|
|
1947
|
+
}, {
|
|
1948
|
+
passed: 0,
|
|
1949
|
+
failures: 0,
|
|
1950
|
+
skipped: 0
|
|
1951
|
+
});
|
|
1952
|
+
// inject failed suites to surface errors during beforeAll/afterAll
|
|
1953
|
+
const suites = getSuites(file);
|
|
1954
|
+
for (const suite of suites) if (suite.result?.errors) {
|
|
1955
|
+
tasks.push(suite);
|
|
1956
|
+
stats.failures += 1;
|
|
1957
|
+
}
|
|
1958
|
+
// If there are no tests, but the file failed to load, we still want to report it as a failure
|
|
1959
|
+
if (tasks.length === 0 && file.result?.state === "fail") {
|
|
1960
|
+
stats.failures = 1;
|
|
1961
|
+
tasks.push({
|
|
1962
|
+
id: file.id,
|
|
1963
|
+
type: "test",
|
|
1964
|
+
name: file.name,
|
|
1965
|
+
mode: "run",
|
|
1966
|
+
result: file.result,
|
|
1967
|
+
meta: {},
|
|
1968
|
+
timeout: 0,
|
|
1969
|
+
context: null,
|
|
1970
|
+
suite: null,
|
|
1971
|
+
file: null,
|
|
1972
|
+
annotations: []
|
|
1973
|
+
});
|
|
1974
|
+
}
|
|
1975
|
+
return {
|
|
1976
|
+
...file,
|
|
1977
|
+
tasks,
|
|
1978
|
+
stats
|
|
1979
|
+
};
|
|
1980
|
+
});
|
|
1981
|
+
const stats = transformed.reduce((stats, file) => {
|
|
1982
|
+
stats.tests += file.tasks.length;
|
|
1983
|
+
stats.failures += file.stats.failures;
|
|
1984
|
+
stats.time += file.result?.duration || 0;
|
|
1985
|
+
return stats;
|
|
1986
|
+
}, {
|
|
1987
|
+
name: this.options.suiteName || "vitest tests",
|
|
1988
|
+
tests: 0,
|
|
1989
|
+
failures: 0,
|
|
1990
|
+
errors: 0,
|
|
1991
|
+
time: 0
|
|
1992
|
+
});
|
|
1993
|
+
await this.writeElement("testsuites", {
|
|
1994
|
+
...stats,
|
|
1995
|
+
time: executionTime(stats.time)
|
|
1996
|
+
}, async () => {
|
|
1997
|
+
for (const file of transformed) {
|
|
1998
|
+
const filename = relative(this.ctx.config.root, file.filepath);
|
|
1999
|
+
await this.writeElement("testsuite", {
|
|
2000
|
+
name: filename,
|
|
2001
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2002
|
+
hostname: hostname(),
|
|
2003
|
+
tests: file.tasks.length,
|
|
2004
|
+
failures: file.stats.failures,
|
|
2005
|
+
errors: 0,
|
|
2006
|
+
skipped: file.stats.skipped,
|
|
2007
|
+
time: getDuration(file)
|
|
2008
|
+
}, async () => {
|
|
2009
|
+
await this.writeTasks(file.tasks, filename);
|
|
2010
|
+
});
|
|
2011
|
+
}
|
|
2012
|
+
});
|
|
2013
|
+
if (this.reportFile) this.ctx.logger.log(`JUNIT report written to ${this.reportFile}`);
|
|
2014
|
+
await this.fileFd?.close();
|
|
2015
|
+
this.fileFd = void 0;
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
function yamlString(str) {
|
|
2020
|
+
return `"${str.replace(/"/g, "\\\"")}"`;
|
|
2021
|
+
}
|
|
2022
|
+
function tapString(str) {
|
|
2023
|
+
return str.replace(/\\/g, "\\\\").replace(/#/g, "\\#").replace(/\n/g, " ");
|
|
2024
|
+
}
|
|
2025
|
+
class TapReporter {
|
|
2026
|
+
ctx;
|
|
2027
|
+
logger;
|
|
2028
|
+
onInit(ctx) {
|
|
2029
|
+
this.ctx = ctx;
|
|
2030
|
+
this.logger = new IndentedLogger(ctx.logger.log.bind(ctx.logger));
|
|
2031
|
+
}
|
|
2032
|
+
static getComment(task) {
|
|
2033
|
+
if (task.mode === "skip") return " # SKIP";
|
|
2034
|
+
else if (task.mode === "todo") return " # TODO";
|
|
2035
|
+
else if (task.result?.duration != null) return ` # time=${task.result.duration.toFixed(2)}ms`;
|
|
2036
|
+
else return "";
|
|
2037
|
+
}
|
|
2038
|
+
logErrorDetails(error, stack) {
|
|
2039
|
+
const errorName = error.name || "Unknown Error";
|
|
2040
|
+
this.logger.log(`name: ${yamlString(String(errorName))}`);
|
|
2041
|
+
this.logger.log(`message: ${yamlString(String(error.message))}`);
|
|
2042
|
+
if (stack)
|
|
2043
|
+
// For compatibility with tap-mocha-reporter
|
|
2044
|
+
this.logger.log(`stack: ${yamlString(`${stack.file}:${stack.line}:${stack.column}`)}`);
|
|
2045
|
+
}
|
|
2046
|
+
logTasks(tasks) {
|
|
2047
|
+
this.logger.log(`1..${tasks.length}`);
|
|
2048
|
+
for (const [i, task] of tasks.entries()) {
|
|
2049
|
+
const id = i + 1;
|
|
2050
|
+
const ok = task.result?.state === "pass" || task.mode === "skip" || task.mode === "todo" ? "ok" : "not ok";
|
|
2051
|
+
const comment = TapReporter.getComment(task);
|
|
2052
|
+
if (task.type === "suite" && task.tasks.length > 0) {
|
|
2053
|
+
this.logger.log(`${ok} ${id} - ${tapString(task.name)}${comment} {`);
|
|
2054
|
+
this.logger.indent();
|
|
2055
|
+
this.logTasks(task.tasks);
|
|
2056
|
+
this.logger.unindent();
|
|
2057
|
+
this.logger.log("}");
|
|
2058
|
+
} else {
|
|
2059
|
+
this.logger.log(`${ok} ${id} - ${tapString(task.name)}${comment}`);
|
|
2060
|
+
const project = this.ctx.getProjectByName(task.file.projectName || "");
|
|
2061
|
+
if (task.type === "test" && task.annotations) {
|
|
2062
|
+
this.logger.indent();
|
|
2063
|
+
task.annotations.forEach(({ type, message }) => {
|
|
2064
|
+
this.logger.log(`# ${type}: ${message}`);
|
|
2065
|
+
});
|
|
2066
|
+
this.logger.unindent();
|
|
2067
|
+
}
|
|
2068
|
+
if (task.result?.state === "fail" && task.result.errors) {
|
|
2069
|
+
this.logger.indent();
|
|
2070
|
+
task.result.errors.forEach((error) => {
|
|
2071
|
+
const stacks = task.file.pool === "browser" ? project.browser?.parseErrorStacktrace(error) || [] : parseErrorStacktrace(error, { frameFilter: this.ctx.config.onStackTrace });
|
|
2072
|
+
const stack = stacks[0];
|
|
2073
|
+
this.logger.log("---");
|
|
2074
|
+
this.logger.log("error:");
|
|
2075
|
+
this.logger.indent();
|
|
2076
|
+
this.logErrorDetails(error);
|
|
2077
|
+
this.logger.unindent();
|
|
2078
|
+
if (stack) this.logger.log(`at: ${yamlString(`${stack.file}:${stack.line}:${stack.column}`)}`);
|
|
2079
|
+
if (error.showDiff) {
|
|
2080
|
+
this.logger.log(`actual: ${yamlString(error.actual)}`);
|
|
2081
|
+
this.logger.log(`expected: ${yamlString(error.expected)}`);
|
|
2082
|
+
}
|
|
2083
|
+
});
|
|
2084
|
+
this.logger.log("...");
|
|
2085
|
+
this.logger.unindent();
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
onFinished(files = this.ctx.state.getFiles()) {
|
|
2091
|
+
this.logger.log("TAP version 13");
|
|
2092
|
+
this.logTasks(files);
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
function flattenTasks(task, baseName = "") {
|
|
2097
|
+
const base = baseName ? `${baseName} > ` : "";
|
|
2098
|
+
if (task.type === "suite" && task.tasks.length > 0) return task.tasks.flatMap((child) => flattenTasks(child, `${base}${task.name}`));
|
|
2099
|
+
else return [{
|
|
2100
|
+
...task,
|
|
2101
|
+
name: `${base}${task.name}`
|
|
2102
|
+
}];
|
|
2103
|
+
}
|
|
2104
|
+
class TapFlatReporter extends TapReporter {
|
|
2105
|
+
onInit(ctx) {
|
|
2106
|
+
super.onInit(ctx);
|
|
2107
|
+
}
|
|
2108
|
+
onFinished(files = this.ctx.state.getFiles()) {
|
|
2109
|
+
this.ctx.logger.log("TAP version 13");
|
|
2110
|
+
const flatTasks = files.flatMap((task) => flattenTasks(task));
|
|
2111
|
+
this.logTasks(flatTasks);
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
class VerboseReporter extends DefaultReporter {
|
|
2116
|
+
verbose = true;
|
|
2117
|
+
renderSucceed = true;
|
|
2118
|
+
printTestModule(module) {
|
|
2119
|
+
// still print the test module in TTY,
|
|
2120
|
+
// but don't print it in the CLI because we
|
|
2121
|
+
// print all the tests when they finish
|
|
2122
|
+
// instead of printing them when the test file finishes
|
|
2123
|
+
if (this.isTTY) return super.printTestModule(module);
|
|
2124
|
+
}
|
|
2125
|
+
onTestCaseResult(test) {
|
|
2126
|
+
super.onTestCaseResult(test);
|
|
2127
|
+
// don't print tests in TTY as they go, only print them
|
|
2128
|
+
// in the CLI when they finish
|
|
2129
|
+
if (this.isTTY) return;
|
|
2130
|
+
const testResult = test.result();
|
|
2131
|
+
if (this.ctx.config.hideSkippedTests && testResult.state === "skipped") return;
|
|
2132
|
+
let title = ` ${getStateSymbol(test.task)} `;
|
|
2133
|
+
if (test.project.name) title += formatProjectName(test.project);
|
|
2134
|
+
title += getFullName(test.task, c.dim(" > "));
|
|
2135
|
+
title += this.getDurationPrefix(test.task);
|
|
2136
|
+
const diagnostic = test.diagnostic();
|
|
2137
|
+
if (diagnostic?.heap != null) title += c.magenta(` ${Math.floor(diagnostic.heap / 1024 / 1024)} MB heap used`);
|
|
2138
|
+
if (testResult.state === "skipped" && testResult.note) title += c.dim(c.gray(` [${testResult.note}]`));
|
|
2139
|
+
this.log(title);
|
|
2140
|
+
if (testResult.state === "failed") testResult.errors.forEach((error) => this.log(c.red(` ${F_RIGHT} ${error?.message}`)));
|
|
2141
|
+
if (test.annotations().length) {
|
|
2142
|
+
this.log();
|
|
2143
|
+
this.printAnnotations(test, "log", 3);
|
|
2144
|
+
this.log();
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
printTestSuite(testSuite) {
|
|
2148
|
+
const indentation = " ".repeat(getIndentation(testSuite.task));
|
|
2149
|
+
const tests = Array.from(testSuite.children.allTests());
|
|
2150
|
+
const state = getStateSymbol(testSuite.task);
|
|
2151
|
+
this.log(` ${indentation}${state} ${testSuite.name} ${c.dim(`(${tests.length})`)}`);
|
|
2152
|
+
}
|
|
2153
|
+
getTestName(test) {
|
|
2154
|
+
return test.name;
|
|
2155
|
+
}
|
|
2156
|
+
getTestIndentation(test) {
|
|
2157
|
+
return " ".repeat(getIndentation(test));
|
|
2158
|
+
}
|
|
2159
|
+
formatShortError() {
|
|
2160
|
+
// Short errors are not shown in tree-view
|
|
2161
|
+
return "";
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
function getIndentation(suite, level = 1) {
|
|
2165
|
+
if (suite.suite && !("filepath" in suite.suite)) return getIndentation(suite.suite, level + 1);
|
|
2166
|
+
return level;
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
const ReportersMap = {
|
|
2170
|
+
"default": DefaultReporter,
|
|
2171
|
+
"basic": BasicReporter,
|
|
2172
|
+
"blob": BlobReporter,
|
|
2173
|
+
"verbose": VerboseReporter,
|
|
2174
|
+
"dot": DotReporter,
|
|
2175
|
+
"json": JsonReporter,
|
|
2176
|
+
"tap": TapReporter,
|
|
2177
|
+
"tap-flat": TapFlatReporter,
|
|
2178
|
+
"junit": JUnitReporter,
|
|
2179
|
+
"hanging-process": HangingProcessReporter,
|
|
2180
|
+
"github-actions": GithubActionsReporter
|
|
2181
|
+
};
|
|
2182
|
+
|
|
2183
|
+
export { BasicReporter as B, DefaultReporter as D, F_RIGHT as F, GithubActionsReporter as G, HangingProcessReporter as H, JsonReporter as J, ReportersMap as R, TapFlatReporter as T, VerboseReporter as V, DotReporter as a, JUnitReporter as b, TapReporter as c, printError as d, errorBanner as e, formatProjectName as f, getStateSymbol as g, divider as h, generateCodeFrame as i, BlobReporter as j, parse as p, readBlobs as r, stringify as s, truncateString as t, utils as u, withLabel as w };
|