singularity-forge/scripts/compile-tests.mjs

244 lines
8.1 KiB
JavaScript
Raw Normal View History

perf(test): compile unit tests with esbuild, reclassify integration tests, fix node_modules symlink (#2809) * fix(test): wire src/resources/extensions/shared/tests/ into test:unit runner The test:unit glob excluded src/resources/extensions/shared/tests/ entirely, leaving format-utils.test.ts (and any future tests there) silently unfired. - Add shared/tests/*.test.ts to the test:unit glob in package.json - Export newestSrcMtime from ensure-workspace-builds.cjs (require.main guard prevents side-effects on require) so the staleness logic can be tested - Add src/tests/ensure-workspace-builds.test.ts covering newestSrcMtime: non-existent dir, no .ts files, single file, max of multiple, recursion, node_modules skip Closes #2808 * perf(test): compile unit tests with esbuild and fix dist-test/node_modules Replace per-file --experimental-strip-types with a single esbuild compilation step (scripts/compile-tests.mjs) that compiles all src/ TypeScript to dist-test/ in ~3s, then runs the pre-compiled JS. Eliminates ~1.7s Node startup overhead per test file. - scripts/compile-tests.mjs: esbuild compilation, asset copy, .ts→.js rewrite, stale file cleanup; creates dist-test/node_modules symlink so resource-loader.ts resolves gsdNodeModules to a real path (fixes node-modules-symlink test failure) - scripts/dist-test-resolve.mjs: ESM loader hook for @gsd/* bare specifiers and .ts→.js fallback rewriting at runtime - .gitignore: exclude dist-test/ from version control - package.json: add test:compile script; update test:unit to compile-then-run; update test:integration globs to cover new integration/ subdirectories - worker-registry.ts: unref() cleanup timer so it does not keep the Node process alive after tests complete Closes #2858 * fix(test): update relative imports in tests/integration/ after directory move When tests were moved from tests/ to tests/integration/ in the previous commit, relative imports weren't updated. ../foo now resolves one level too shallow. Fix all 117 import paths across 43 test files: - ../foo → ../../foo (source files at gsd/ level) - ../../get-secrets-from-user.ts → ../../../ (at extensions/ level) - ../../subagent/worker-registry.ts → ../../../ (at extensions/ level) - ./marketplace-test-fixtures.js → ../marketplace-test-fixtures.ts - ./test-helpers.ts → ../test-helpers.ts typecheck:extensions now passes with zero errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(integration): set 10-minute timeout for integration test runner build job takes ~7min on main. Without a global timeout, hanging tests block the suite indefinitely. --test-timeout=600000 caps each test at 10min. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Revert "test(integration): set 10-minute timeout for integration test runner" This reverts commit be77ead77d369ad8569292ae6b69ba56435f5433. * fix(test): correct formatDuration(0) edge case and docker test root path - formatDuration(0) now returns '0s' instead of '0ms' by guarding the sub-second branch with ms > 0 - docker-template.test.ts root path goes ../../.. from dist-test/src/tests/ to reach project root instead of landing in dist-test/ - replace require() calls in skill-health.ts and visualizer-overlay.ts with proper ES module imports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct relative import paths in integration tests All affected tests were one directory level off — importing from ../web/ and ../resources/ when the correct paths are ../../web/ and ../../resources/. Tests live at src/tests/integration/, not src/tests/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): add esbuild to root devDeps and wire dist-test-resolve hook P1: esbuild was only in web/package.json — compile-tests.mjs requires it at the root node_modules path, so CI failed on clean installs. P2: dist-test-resolve.mjs existed but was never loaded; @gsd/* imports in compiled tests resolved to installed workspace packages instead of freshly compiled dist-test output. Add --import to test:unit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(deps): align esbuild version with lock file (0.25.12) ^0.27.4 didn't satisfy the existing lock file entry. Use the version already present so npm ci passes without regenerating the lock file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct all relative import depths in src/tests/integration/ Tests in src/tests/integration/ need 3 levels up (../../..) to reach project-root dirs (web/, packages/) and 2 levels up (../..) to reach src-level dirs (src/web/, src/cli-web-branch.ts). Fixes: - ../../web/lib/ → ../../../web/lib/ (Next.js app, not src/web/) - ../../web/app/ → ../../../web/app/ - ../../packages/ → ../../../packages/ - ../cli-web-branch.ts → ../../cli-web-branch.ts - ../web-mode.ts → ../../web-mode.ts - ../resources/extensions/ → ../../resources/extensions/ - ci_monitor ROOT path: 2 levels up → 3 levels up - web-responsive WEB_ROOT: 2 levels up → 3 levels up Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): use dot reporter for test:unit to reduce noise Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): switch test:unit reporter to tap Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): compact test reporter — silent on pass, failures + summary only Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): include shared/tests in test:coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct path depths in tests moved to integration/ Tests moved from tests/ to tests/integration/ need one extra ../ to reach the same source files. Also fix web component paths — those files live at web/ not src/web/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): fix web component paths in web-session-parity-contract Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): use process.cwd() for project root in docker-template test Resolving relative to __dirname breaks under test:coverage which runs source files directly from src/tests/ — needs ../.. not ../../.. (the extra level only exists in the compiled dist-test/ output). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: retrigger CI --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 16:51:49 -04:00
#!/usr/bin/env node
2026-05-05 14:46:18 +02:00
perf(test): compile unit tests with esbuild, reclassify integration tests, fix node_modules symlink (#2809) * fix(test): wire src/resources/extensions/shared/tests/ into test:unit runner The test:unit glob excluded src/resources/extensions/shared/tests/ entirely, leaving format-utils.test.ts (and any future tests there) silently unfired. - Add shared/tests/*.test.ts to the test:unit glob in package.json - Export newestSrcMtime from ensure-workspace-builds.cjs (require.main guard prevents side-effects on require) so the staleness logic can be tested - Add src/tests/ensure-workspace-builds.test.ts covering newestSrcMtime: non-existent dir, no .ts files, single file, max of multiple, recursion, node_modules skip Closes #2808 * perf(test): compile unit tests with esbuild and fix dist-test/node_modules Replace per-file --experimental-strip-types with a single esbuild compilation step (scripts/compile-tests.mjs) that compiles all src/ TypeScript to dist-test/ in ~3s, then runs the pre-compiled JS. Eliminates ~1.7s Node startup overhead per test file. - scripts/compile-tests.mjs: esbuild compilation, asset copy, .ts→.js rewrite, stale file cleanup; creates dist-test/node_modules symlink so resource-loader.ts resolves gsdNodeModules to a real path (fixes node-modules-symlink test failure) - scripts/dist-test-resolve.mjs: ESM loader hook for @gsd/* bare specifiers and .ts→.js fallback rewriting at runtime - .gitignore: exclude dist-test/ from version control - package.json: add test:compile script; update test:unit to compile-then-run; update test:integration globs to cover new integration/ subdirectories - worker-registry.ts: unref() cleanup timer so it does not keep the Node process alive after tests complete Closes #2858 * fix(test): update relative imports in tests/integration/ after directory move When tests were moved from tests/ to tests/integration/ in the previous commit, relative imports weren't updated. ../foo now resolves one level too shallow. Fix all 117 import paths across 43 test files: - ../foo → ../../foo (source files at gsd/ level) - ../../get-secrets-from-user.ts → ../../../ (at extensions/ level) - ../../subagent/worker-registry.ts → ../../../ (at extensions/ level) - ./marketplace-test-fixtures.js → ../marketplace-test-fixtures.ts - ./test-helpers.ts → ../test-helpers.ts typecheck:extensions now passes with zero errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(integration): set 10-minute timeout for integration test runner build job takes ~7min on main. Without a global timeout, hanging tests block the suite indefinitely. --test-timeout=600000 caps each test at 10min. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Revert "test(integration): set 10-minute timeout for integration test runner" This reverts commit be77ead77d369ad8569292ae6b69ba56435f5433. * fix(test): correct formatDuration(0) edge case and docker test root path - formatDuration(0) now returns '0s' instead of '0ms' by guarding the sub-second branch with ms > 0 - docker-template.test.ts root path goes ../../.. from dist-test/src/tests/ to reach project root instead of landing in dist-test/ - replace require() calls in skill-health.ts and visualizer-overlay.ts with proper ES module imports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct relative import paths in integration tests All affected tests were one directory level off — importing from ../web/ and ../resources/ when the correct paths are ../../web/ and ../../resources/. Tests live at src/tests/integration/, not src/tests/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): add esbuild to root devDeps and wire dist-test-resolve hook P1: esbuild was only in web/package.json — compile-tests.mjs requires it at the root node_modules path, so CI failed on clean installs. P2: dist-test-resolve.mjs existed but was never loaded; @gsd/* imports in compiled tests resolved to installed workspace packages instead of freshly compiled dist-test output. Add --import to test:unit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(deps): align esbuild version with lock file (0.25.12) ^0.27.4 didn't satisfy the existing lock file entry. Use the version already present so npm ci passes without regenerating the lock file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct all relative import depths in src/tests/integration/ Tests in src/tests/integration/ need 3 levels up (../../..) to reach project-root dirs (web/, packages/) and 2 levels up (../..) to reach src-level dirs (src/web/, src/cli-web-branch.ts). Fixes: - ../../web/lib/ → ../../../web/lib/ (Next.js app, not src/web/) - ../../web/app/ → ../../../web/app/ - ../../packages/ → ../../../packages/ - ../cli-web-branch.ts → ../../cli-web-branch.ts - ../web-mode.ts → ../../web-mode.ts - ../resources/extensions/ → ../../resources/extensions/ - ci_monitor ROOT path: 2 levels up → 3 levels up - web-responsive WEB_ROOT: 2 levels up → 3 levels up Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): use dot reporter for test:unit to reduce noise Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): switch test:unit reporter to tap Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): compact test reporter — silent on pass, failures + summary only Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): include shared/tests in test:coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct path depths in tests moved to integration/ Tests moved from tests/ to tests/integration/ need one extra ../ to reach the same source files. Also fix web component paths — those files live at web/ not src/web/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): fix web component paths in web-session-parity-contract Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): use process.cwd() for project root in docker-template test Resolving relative to __dirname breaks under test:coverage which runs source files directly from src/tests/ — needs ../.. not ../../.. (the extra level only exists in the compiled dist-test/ output). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: retrigger CI --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 16:51:49 -04:00
/**
* Compile all TypeScript source + test files to dist-test/ using esbuild.
* Run compiled JS directly with node --test (no per-file TS overhead).
*
* Usage: node scripts/compile-tests.mjs
*/
2026-05-05 14:46:18 +02:00
import { symlinkSync } from "node:fs";
2026-05-05 14:31:16 +02:00
import { cp, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
import { createRequire } from "node:module";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
perf(test): compile unit tests with esbuild, reclassify integration tests, fix node_modules symlink (#2809) * fix(test): wire src/resources/extensions/shared/tests/ into test:unit runner The test:unit glob excluded src/resources/extensions/shared/tests/ entirely, leaving format-utils.test.ts (and any future tests there) silently unfired. - Add shared/tests/*.test.ts to the test:unit glob in package.json - Export newestSrcMtime from ensure-workspace-builds.cjs (require.main guard prevents side-effects on require) so the staleness logic can be tested - Add src/tests/ensure-workspace-builds.test.ts covering newestSrcMtime: non-existent dir, no .ts files, single file, max of multiple, recursion, node_modules skip Closes #2808 * perf(test): compile unit tests with esbuild and fix dist-test/node_modules Replace per-file --experimental-strip-types with a single esbuild compilation step (scripts/compile-tests.mjs) that compiles all src/ TypeScript to dist-test/ in ~3s, then runs the pre-compiled JS. Eliminates ~1.7s Node startup overhead per test file. - scripts/compile-tests.mjs: esbuild compilation, asset copy, .ts→.js rewrite, stale file cleanup; creates dist-test/node_modules symlink so resource-loader.ts resolves gsdNodeModules to a real path (fixes node-modules-symlink test failure) - scripts/dist-test-resolve.mjs: ESM loader hook for @gsd/* bare specifiers and .ts→.js fallback rewriting at runtime - .gitignore: exclude dist-test/ from version control - package.json: add test:compile script; update test:unit to compile-then-run; update test:integration globs to cover new integration/ subdirectories - worker-registry.ts: unref() cleanup timer so it does not keep the Node process alive after tests complete Closes #2858 * fix(test): update relative imports in tests/integration/ after directory move When tests were moved from tests/ to tests/integration/ in the previous commit, relative imports weren't updated. ../foo now resolves one level too shallow. Fix all 117 import paths across 43 test files: - ../foo → ../../foo (source files at gsd/ level) - ../../get-secrets-from-user.ts → ../../../ (at extensions/ level) - ../../subagent/worker-registry.ts → ../../../ (at extensions/ level) - ./marketplace-test-fixtures.js → ../marketplace-test-fixtures.ts - ./test-helpers.ts → ../test-helpers.ts typecheck:extensions now passes with zero errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(integration): set 10-minute timeout for integration test runner build job takes ~7min on main. Without a global timeout, hanging tests block the suite indefinitely. --test-timeout=600000 caps each test at 10min. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Revert "test(integration): set 10-minute timeout for integration test runner" This reverts commit be77ead77d369ad8569292ae6b69ba56435f5433. * fix(test): correct formatDuration(0) edge case and docker test root path - formatDuration(0) now returns '0s' instead of '0ms' by guarding the sub-second branch with ms > 0 - docker-template.test.ts root path goes ../../.. from dist-test/src/tests/ to reach project root instead of landing in dist-test/ - replace require() calls in skill-health.ts and visualizer-overlay.ts with proper ES module imports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct relative import paths in integration tests All affected tests were one directory level off — importing from ../web/ and ../resources/ when the correct paths are ../../web/ and ../../resources/. Tests live at src/tests/integration/, not src/tests/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): add esbuild to root devDeps and wire dist-test-resolve hook P1: esbuild was only in web/package.json — compile-tests.mjs requires it at the root node_modules path, so CI failed on clean installs. P2: dist-test-resolve.mjs existed but was never loaded; @gsd/* imports in compiled tests resolved to installed workspace packages instead of freshly compiled dist-test output. Add --import to test:unit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(deps): align esbuild version with lock file (0.25.12) ^0.27.4 didn't satisfy the existing lock file entry. Use the version already present so npm ci passes without regenerating the lock file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct all relative import depths in src/tests/integration/ Tests in src/tests/integration/ need 3 levels up (../../..) to reach project-root dirs (web/, packages/) and 2 levels up (../..) to reach src-level dirs (src/web/, src/cli-web-branch.ts). Fixes: - ../../web/lib/ → ../../../web/lib/ (Next.js app, not src/web/) - ../../web/app/ → ../../../web/app/ - ../../packages/ → ../../../packages/ - ../cli-web-branch.ts → ../../cli-web-branch.ts - ../web-mode.ts → ../../web-mode.ts - ../resources/extensions/ → ../../resources/extensions/ - ci_monitor ROOT path: 2 levels up → 3 levels up - web-responsive WEB_ROOT: 2 levels up → 3 levels up Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): use dot reporter for test:unit to reduce noise Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): switch test:unit reporter to tap Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): compact test reporter — silent on pass, failures + summary only Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): include shared/tests in test:coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct path depths in tests moved to integration/ Tests moved from tests/ to tests/integration/ need one extra ../ to reach the same source files. Also fix web component paths — those files live at web/ not src/web/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): fix web component paths in web-session-parity-contract Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): use process.cwd() for project root in docker-template test Resolving relative to __dirname breaks under test:coverage which runs source files directly from src/tests/ — needs ../.. not ../../.. (the extra level only exists in the compiled dist-test/ output). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: retrigger CI --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 16:51:49 -04:00
2026-05-05 14:31:16 +02:00
const __dirname = fileURLToPath(new URL(".", import.meta.url));
const ROOT = join(__dirname, "..");
perf(test): compile unit tests with esbuild, reclassify integration tests, fix node_modules symlink (#2809) * fix(test): wire src/resources/extensions/shared/tests/ into test:unit runner The test:unit glob excluded src/resources/extensions/shared/tests/ entirely, leaving format-utils.test.ts (and any future tests there) silently unfired. - Add shared/tests/*.test.ts to the test:unit glob in package.json - Export newestSrcMtime from ensure-workspace-builds.cjs (require.main guard prevents side-effects on require) so the staleness logic can be tested - Add src/tests/ensure-workspace-builds.test.ts covering newestSrcMtime: non-existent dir, no .ts files, single file, max of multiple, recursion, node_modules skip Closes #2808 * perf(test): compile unit tests with esbuild and fix dist-test/node_modules Replace per-file --experimental-strip-types with a single esbuild compilation step (scripts/compile-tests.mjs) that compiles all src/ TypeScript to dist-test/ in ~3s, then runs the pre-compiled JS. Eliminates ~1.7s Node startup overhead per test file. - scripts/compile-tests.mjs: esbuild compilation, asset copy, .ts→.js rewrite, stale file cleanup; creates dist-test/node_modules symlink so resource-loader.ts resolves gsdNodeModules to a real path (fixes node-modules-symlink test failure) - scripts/dist-test-resolve.mjs: ESM loader hook for @gsd/* bare specifiers and .ts→.js fallback rewriting at runtime - .gitignore: exclude dist-test/ from version control - package.json: add test:compile script; update test:unit to compile-then-run; update test:integration globs to cover new integration/ subdirectories - worker-registry.ts: unref() cleanup timer so it does not keep the Node process alive after tests complete Closes #2858 * fix(test): update relative imports in tests/integration/ after directory move When tests were moved from tests/ to tests/integration/ in the previous commit, relative imports weren't updated. ../foo now resolves one level too shallow. Fix all 117 import paths across 43 test files: - ../foo → ../../foo (source files at gsd/ level) - ../../get-secrets-from-user.ts → ../../../ (at extensions/ level) - ../../subagent/worker-registry.ts → ../../../ (at extensions/ level) - ./marketplace-test-fixtures.js → ../marketplace-test-fixtures.ts - ./test-helpers.ts → ../test-helpers.ts typecheck:extensions now passes with zero errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(integration): set 10-minute timeout for integration test runner build job takes ~7min on main. Without a global timeout, hanging tests block the suite indefinitely. --test-timeout=600000 caps each test at 10min. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Revert "test(integration): set 10-minute timeout for integration test runner" This reverts commit be77ead77d369ad8569292ae6b69ba56435f5433. * fix(test): correct formatDuration(0) edge case and docker test root path - formatDuration(0) now returns '0s' instead of '0ms' by guarding the sub-second branch with ms > 0 - docker-template.test.ts root path goes ../../.. from dist-test/src/tests/ to reach project root instead of landing in dist-test/ - replace require() calls in skill-health.ts and visualizer-overlay.ts with proper ES module imports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct relative import paths in integration tests All affected tests were one directory level off — importing from ../web/ and ../resources/ when the correct paths are ../../web/ and ../../resources/. Tests live at src/tests/integration/, not src/tests/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): add esbuild to root devDeps and wire dist-test-resolve hook P1: esbuild was only in web/package.json — compile-tests.mjs requires it at the root node_modules path, so CI failed on clean installs. P2: dist-test-resolve.mjs existed but was never loaded; @gsd/* imports in compiled tests resolved to installed workspace packages instead of freshly compiled dist-test output. Add --import to test:unit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(deps): align esbuild version with lock file (0.25.12) ^0.27.4 didn't satisfy the existing lock file entry. Use the version already present so npm ci passes without regenerating the lock file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct all relative import depths in src/tests/integration/ Tests in src/tests/integration/ need 3 levels up (../../..) to reach project-root dirs (web/, packages/) and 2 levels up (../..) to reach src-level dirs (src/web/, src/cli-web-branch.ts). Fixes: - ../../web/lib/ → ../../../web/lib/ (Next.js app, not src/web/) - ../../web/app/ → ../../../web/app/ - ../../packages/ → ../../../packages/ - ../cli-web-branch.ts → ../../cli-web-branch.ts - ../web-mode.ts → ../../web-mode.ts - ../resources/extensions/ → ../../resources/extensions/ - ci_monitor ROOT path: 2 levels up → 3 levels up - web-responsive WEB_ROOT: 2 levels up → 3 levels up Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): use dot reporter for test:unit to reduce noise Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): switch test:unit reporter to tap Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): compact test reporter — silent on pass, failures + summary only Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): include shared/tests in test:coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct path depths in tests moved to integration/ Tests moved from tests/ to tests/integration/ need one extra ../ to reach the same source files. Also fix web component paths — those files live at web/ not src/web/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): fix web component paths in web-session-parity-contract Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): use process.cwd() for project root in docker-template test Resolving relative to __dirname breaks under test:coverage which runs source files directly from src/tests/ — needs ../.. not ../../.. (the extra level only exists in the compiled dist-test/ output). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: retrigger CI --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 16:51:49 -04:00
const require = createRequire(import.meta.url);
2026-05-05 14:31:16 +02:00
const esbuild = require(join(ROOT, "node_modules/esbuild"));
perf(test): compile unit tests with esbuild, reclassify integration tests, fix node_modules symlink (#2809) * fix(test): wire src/resources/extensions/shared/tests/ into test:unit runner The test:unit glob excluded src/resources/extensions/shared/tests/ entirely, leaving format-utils.test.ts (and any future tests there) silently unfired. - Add shared/tests/*.test.ts to the test:unit glob in package.json - Export newestSrcMtime from ensure-workspace-builds.cjs (require.main guard prevents side-effects on require) so the staleness logic can be tested - Add src/tests/ensure-workspace-builds.test.ts covering newestSrcMtime: non-existent dir, no .ts files, single file, max of multiple, recursion, node_modules skip Closes #2808 * perf(test): compile unit tests with esbuild and fix dist-test/node_modules Replace per-file --experimental-strip-types with a single esbuild compilation step (scripts/compile-tests.mjs) that compiles all src/ TypeScript to dist-test/ in ~3s, then runs the pre-compiled JS. Eliminates ~1.7s Node startup overhead per test file. - scripts/compile-tests.mjs: esbuild compilation, asset copy, .ts→.js rewrite, stale file cleanup; creates dist-test/node_modules symlink so resource-loader.ts resolves gsdNodeModules to a real path (fixes node-modules-symlink test failure) - scripts/dist-test-resolve.mjs: ESM loader hook for @gsd/* bare specifiers and .ts→.js fallback rewriting at runtime - .gitignore: exclude dist-test/ from version control - package.json: add test:compile script; update test:unit to compile-then-run; update test:integration globs to cover new integration/ subdirectories - worker-registry.ts: unref() cleanup timer so it does not keep the Node process alive after tests complete Closes #2858 * fix(test): update relative imports in tests/integration/ after directory move When tests were moved from tests/ to tests/integration/ in the previous commit, relative imports weren't updated. ../foo now resolves one level too shallow. Fix all 117 import paths across 43 test files: - ../foo → ../../foo (source files at gsd/ level) - ../../get-secrets-from-user.ts → ../../../ (at extensions/ level) - ../../subagent/worker-registry.ts → ../../../ (at extensions/ level) - ./marketplace-test-fixtures.js → ../marketplace-test-fixtures.ts - ./test-helpers.ts → ../test-helpers.ts typecheck:extensions now passes with zero errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(integration): set 10-minute timeout for integration test runner build job takes ~7min on main. Without a global timeout, hanging tests block the suite indefinitely. --test-timeout=600000 caps each test at 10min. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Revert "test(integration): set 10-minute timeout for integration test runner" This reverts commit be77ead77d369ad8569292ae6b69ba56435f5433. * fix(test): correct formatDuration(0) edge case and docker test root path - formatDuration(0) now returns '0s' instead of '0ms' by guarding the sub-second branch with ms > 0 - docker-template.test.ts root path goes ../../.. from dist-test/src/tests/ to reach project root instead of landing in dist-test/ - replace require() calls in skill-health.ts and visualizer-overlay.ts with proper ES module imports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct relative import paths in integration tests All affected tests were one directory level off — importing from ../web/ and ../resources/ when the correct paths are ../../web/ and ../../resources/. Tests live at src/tests/integration/, not src/tests/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): add esbuild to root devDeps and wire dist-test-resolve hook P1: esbuild was only in web/package.json — compile-tests.mjs requires it at the root node_modules path, so CI failed on clean installs. P2: dist-test-resolve.mjs existed but was never loaded; @gsd/* imports in compiled tests resolved to installed workspace packages instead of freshly compiled dist-test output. Add --import to test:unit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(deps): align esbuild version with lock file (0.25.12) ^0.27.4 didn't satisfy the existing lock file entry. Use the version already present so npm ci passes without regenerating the lock file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct all relative import depths in src/tests/integration/ Tests in src/tests/integration/ need 3 levels up (../../..) to reach project-root dirs (web/, packages/) and 2 levels up (../..) to reach src-level dirs (src/web/, src/cli-web-branch.ts). Fixes: - ../../web/lib/ → ../../../web/lib/ (Next.js app, not src/web/) - ../../web/app/ → ../../../web/app/ - ../../packages/ → ../../../packages/ - ../cli-web-branch.ts → ../../cli-web-branch.ts - ../web-mode.ts → ../../web-mode.ts - ../resources/extensions/ → ../../resources/extensions/ - ci_monitor ROOT path: 2 levels up → 3 levels up - web-responsive WEB_ROOT: 2 levels up → 3 levels up Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): use dot reporter for test:unit to reduce noise Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): switch test:unit reporter to tap Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): compact test reporter — silent on pass, failures + summary only Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): include shared/tests in test:coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct path depths in tests moved to integration/ Tests moved from tests/ to tests/integration/ need one extra ../ to reach the same source files. Also fix web component paths — those files live at web/ not src/web/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): fix web component paths in web-session-parity-contract Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): use process.cwd() for project root in docker-template test Resolving relative to __dirname breaks under test:coverage which runs source files directly from src/tests/ — needs ../.. not ../../.. (the extra level only exists in the compiled dist-test/ output). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: retrigger CI --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 16:51:49 -04:00
// Recursively collect files by extension (skip node_modules, templates, etc.)
// Directories to skip during file collection
2026-05-05 14:31:16 +02:00
const SKIP_DIRS = new Set([
"node_modules",
"templates",
"__tests__",
"integration",
]);
async function collectFiles(dir, exts = [".ts", ".mjs"]) {
const results = [];
let entries;
try {
entries = await readdir(dir, { withFileTypes: true });
} catch {
return results;
}
for (const entry of entries) {
if (SKIP_DIRS.has(entry.name)) continue;
const full = join(dir, entry.name);
if (entry.isDirectory()) {
results.push(...(await collectFiles(full, exts)));
} else if (
exts.some((ext) => entry.name.endsWith(ext)) &&
!entry.name.endsWith(".d.ts")
) {
results.push(full);
}
}
return results;
perf(test): compile unit tests with esbuild, reclassify integration tests, fix node_modules symlink (#2809) * fix(test): wire src/resources/extensions/shared/tests/ into test:unit runner The test:unit glob excluded src/resources/extensions/shared/tests/ entirely, leaving format-utils.test.ts (and any future tests there) silently unfired. - Add shared/tests/*.test.ts to the test:unit glob in package.json - Export newestSrcMtime from ensure-workspace-builds.cjs (require.main guard prevents side-effects on require) so the staleness logic can be tested - Add src/tests/ensure-workspace-builds.test.ts covering newestSrcMtime: non-existent dir, no .ts files, single file, max of multiple, recursion, node_modules skip Closes #2808 * perf(test): compile unit tests with esbuild and fix dist-test/node_modules Replace per-file --experimental-strip-types with a single esbuild compilation step (scripts/compile-tests.mjs) that compiles all src/ TypeScript to dist-test/ in ~3s, then runs the pre-compiled JS. Eliminates ~1.7s Node startup overhead per test file. - scripts/compile-tests.mjs: esbuild compilation, asset copy, .ts→.js rewrite, stale file cleanup; creates dist-test/node_modules symlink so resource-loader.ts resolves gsdNodeModules to a real path (fixes node-modules-symlink test failure) - scripts/dist-test-resolve.mjs: ESM loader hook for @gsd/* bare specifiers and .ts→.js fallback rewriting at runtime - .gitignore: exclude dist-test/ from version control - package.json: add test:compile script; update test:unit to compile-then-run; update test:integration globs to cover new integration/ subdirectories - worker-registry.ts: unref() cleanup timer so it does not keep the Node process alive after tests complete Closes #2858 * fix(test): update relative imports in tests/integration/ after directory move When tests were moved from tests/ to tests/integration/ in the previous commit, relative imports weren't updated. ../foo now resolves one level too shallow. Fix all 117 import paths across 43 test files: - ../foo → ../../foo (source files at gsd/ level) - ../../get-secrets-from-user.ts → ../../../ (at extensions/ level) - ../../subagent/worker-registry.ts → ../../../ (at extensions/ level) - ./marketplace-test-fixtures.js → ../marketplace-test-fixtures.ts - ./test-helpers.ts → ../test-helpers.ts typecheck:extensions now passes with zero errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(integration): set 10-minute timeout for integration test runner build job takes ~7min on main. Without a global timeout, hanging tests block the suite indefinitely. --test-timeout=600000 caps each test at 10min. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Revert "test(integration): set 10-minute timeout for integration test runner" This reverts commit be77ead77d369ad8569292ae6b69ba56435f5433. * fix(test): correct formatDuration(0) edge case and docker test root path - formatDuration(0) now returns '0s' instead of '0ms' by guarding the sub-second branch with ms > 0 - docker-template.test.ts root path goes ../../.. from dist-test/src/tests/ to reach project root instead of landing in dist-test/ - replace require() calls in skill-health.ts and visualizer-overlay.ts with proper ES module imports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct relative import paths in integration tests All affected tests were one directory level off — importing from ../web/ and ../resources/ when the correct paths are ../../web/ and ../../resources/. Tests live at src/tests/integration/, not src/tests/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): add esbuild to root devDeps and wire dist-test-resolve hook P1: esbuild was only in web/package.json — compile-tests.mjs requires it at the root node_modules path, so CI failed on clean installs. P2: dist-test-resolve.mjs existed but was never loaded; @gsd/* imports in compiled tests resolved to installed workspace packages instead of freshly compiled dist-test output. Add --import to test:unit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(deps): align esbuild version with lock file (0.25.12) ^0.27.4 didn't satisfy the existing lock file entry. Use the version already present so npm ci passes without regenerating the lock file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct all relative import depths in src/tests/integration/ Tests in src/tests/integration/ need 3 levels up (../../..) to reach project-root dirs (web/, packages/) and 2 levels up (../..) to reach src-level dirs (src/web/, src/cli-web-branch.ts). Fixes: - ../../web/lib/ → ../../../web/lib/ (Next.js app, not src/web/) - ../../web/app/ → ../../../web/app/ - ../../packages/ → ../../../packages/ - ../cli-web-branch.ts → ../../cli-web-branch.ts - ../web-mode.ts → ../../web-mode.ts - ../resources/extensions/ → ../../resources/extensions/ - ci_monitor ROOT path: 2 levels up → 3 levels up - web-responsive WEB_ROOT: 2 levels up → 3 levels up Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): use dot reporter for test:unit to reduce noise Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): switch test:unit reporter to tap Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): compact test reporter — silent on pass, failures + summary only Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): include shared/tests in test:coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct path depths in tests moved to integration/ Tests moved from tests/ to tests/integration/ need one extra ../ to reach the same source files. Also fix web component paths — those files live at web/ not src/web/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): fix web component paths in web-session-parity-contract Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): use process.cwd() for project root in docker-template test Resolving relative to __dirname breaks under test:coverage which runs source files directly from src/tests/ — needs ../.. not ../../.. (the extra level only exists in the compiled dist-test/ output). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: retrigger CI --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 16:51:49 -04:00
}
// Dirs to skip when copying assets (node_modules are never useful in dist-test)
2026-05-05 14:31:16 +02:00
const ASSET_SKIP_DIRS = new Set(["node_modules", "__tests__", "integration"]);
perf(test): compile unit tests with esbuild, reclassify integration tests, fix node_modules symlink (#2809) * fix(test): wire src/resources/extensions/shared/tests/ into test:unit runner The test:unit glob excluded src/resources/extensions/shared/tests/ entirely, leaving format-utils.test.ts (and any future tests there) silently unfired. - Add shared/tests/*.test.ts to the test:unit glob in package.json - Export newestSrcMtime from ensure-workspace-builds.cjs (require.main guard prevents side-effects on require) so the staleness logic can be tested - Add src/tests/ensure-workspace-builds.test.ts covering newestSrcMtime: non-existent dir, no .ts files, single file, max of multiple, recursion, node_modules skip Closes #2808 * perf(test): compile unit tests with esbuild and fix dist-test/node_modules Replace per-file --experimental-strip-types with a single esbuild compilation step (scripts/compile-tests.mjs) that compiles all src/ TypeScript to dist-test/ in ~3s, then runs the pre-compiled JS. Eliminates ~1.7s Node startup overhead per test file. - scripts/compile-tests.mjs: esbuild compilation, asset copy, .ts→.js rewrite, stale file cleanup; creates dist-test/node_modules symlink so resource-loader.ts resolves gsdNodeModules to a real path (fixes node-modules-symlink test failure) - scripts/dist-test-resolve.mjs: ESM loader hook for @gsd/* bare specifiers and .ts→.js fallback rewriting at runtime - .gitignore: exclude dist-test/ from version control - package.json: add test:compile script; update test:unit to compile-then-run; update test:integration globs to cover new integration/ subdirectories - worker-registry.ts: unref() cleanup timer so it does not keep the Node process alive after tests complete Closes #2858 * fix(test): update relative imports in tests/integration/ after directory move When tests were moved from tests/ to tests/integration/ in the previous commit, relative imports weren't updated. ../foo now resolves one level too shallow. Fix all 117 import paths across 43 test files: - ../foo → ../../foo (source files at gsd/ level) - ../../get-secrets-from-user.ts → ../../../ (at extensions/ level) - ../../subagent/worker-registry.ts → ../../../ (at extensions/ level) - ./marketplace-test-fixtures.js → ../marketplace-test-fixtures.ts - ./test-helpers.ts → ../test-helpers.ts typecheck:extensions now passes with zero errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(integration): set 10-minute timeout for integration test runner build job takes ~7min on main. Without a global timeout, hanging tests block the suite indefinitely. --test-timeout=600000 caps each test at 10min. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Revert "test(integration): set 10-minute timeout for integration test runner" This reverts commit be77ead77d369ad8569292ae6b69ba56435f5433. * fix(test): correct formatDuration(0) edge case and docker test root path - formatDuration(0) now returns '0s' instead of '0ms' by guarding the sub-second branch with ms > 0 - docker-template.test.ts root path goes ../../.. from dist-test/src/tests/ to reach project root instead of landing in dist-test/ - replace require() calls in skill-health.ts and visualizer-overlay.ts with proper ES module imports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct relative import paths in integration tests All affected tests were one directory level off — importing from ../web/ and ../resources/ when the correct paths are ../../web/ and ../../resources/. Tests live at src/tests/integration/, not src/tests/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): add esbuild to root devDeps and wire dist-test-resolve hook P1: esbuild was only in web/package.json — compile-tests.mjs requires it at the root node_modules path, so CI failed on clean installs. P2: dist-test-resolve.mjs existed but was never loaded; @gsd/* imports in compiled tests resolved to installed workspace packages instead of freshly compiled dist-test output. Add --import to test:unit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(deps): align esbuild version with lock file (0.25.12) ^0.27.4 didn't satisfy the existing lock file entry. Use the version already present so npm ci passes without regenerating the lock file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct all relative import depths in src/tests/integration/ Tests in src/tests/integration/ need 3 levels up (../../..) to reach project-root dirs (web/, packages/) and 2 levels up (../..) to reach src-level dirs (src/web/, src/cli-web-branch.ts). Fixes: - ../../web/lib/ → ../../../web/lib/ (Next.js app, not src/web/) - ../../web/app/ → ../../../web/app/ - ../../packages/ → ../../../packages/ - ../cli-web-branch.ts → ../../cli-web-branch.ts - ../web-mode.ts → ../../web-mode.ts - ../resources/extensions/ → ../../resources/extensions/ - ci_monitor ROOT path: 2 levels up → 3 levels up - web-responsive WEB_ROOT: 2 levels up → 3 levels up Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): use dot reporter for test:unit to reduce noise Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): switch test:unit reporter to tap Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): compact test reporter — silent on pass, failures + summary only Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): include shared/tests in test:coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct path depths in tests moved to integration/ Tests moved from tests/ to tests/integration/ need one extra ../ to reach the same source files. Also fix web component paths — those files live at web/ not src/web/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): fix web component paths in web-session-parity-contract Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): use process.cwd() for project root in docker-template test Resolving relative to __dirname breaks under test:coverage which runs source files directly from src/tests/ — needs ../.. not ../../.. (the extra level only exists in the compiled dist-test/ output). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: retrigger CI --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 16:51:49 -04:00
/**
* Recursively copy files from srcDir to destDir.
* Skips node_modules only. Copies everything: .ts/.tsx originals (for jiti),
* .mjs helpers, .md/.yaml/.json assets, etc.
* esbuild compiled .js output already lands in dist-test, so we just
* overlay the asset files on top.
*/
async function copyAssets(srcDir, destDir) {
2026-05-05 14:31:16 +02:00
let entries;
try {
entries = await readdir(srcDir, { withFileTypes: true });
} catch {
return; // directory doesn't exist, nothing to copy
}
for (const entry of entries) {
if (ASSET_SKIP_DIRS.has(entry.name)) continue;
const srcPath = join(srcDir, entry.name);
const destPath = join(destDir, entry.name);
if (entry.isDirectory()) {
await copyAssets(srcPath, destPath);
} else {
await mkdir(destDir, { recursive: true });
await cp(srcPath, destPath, { force: true });
}
}
perf(test): compile unit tests with esbuild, reclassify integration tests, fix node_modules symlink (#2809) * fix(test): wire src/resources/extensions/shared/tests/ into test:unit runner The test:unit glob excluded src/resources/extensions/shared/tests/ entirely, leaving format-utils.test.ts (and any future tests there) silently unfired. - Add shared/tests/*.test.ts to the test:unit glob in package.json - Export newestSrcMtime from ensure-workspace-builds.cjs (require.main guard prevents side-effects on require) so the staleness logic can be tested - Add src/tests/ensure-workspace-builds.test.ts covering newestSrcMtime: non-existent dir, no .ts files, single file, max of multiple, recursion, node_modules skip Closes #2808 * perf(test): compile unit tests with esbuild and fix dist-test/node_modules Replace per-file --experimental-strip-types with a single esbuild compilation step (scripts/compile-tests.mjs) that compiles all src/ TypeScript to dist-test/ in ~3s, then runs the pre-compiled JS. Eliminates ~1.7s Node startup overhead per test file. - scripts/compile-tests.mjs: esbuild compilation, asset copy, .ts→.js rewrite, stale file cleanup; creates dist-test/node_modules symlink so resource-loader.ts resolves gsdNodeModules to a real path (fixes node-modules-symlink test failure) - scripts/dist-test-resolve.mjs: ESM loader hook for @gsd/* bare specifiers and .ts→.js fallback rewriting at runtime - .gitignore: exclude dist-test/ from version control - package.json: add test:compile script; update test:unit to compile-then-run; update test:integration globs to cover new integration/ subdirectories - worker-registry.ts: unref() cleanup timer so it does not keep the Node process alive after tests complete Closes #2858 * fix(test): update relative imports in tests/integration/ after directory move When tests were moved from tests/ to tests/integration/ in the previous commit, relative imports weren't updated. ../foo now resolves one level too shallow. Fix all 117 import paths across 43 test files: - ../foo → ../../foo (source files at gsd/ level) - ../../get-secrets-from-user.ts → ../../../ (at extensions/ level) - ../../subagent/worker-registry.ts → ../../../ (at extensions/ level) - ./marketplace-test-fixtures.js → ../marketplace-test-fixtures.ts - ./test-helpers.ts → ../test-helpers.ts typecheck:extensions now passes with zero errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(integration): set 10-minute timeout for integration test runner build job takes ~7min on main. Without a global timeout, hanging tests block the suite indefinitely. --test-timeout=600000 caps each test at 10min. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Revert "test(integration): set 10-minute timeout for integration test runner" This reverts commit be77ead77d369ad8569292ae6b69ba56435f5433. * fix(test): correct formatDuration(0) edge case and docker test root path - formatDuration(0) now returns '0s' instead of '0ms' by guarding the sub-second branch with ms > 0 - docker-template.test.ts root path goes ../../.. from dist-test/src/tests/ to reach project root instead of landing in dist-test/ - replace require() calls in skill-health.ts and visualizer-overlay.ts with proper ES module imports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct relative import paths in integration tests All affected tests were one directory level off — importing from ../web/ and ../resources/ when the correct paths are ../../web/ and ../../resources/. Tests live at src/tests/integration/, not src/tests/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): add esbuild to root devDeps and wire dist-test-resolve hook P1: esbuild was only in web/package.json — compile-tests.mjs requires it at the root node_modules path, so CI failed on clean installs. P2: dist-test-resolve.mjs existed but was never loaded; @gsd/* imports in compiled tests resolved to installed workspace packages instead of freshly compiled dist-test output. Add --import to test:unit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(deps): align esbuild version with lock file (0.25.12) ^0.27.4 didn't satisfy the existing lock file entry. Use the version already present so npm ci passes without regenerating the lock file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct all relative import depths in src/tests/integration/ Tests in src/tests/integration/ need 3 levels up (../../..) to reach project-root dirs (web/, packages/) and 2 levels up (../..) to reach src-level dirs (src/web/, src/cli-web-branch.ts). Fixes: - ../../web/lib/ → ../../../web/lib/ (Next.js app, not src/web/) - ../../web/app/ → ../../../web/app/ - ../../packages/ → ../../../packages/ - ../cli-web-branch.ts → ../../cli-web-branch.ts - ../web-mode.ts → ../../web-mode.ts - ../resources/extensions/ → ../../resources/extensions/ - ci_monitor ROOT path: 2 levels up → 3 levels up - web-responsive WEB_ROOT: 2 levels up → 3 levels up Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): use dot reporter for test:unit to reduce noise Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): switch test:unit reporter to tap Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): compact test reporter — silent on pass, failures + summary only Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): include shared/tests in test:coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct path depths in tests moved to integration/ Tests moved from tests/ to tests/integration/ need one extra ../ to reach the same source files. Also fix web component paths — those files live at web/ not src/web/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): fix web component paths in web-session-parity-contract Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): use process.cwd() for project root in docker-template test Resolving relative to __dirname breaks under test:coverage which runs source files directly from src/tests/ — needs ../.. not ../../.. (the extra level only exists in the compiled dist-test/ output). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: retrigger CI --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 16:51:49 -04:00
}
async function main() {
2026-05-05 14:31:16 +02:00
const start = Date.now();
// Collect entry points from src/ and packages/*/src/
const srcFiles = await collectFiles(join(ROOT, "src"));
const packagesDir = join(ROOT, "packages");
const pkgEntries = await readdir(packagesDir, { withFileTypes: true });
const packageFiles = [];
for (const entry of pkgEntries) {
if (!entry.isDirectory()) continue;
const pkgSrc = join(packagesDir, entry.name, "src");
packageFiles.push(...(await collectFiles(pkgSrc)));
}
// Also compile web/lib/ — some tests import from ../../web/lib/
const webLibFiles = await collectFiles(join(ROOT, "web", "lib"));
const entryPoints = [...srcFiles, ...packageFiles, ...webLibFiles];
console.log(`Compiling ${entryPoints.length} files to dist-test/...`);
// bundle:false transforms TypeScript but keeps import specifiers verbatim.
// We post-process the output to rewrite .ts → .js in import strings.
await esbuild.build({
entryPoints,
outdir: join(ROOT, "dist-test"),
outbase: ROOT,
bundle: false,
format: "esm",
platform: "node",
target: "node24",
sourcemap: "inline",
packages: "external",
logLevel: "warning",
});
// Copy non-compiled assets from src/ to dist-test/src/ maintaining structure.
// Tests use import.meta.url to resolve sibling .md, .yaml, .json, .ts etc.
// Also copy original .ts files — jiti-based imports load .ts source directly.
const srcDir = join(ROOT, "src");
const distSrcDir = join(ROOT, "dist-test", "src");
await copyAssets(srcDir, distSrcDir);
console.log("Copied non-TS assets and .ts source files to dist-test/src/");
// Copy packages/*/src/ assets as well
for (const entry of pkgEntries) {
if (!entry.isDirectory()) continue;
const pkgSrc = join(packagesDir, entry.name, "src");
const pkgDistSrc = join(ROOT, "dist-test", "packages", entry.name, "src");
await copyAssets(pkgSrc, pkgDistSrc);
}
// Copy web/lib/ assets (tests import from ../../web/lib/ relative to dist-test/src/tests/)
await copyAssets(
join(ROOT, "web", "lib"),
join(ROOT, "dist-test", "web", "lib"),
);
// Copy web/components/ assets (xterm-theme test reads shell-terminal.tsx via import.meta.dirname)
await copyAssets(
join(ROOT, "web", "components"),
join(ROOT, "dist-test", "web", "components"),
);
// Copy scripts/ non-TS files (.cjs etc) — some tests require() scripts directly
await copyAssets(join(ROOT, "scripts"), join(ROOT, "dist-test", "scripts"));
// Copy root package.json — some tests read it to check version/engines fields
await cp(
join(ROOT, "package.json"),
join(ROOT, "dist-test", "package.json"),
{ force: true },
);
// Copy root dist/ into dist-test/dist/ — some tests compute projectRoot as
// 3 levels up from dist-test/src/tests/ which lands at dist-test/, then
2026-05-05 15:42:10 +02:00
// import from dist package entrypoints etc.
2026-05-05 14:31:16 +02:00
const rootDistDir = join(ROOT, "dist");
const distTestDistDir = join(ROOT, "dist-test", "dist");
await copyAssets(rootDistDir, distTestDistDir);
// Post-process: rewrite .ts import specifiers to .js in all compiled JS files.
// esbuild with bundle:false preserves original specifiers; Node can't load .ts.
const compiledJsFiles = await collectFiles(join(ROOT, "dist-test"), [".js"]);
// Regex matches .ts in from/import() strings but not sourceMappingURL comments
const tsImportRe = /(from\s+["'])(\.\.?\/[^"']*?)\.ts(["'])/g;
const tsDynImportRe = /(import\(["'])(\.\.?\/[^"']*?)\.ts(["'])\)/g;
let rewritten = 0;
await Promise.all(
compiledJsFiles.map(async (file) => {
const src = await readFile(file, "utf-8");
const out = src
.replace(tsImportRe, (_, a, b, c) => `${a}${b}.js${c}`)
.replace(tsDynImportRe, (_, a, b, c) => `${a}${b}.js${c})`);
if (out !== src) {
await writeFile(file, out, "utf-8");
rewritten++;
}
}),
);
if (rewritten > 0) {
console.log(`Rewrote .ts → .js imports in ${rewritten} files`);
}
// Remove stale compiled test files: dist-test entries whose source no longer exists
// in a non-integration source directory (e.g. test moved to integration/).
// Only cleans *.test.js and *.test.ts files to avoid touching non-test outputs.
const { rm } = await import("node:fs/promises");
const { existsSync } = await import("node:fs");
const testDirsToClean = [
[join(ROOT, "dist-test", "src", "tests"), join(ROOT, "src", "tests")],
[
join(ROOT, "dist-test", "src", "resources", "extensions", "sf", "tests"),
join(ROOT, "src", "resources", "extensions", "sf", "tests"),
],
];
let staleCleaned = 0;
for (const [distDir, srcDir] of testDirsToClean) {
let distEntries;
try {
distEntries = await readdir(distDir, { withFileTypes: true });
} catch {
continue;
}
for (const entry of distEntries) {
if (!entry.isFile()) continue;
if (!entry.name.match(/\.test\.(js|ts)$/)) continue;
const stem = entry.name.replace(/\.(js|ts)$/, "");
// Source could be .ts or .mjs (esbuild compiles both to .js)
const hasTsSrc = existsSync(join(srcDir, stem + ".ts"));
const hasMjsSrc = existsSync(join(srcDir, stem + ".mjs"));
if (!hasTsSrc && !hasMjsSrc) {
await rm(join(distDir, entry.name));
staleCleaned++;
}
}
}
if (staleCleaned > 0) {
console.log(
`Removed ${staleCleaned} stale compiled test files from dist-test/`,
);
}
// Ensure dist-test/node_modules exists so resource-loader.ts (which computes
// packageRoot from import.meta.url) resolves sfNodeModules to a real path.
// Without this, initResources creates dangling symlinks in test environments.
const distNodeModules = join(ROOT, "dist-test", "node_modules");
if (!existsSync(distNodeModules)) {
symlinkSync(join(ROOT, "node_modules"), distNodeModules);
}
const elapsed = ((Date.now() - start) / 1000).toFixed(2);
console.log(`Done in ${elapsed}s`);
perf(test): compile unit tests with esbuild, reclassify integration tests, fix node_modules symlink (#2809) * fix(test): wire src/resources/extensions/shared/tests/ into test:unit runner The test:unit glob excluded src/resources/extensions/shared/tests/ entirely, leaving format-utils.test.ts (and any future tests there) silently unfired. - Add shared/tests/*.test.ts to the test:unit glob in package.json - Export newestSrcMtime from ensure-workspace-builds.cjs (require.main guard prevents side-effects on require) so the staleness logic can be tested - Add src/tests/ensure-workspace-builds.test.ts covering newestSrcMtime: non-existent dir, no .ts files, single file, max of multiple, recursion, node_modules skip Closes #2808 * perf(test): compile unit tests with esbuild and fix dist-test/node_modules Replace per-file --experimental-strip-types with a single esbuild compilation step (scripts/compile-tests.mjs) that compiles all src/ TypeScript to dist-test/ in ~3s, then runs the pre-compiled JS. Eliminates ~1.7s Node startup overhead per test file. - scripts/compile-tests.mjs: esbuild compilation, asset copy, .ts→.js rewrite, stale file cleanup; creates dist-test/node_modules symlink so resource-loader.ts resolves gsdNodeModules to a real path (fixes node-modules-symlink test failure) - scripts/dist-test-resolve.mjs: ESM loader hook for @gsd/* bare specifiers and .ts→.js fallback rewriting at runtime - .gitignore: exclude dist-test/ from version control - package.json: add test:compile script; update test:unit to compile-then-run; update test:integration globs to cover new integration/ subdirectories - worker-registry.ts: unref() cleanup timer so it does not keep the Node process alive after tests complete Closes #2858 * fix(test): update relative imports in tests/integration/ after directory move When tests were moved from tests/ to tests/integration/ in the previous commit, relative imports weren't updated. ../foo now resolves one level too shallow. Fix all 117 import paths across 43 test files: - ../foo → ../../foo (source files at gsd/ level) - ../../get-secrets-from-user.ts → ../../../ (at extensions/ level) - ../../subagent/worker-registry.ts → ../../../ (at extensions/ level) - ./marketplace-test-fixtures.js → ../marketplace-test-fixtures.ts - ./test-helpers.ts → ../test-helpers.ts typecheck:extensions now passes with zero errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(integration): set 10-minute timeout for integration test runner build job takes ~7min on main. Without a global timeout, hanging tests block the suite indefinitely. --test-timeout=600000 caps each test at 10min. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Revert "test(integration): set 10-minute timeout for integration test runner" This reverts commit be77ead77d369ad8569292ae6b69ba56435f5433. * fix(test): correct formatDuration(0) edge case and docker test root path - formatDuration(0) now returns '0s' instead of '0ms' by guarding the sub-second branch with ms > 0 - docker-template.test.ts root path goes ../../.. from dist-test/src/tests/ to reach project root instead of landing in dist-test/ - replace require() calls in skill-health.ts and visualizer-overlay.ts with proper ES module imports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct relative import paths in integration tests All affected tests were one directory level off — importing from ../web/ and ../resources/ when the correct paths are ../../web/ and ../../resources/. Tests live at src/tests/integration/, not src/tests/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): add esbuild to root devDeps and wire dist-test-resolve hook P1: esbuild was only in web/package.json — compile-tests.mjs requires it at the root node_modules path, so CI failed on clean installs. P2: dist-test-resolve.mjs existed but was never loaded; @gsd/* imports in compiled tests resolved to installed workspace packages instead of freshly compiled dist-test output. Add --import to test:unit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(deps): align esbuild version with lock file (0.25.12) ^0.27.4 didn't satisfy the existing lock file entry. Use the version already present so npm ci passes without regenerating the lock file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct all relative import depths in src/tests/integration/ Tests in src/tests/integration/ need 3 levels up (../../..) to reach project-root dirs (web/, packages/) and 2 levels up (../..) to reach src-level dirs (src/web/, src/cli-web-branch.ts). Fixes: - ../../web/lib/ → ../../../web/lib/ (Next.js app, not src/web/) - ../../web/app/ → ../../../web/app/ - ../../packages/ → ../../../packages/ - ../cli-web-branch.ts → ../../cli-web-branch.ts - ../web-mode.ts → ../../web-mode.ts - ../resources/extensions/ → ../../resources/extensions/ - ci_monitor ROOT path: 2 levels up → 3 levels up - web-responsive WEB_ROOT: 2 levels up → 3 levels up Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): use dot reporter for test:unit to reduce noise Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): switch test:unit reporter to tap Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): compact test reporter — silent on pass, failures + summary only Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): include shared/tests in test:coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct path depths in tests moved to integration/ Tests moved from tests/ to tests/integration/ need one extra ../ to reach the same source files. Also fix web component paths — those files live at web/ not src/web/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): fix web component paths in web-session-parity-contract Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): use process.cwd() for project root in docker-template test Resolving relative to __dirname breaks under test:coverage which runs source files directly from src/tests/ — needs ../.. not ../../.. (the extra level only exists in the compiled dist-test/ output). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: retrigger CI --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 16:51:49 -04:00
}
2026-05-05 14:31:16 +02:00
main().catch((err) => {
console.error(err);
process.exit(1);
perf(test): compile unit tests with esbuild, reclassify integration tests, fix node_modules symlink (#2809) * fix(test): wire src/resources/extensions/shared/tests/ into test:unit runner The test:unit glob excluded src/resources/extensions/shared/tests/ entirely, leaving format-utils.test.ts (and any future tests there) silently unfired. - Add shared/tests/*.test.ts to the test:unit glob in package.json - Export newestSrcMtime from ensure-workspace-builds.cjs (require.main guard prevents side-effects on require) so the staleness logic can be tested - Add src/tests/ensure-workspace-builds.test.ts covering newestSrcMtime: non-existent dir, no .ts files, single file, max of multiple, recursion, node_modules skip Closes #2808 * perf(test): compile unit tests with esbuild and fix dist-test/node_modules Replace per-file --experimental-strip-types with a single esbuild compilation step (scripts/compile-tests.mjs) that compiles all src/ TypeScript to dist-test/ in ~3s, then runs the pre-compiled JS. Eliminates ~1.7s Node startup overhead per test file. - scripts/compile-tests.mjs: esbuild compilation, asset copy, .ts→.js rewrite, stale file cleanup; creates dist-test/node_modules symlink so resource-loader.ts resolves gsdNodeModules to a real path (fixes node-modules-symlink test failure) - scripts/dist-test-resolve.mjs: ESM loader hook for @gsd/* bare specifiers and .ts→.js fallback rewriting at runtime - .gitignore: exclude dist-test/ from version control - package.json: add test:compile script; update test:unit to compile-then-run; update test:integration globs to cover new integration/ subdirectories - worker-registry.ts: unref() cleanup timer so it does not keep the Node process alive after tests complete Closes #2858 * fix(test): update relative imports in tests/integration/ after directory move When tests were moved from tests/ to tests/integration/ in the previous commit, relative imports weren't updated. ../foo now resolves one level too shallow. Fix all 117 import paths across 43 test files: - ../foo → ../../foo (source files at gsd/ level) - ../../get-secrets-from-user.ts → ../../../ (at extensions/ level) - ../../subagent/worker-registry.ts → ../../../ (at extensions/ level) - ./marketplace-test-fixtures.js → ../marketplace-test-fixtures.ts - ./test-helpers.ts → ../test-helpers.ts typecheck:extensions now passes with zero errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(integration): set 10-minute timeout for integration test runner build job takes ~7min on main. Without a global timeout, hanging tests block the suite indefinitely. --test-timeout=600000 caps each test at 10min. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Revert "test(integration): set 10-minute timeout for integration test runner" This reverts commit be77ead77d369ad8569292ae6b69ba56435f5433. * fix(test): correct formatDuration(0) edge case and docker test root path - formatDuration(0) now returns '0s' instead of '0ms' by guarding the sub-second branch with ms > 0 - docker-template.test.ts root path goes ../../.. from dist-test/src/tests/ to reach project root instead of landing in dist-test/ - replace require() calls in skill-health.ts and visualizer-overlay.ts with proper ES module imports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct relative import paths in integration tests All affected tests were one directory level off — importing from ../web/ and ../resources/ when the correct paths are ../../web/ and ../../resources/. Tests live at src/tests/integration/, not src/tests/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): add esbuild to root devDeps and wire dist-test-resolve hook P1: esbuild was only in web/package.json — compile-tests.mjs requires it at the root node_modules path, so CI failed on clean installs. P2: dist-test-resolve.mjs existed but was never loaded; @gsd/* imports in compiled tests resolved to installed workspace packages instead of freshly compiled dist-test output. Add --import to test:unit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(deps): align esbuild version with lock file (0.25.12) ^0.27.4 didn't satisfy the existing lock file entry. Use the version already present so npm ci passes without regenerating the lock file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct all relative import depths in src/tests/integration/ Tests in src/tests/integration/ need 3 levels up (../../..) to reach project-root dirs (web/, packages/) and 2 levels up (../..) to reach src-level dirs (src/web/, src/cli-web-branch.ts). Fixes: - ../../web/lib/ → ../../../web/lib/ (Next.js app, not src/web/) - ../../web/app/ → ../../../web/app/ - ../../packages/ → ../../../packages/ - ../cli-web-branch.ts → ../../cli-web-branch.ts - ../web-mode.ts → ../../web-mode.ts - ../resources/extensions/ → ../../resources/extensions/ - ci_monitor ROOT path: 2 levels up → 3 levels up - web-responsive WEB_ROOT: 2 levels up → 3 levels up Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): use dot reporter for test:unit to reduce noise Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): switch test:unit reporter to tap Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): compact test reporter — silent on pass, failures + summary only Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(test): include shared/tests in test:coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): correct path depths in tests moved to integration/ Tests moved from tests/ to tests/integration/ need one extra ../ to reach the same source files. Also fix web component paths — those files live at web/ not src/web/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): fix web component paths in web-session-parity-contract Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): use process.cwd() for project root in docker-template test Resolving relative to __dirname breaks under test:coverage which runs source files directly from src/tests/ — needs ../.. not ../../.. (the extra level only exists in the compiled dist-test/ output). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: retrigger CI --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 16:51:49 -04:00
});