From a6dd8aa42ad50e0488271e4805ddbb4d60eab4eb Mon Sep 17 00:00:00 2001 From: figmar Date: Sun, 11 Oct 2026 19:33:01 +0800 Subject: [PATCH] fix(test): add missing devDeps + sourcemap transform + jsdom directives MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WorkBuddy review found 38 of 131 spec files failed at collection time (0 tests executed) — the '1015 passed' was a false green because vitest only counts 'Tests failed', not 'Test Files failed'. Root cause: dsh-client-ui-primitives@0.2.0-rc.2 declares dependencies:null but statically imports 23 external root packages. Our project declared only 18. Under pnpm strict layout, the missing 5 (dsh-client-store, dsh-util-code-language, dsh-util-workspace-path, diff, simple-icons) were unresolvable when Vite inlined the primitives package. Fixes: - Add 7 missing devDeps: dsh-client-store@0.2.0-rc.2, dsh-util-code-language@0.2.0-rc.2, dsh-util-workspace-path@0.2.0-rc.2, diff@9.0.0, simple-icons@16.35.0, zustand@5.0.15, immer@11.1.21 - vitest.config.ts: add transform plugin to strip sourceMappingURL comments from dsh-client-ui-primitives (upstream ships lib/index.js with trailing sourceMappingURL but package.json files excludes .map) - 5 spec files: add @vitest-environment jsdom directive (they import dsh-client-ui-primitives which calls window.addEventListener at module load; node environment lacks window) - Remove empty .map file hack from node_modules (ineffective + .gitignore blocks it from version control) Result: Test Files 131 passed (131), Tests 1367 passed | 9 skipped, EXIT=0. Verified: simple-icons 25 named exports all present. Typecheck + build pass. --- package.json | 9 ++- pnpm-lock.yaml | 89 +++++++++++++++++++++++++++++ pnpm-workspace.yaml | 1 + tests/apes-tabs.spec.ts | 1 + tests/builtins.spec.ts | 1 + tests/markdown-copy-labels.spec.tsx | 1 + tests/markdown-frontmatter.spec.tsx | 1 + tests/sandbox-views.spec.tsx | 1 + vitest.config.ts | 14 +++++ 9 files changed, 117 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index de3db31..d8f688d 100644 --- a/package.json +++ b/package.json @@ -159,6 +159,7 @@ "@deepseek-ai/dsh-agent-loop": "0.2.0-rc.2", "@deepseek-ai/dsh-attachment": "0.2.0-rc.2", "@deepseek-ai/dsh-client-locale": "0.2.0-rc.2", + "@deepseek-ai/dsh-client-store": "0.2.0-rc.2", "@deepseek-ai/dsh-client-ui-conversation": "0.2.0-rc.2", "@deepseek-ai/dsh-client-ui-primitives": "0.2.0-rc.2", "@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.2", @@ -177,7 +178,9 @@ "@deepseek-ai/dsh-system-prompt": "0.2.0-rc.2", "@deepseek-ai/dsh-tools": "0.2.0-rc.2", "@deepseek-ai/dsh-user-approval": "0.2.0-rc.2", + "@deepseek-ai/dsh-util-code-language": "0.2.0-rc.2", "@deepseek-ai/dsh-util-time": "0.2.0-rc.2", + "@deepseek-ai/dsh-util-workspace-path": "0.2.0-rc.2", "@eslint/js": "^10.0.1", "@huanlin/dsh-plugin-better-locale": "^0.1.0", "@playwright/test": "^1.62.1", @@ -191,9 +194,11 @@ "@xterm/xterm": "^5.5.0", "anser": "^2.3.5", "cordis": "^4.0.0-rc.8", + "diff": "9.0.0", "eslint": "^10.9.1", "eslint-plugin-react-hooks": "^7.1.1", "globals": "^17.12.0", + "immer": "11.1.21", "jsdom": "^29.1.1", "katex": "^0.16.47", "lightningcss": "^1.32.0", @@ -212,11 +217,13 @@ "react": "^18.2.0", "react-dom": "18.2.0", "shiki": "^4.3.1", + "simple-icons": "16.35.0", "tsdown": "^0.22.2", "typescript": "^5.6.0", "typescript-eslint": "^8.69.0", "unrun": "^0.2.39", - "vitest": "^4.1.8" + "vitest": "^4.1.8", + "zustand": "5.0.15" }, "forkedFrom": { "name": "dsh-better-sidebar", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 18e2031..a4c9114 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -117,6 +117,9 @@ importers: '@deepseek-ai/dsh-client-locale': specifier: 0.2.0-rc.2 version: 0.2.0-rc.2(@deepseek-ai/cordis@4.0.4) + '@deepseek-ai/dsh-client-store': + specifier: 0.2.0-rc.2 + version: 0.2.0-rc.2(@deepseek-ai/cordis@4.0.4) '@deepseek-ai/dsh-client-ui-conversation': specifier: 0.2.0-rc.2 version: 0.2.0-rc.2(@deepseek-ai/cordis@4.0.4) @@ -171,9 +174,15 @@ importers: '@deepseek-ai/dsh-user-approval': specifier: 0.2.0-rc.2 version: 0.2.0-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-agent@0.2.0-rc.2(b872d4d836bb263e5b3a50782f98c977))(@deepseek-ai/dsh-brand@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-invariants@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4)))(@deepseek-ai/dsh-session@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-scope@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4))))(@deepseek-ai/dsh-system-prompt@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4)))) + '@deepseek-ai/dsh-util-code-language': + specifier: 0.2.0-rc.2 + version: 0.2.0-rc.2(@deepseek-ai/cordis@4.0.4) '@deepseek-ai/dsh-util-time': specifier: 0.2.0-rc.2 version: 0.2.0-rc.2(@deepseek-ai/cordis@4.0.4) + '@deepseek-ai/dsh-util-workspace-path': + specifier: 0.2.0-rc.2 + version: 0.2.0-rc.2(@deepseek-ai/cordis@4.0.4) '@eslint/js': specifier: ^10.0.1 version: 10.0.1(eslint@10.11.0) @@ -213,6 +222,9 @@ importers: cordis: specifier: ^4.0.0-rc.8 version: 4.0.0-rc.8(@cordisjs/plugin-loader@1.0.0-rc.5) + diff: + specifier: 9.0.0 + version: 9.0.0 eslint: specifier: ^10.9.1 version: 10.11.0 @@ -222,6 +234,9 @@ importers: globals: specifier: ^17.12.0 version: 17.13.0 + immer: + specifier: 11.1.21 + version: 11.1.21 jsdom: specifier: ^29.1.1 version: 29.1.1 @@ -276,6 +291,9 @@ importers: shiki: specifier: ^4.3.1 version: 4.4.3 + simple-icons: + specifier: 16.35.0 + version: 16.35.0 tsdown: specifier: ^0.22.2 version: 0.22.14(typescript@5.6.2)(unrun@0.2.39) @@ -291,6 +309,9 @@ importers: vitest: specifier: ^4.1.8 version: 4.1.11(@types/node@24.13.3)(jsdom@29.1.1)(vite@8.2.2(@types/node@24.13.3)(yaml@2.9.1)) + zustand: + specifier: 5.0.15 + version: 5.0.15(@types/react@18.3.31)(immer@11.1.21)(react@18.2.0) packages: @@ -613,6 +634,11 @@ packages: peerDependencies: '@deepseek-ai/cordis': ~4.0.4 + '@deepseek-ai/dsh-client-store@0.2.0-rc.2': + resolution: {integrity: sha512-unHIDNnHudDIj05W99m+dVPXLYy7qNvMJ/D5FWb7cov0CbiQvliqbvFeMAU6LzC+u3vTkVJgSMIAwAVdQgYHEA==} + peerDependencies: + '@deepseek-ai/cordis': ~4.0.4 + '@deepseek-ai/dsh-client-ui-conversation@0.2.0-rc.2': resolution: {integrity: sha512-Y1eWKVeh84cbB0fcV0MFOMUHBeptlzBCzsw6xslZS7p1a8l9PeFcjx5ZVTkKFuFMCfwEHWTeV9HcYqWLYH0bhw==} peerDependencies: @@ -838,6 +864,11 @@ packages: '@deepseek-ai/dsh-session': 0.2.0-rc.2 '@deepseek-ai/dsh-system-prompt': 0.2.0-rc.2 + '@deepseek-ai/dsh-util-code-language@0.2.0-rc.2': + resolution: {integrity: sha512-MYp8KlKWKgwxRfwwMbji4zweDZxVJ1smaneMAKjJvexDc9v+C40o1pJL5Ch/atny8a7O4aiBM1uSvC4bo7/S3g==} + peerDependencies: + '@deepseek-ai/cordis': ~4.0.4 + '@deepseek-ai/dsh-util-crypto@0.2.0-rc.2': resolution: {integrity: sha512-5OvvmepY69uXTagUMlnoHqg7euI4ZMifLgfdV8xZO20OslWGGiRCkJbZRyDtcJG9GsXWz9UimfWmUu52zKXJ5w==} peerDependencies: @@ -853,6 +884,11 @@ packages: peerDependencies: '@deepseek-ai/cordis': ~4.0.4 + '@deepseek-ai/dsh-util-workspace-path@0.2.0-rc.2': + resolution: {integrity: sha512-pjjpi+hN29dVf9HMitxo5gUAXKNdYcJ75vNVjKp2T6sdBy0wxcMKlfddu/bYx/xDL3teNBhh17EH7w1asYNNZQ==} + peerDependencies: + '@deepseek-ai/cordis': ~4.0.4 + '@deepseek-ai/schemastery@3.18.4': resolution: {integrity: sha512-SSXO6tYuyrIqKVbmOnIq0s+riUywYzouFMcnBluHF9n4KMo2G8HvEzhCYj6pj2617/glOjbJuVInJ9hfONsjkg==} @@ -2137,6 +2173,10 @@ packages: devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + diff@9.0.0: + resolution: {integrity: sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==} + engines: {node: '>=0.3.1'} + dompurify@3.4.14: resolution: {integrity: sha512-dVoH9z+MY+C9IilgGCk3YfFqjLi3fChm2OiKJMzh6axrJ5qwxqWaZamgmHrpv22CN/KdbZJuGEGgfQoL00LTdg==} @@ -2343,6 +2383,9 @@ packages: resolution: {integrity: sha512-/8UvqAPU9DGTI9k4mxtf49U37Isfwr8Uts96+SBHIkFxPJnHS0Ew4f00sM4Scd8V8EjM0jUNtVDdv1kPdt35lg==} engines: {node: '>= 4'} + immer@11.1.21: + resolution: {integrity: sha512-bZSadeCPGdaY5/qRLgr6mDSH1ra21rD3rqpiWk7+QTr4ayYPTE9qZYdLh/NdPhMe0wSrTvHD/Lk8q5EwhUs0aw==} + import-meta-resolve@4.2.0: resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} @@ -2993,6 +3036,10 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + simple-icons@16.35.0: + resolution: {integrity: sha512-TCfl/2+GTrx0nCo4pEWGvxhOb8c6NsqOU1OpwjtF4lwJAthB8IYVD0fuIMjLMg6JFuG1YBO0t1iETQqJLqkoJA==} + engines: {node: '>=0.12.18'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -3356,6 +3403,24 @@ packages: zod@4.4.3: resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + zustand@5.0.15: + resolution: {integrity: sha512-MpSEjRiBkA9crSYeOUH32rJC7SVqAbm0Fqcqge/bUi2PPoLcBWKOsG+C8mevmpr8TwXHBVkChbbJiyvkE+i/3A==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + immer: '>=9.0.6' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -3808,6 +3873,10 @@ snapshots: '@deepseek-ai/cordis': 4.0.4(@deepseek-ai/cordis-plugin-include@1.0.9)(@deepseek-ai/cordis-plugin-loader@1.0.5) '@deepseek-ai/schemastery': 3.18.4 + '@deepseek-ai/dsh-client-store@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4)': + dependencies: + '@deepseek-ai/cordis': 4.0.4(@deepseek-ai/cordis-plugin-include@1.0.9)(@deepseek-ai/cordis-plugin-loader@1.0.5) + '@deepseek-ai/dsh-client-ui-conversation@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4)': dependencies: '@deepseek-ai/cordis': 4.0.4(@deepseek-ai/cordis-plugin-include@1.0.9)(@deepseek-ai/cordis-plugin-loader@1.0.5) @@ -4022,6 +4091,10 @@ snapshots: '@deepseek-ai/dsh-system-prompt': 0.2.0-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-llm@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4))(@deepseek-ai/dsh-scope@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4)(@deepseek-ai/dsh-invariants@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4))) '@deepseek-ai/schemastery': 3.18.4 + '@deepseek-ai/dsh-util-code-language@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4)': + dependencies: + '@deepseek-ai/cordis': 4.0.4(@deepseek-ai/cordis-plugin-include@1.0.9)(@deepseek-ai/cordis-plugin-loader@1.0.5) + '@deepseek-ai/dsh-util-crypto@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4)': dependencies: '@deepseek-ai/cordis': 4.0.4(@deepseek-ai/cordis-plugin-include@1.0.9)(@deepseek-ai/cordis-plugin-loader@1.0.5) @@ -4034,6 +4107,10 @@ snapshots: dependencies: '@deepseek-ai/cordis': 4.0.4(@deepseek-ai/cordis-plugin-include@1.0.9)(@deepseek-ai/cordis-plugin-loader@1.0.5) + '@deepseek-ai/dsh-util-workspace-path@0.2.0-rc.2(@deepseek-ai/cordis@4.0.4)': + dependencies: + '@deepseek-ai/cordis': 4.0.4(@deepseek-ai/cordis-plugin-include@1.0.9)(@deepseek-ai/cordis-plugin-loader@1.0.5) + '@deepseek-ai/schemastery@3.18.4': dependencies: '@deepseek-ai/cosmokit': 1.8.5 @@ -5202,6 +5279,8 @@ snapshots: dependencies: dequal: 2.0.3 + diff@9.0.0: {} + dompurify@3.4.14: optionalDependencies: '@types/trusted-types': 2.0.7 @@ -5408,6 +5487,8 @@ snapshots: ignore@7.0.12: {} + immer@11.1.21: {} + import-meta-resolve@4.2.0: {} import-without-cache@0.4.0: {} @@ -6253,6 +6334,8 @@ snapshots: siginfo@2.0.0: {} + simple-icons@16.35.0: {} + source-map-js@1.2.1: {} source-map-js@1.2.2: {} @@ -6549,4 +6632,10 @@ snapshots: zod@4.4.3: {} + zustand@5.0.15(@types/react@18.3.31)(immer@11.1.21)(react@18.2.0): + optionalDependencies: + '@types/react': 18.3.31 + immer: 11.1.21 + react: 18.2.0 + zwitch@2.0.4: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index c4a3648..135f168 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -76,3 +76,4 @@ minimumReleaseAgeExclude: - '@deepseek-ai/dsh-workspace@0.0.1-rc.1' - '@deepseek-ai/schemastery@3.18.1-rc.1 || 3.18.1' - '@huanlin/dsh-plugin-better-locale@0.1.0' + - simple-icons@16.35.0 diff --git a/tests/apes-tabs.spec.ts b/tests/apes-tabs.spec.ts index 547cc5a..e5e7a51 100644 --- a/tests/apes-tabs.spec.ts +++ b/tests/apes-tabs.spec.ts @@ -1,3 +1,4 @@ +// @vitest-environment jsdom /** * apes:* tab registration tests (Phase 1/1b, C6: 3 tabs). The fork registers * its three information-layer tabs (agents / apps / profile) through the same diff --git a/tests/builtins.spec.ts b/tests/builtins.spec.ts index 1a26e51..aeaae2e 100644 --- a/tests/builtins.spec.ts +++ b/tests/builtins.spec.ts @@ -1,3 +1,4 @@ +// @vitest-environment jsdom /** * Built-in registration tests: the plugin registers 7 tabs and 6 file * viewers through the same service external plugins use (dogfooding); diff --git a/tests/markdown-copy-labels.spec.tsx b/tests/markdown-copy-labels.spec.tsx index fc57ddb..decb695 100644 --- a/tests/markdown-copy-labels.spec.tsx +++ b/tests/markdown-copy-labels.spec.tsx @@ -1,3 +1,4 @@ +// @vitest-environment jsdom /** * Markdown preview copy-label spec: the fence copy buttons ("复制" / "Copy") * must follow the DSH locale service through `codeLabels` — the DSH diff --git a/tests/markdown-frontmatter.spec.tsx b/tests/markdown-frontmatter.spec.tsx index 7ac43e2..45b8aad 100644 --- a/tests/markdown-frontmatter.spec.tsx +++ b/tests/markdown-frontmatter.spec.tsx @@ -1,3 +1,4 @@ +// @vitest-environment jsdom /** * Markdown frontmatter preview regression (#251): a leading, closed YAML * metadata block must not reach the shared MarkdownText parser, where its diff --git a/tests/sandbox-views.spec.tsx b/tests/sandbox-views.spec.tsx index ee5ab9a..01ce168 100644 --- a/tests/sandbox-views.spec.tsx +++ b/tests/sandbox-views.spec.tsx @@ -1,3 +1,4 @@ +// @vitest-environment jsdom /** * Sandbox-contract tests for the two built-in web surfaces (HTML preview * iframe and the browser tab iframe). The iframe sandbox — opaque origin, diff --git a/vitest.config.ts b/vitest.config.ts index ac175e3..62fffec 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -12,7 +12,21 @@ */ import { defineConfig } from 'vitest/config' +// 上游 dsh-client-ui-primitives 的 lib 带 sourceMappingURL 注释但未发布 map +// 文件(package.json 的 files 不含 .map)→ Vite 读 map 报 ENOENT。 +// 这里在 transform 阶段剥掉该注释;不要手改 node_modules(pnpm install 即失效)。 +const stripMissingSourcemapRefs = { + name: 'strip-missing-sourcemap-refs', + enforce: 'pre' as const, + transform(code: string, id: string) { + if (!id.includes('dsh-client-ui-primitives')) return + if (!code.includes('sourceMappingURL')) return + return { code: code.replace(/\/\/\/?\s*sourceMappingURL=.*$/gm, ''), map: null } + }, +} + export default defineConfig({ + plugins: [stripMissingSourcemapRefs], test: { // Bridge Node's `localStorage` accessor to jsdom's store (see the file). setupFiles: ['tests/setup.ts'],