* 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>
99 lines
2.8 KiB
TypeScript
99 lines
2.8 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { tmpdir } from "node:os";
|
|
import { pathToFileURL } from "node:url";
|
|
|
|
const { resolveGsdCliEntry } = await import("../../web/cli-entry.ts");
|
|
|
|
function makeFixture(paths: string[]): string {
|
|
const root = mkdtempSync(join(tmpdir(), "gsd-cli-entry-"));
|
|
for (const relativePath of paths) {
|
|
const fullPath = join(root, relativePath);
|
|
mkdirSync(join(fullPath, ".."), { recursive: true });
|
|
writeFileSync(fullPath, "// fixture\n");
|
|
}
|
|
return root;
|
|
}
|
|
|
|
test("resolveGsdCliEntry prefers the built loader for packaged standalone interactive sessions", (t) => {
|
|
const packageRoot = makeFixture([
|
|
"dist/loader.js",
|
|
"src/loader.ts",
|
|
"src/resources/extensions/gsd/tests/resolve-ts.mjs",
|
|
]);
|
|
|
|
t.after(() => { rmSync(packageRoot, { recursive: true, force: true }); });
|
|
|
|
const entry = resolveGsdCliEntry({
|
|
packageRoot,
|
|
cwd: "/tmp/project-a",
|
|
execPath: "/custom/node",
|
|
hostKind: "packaged-standalone",
|
|
mode: "interactive",
|
|
});
|
|
|
|
assert.deepEqual(entry, {
|
|
command: "/custom/node",
|
|
args: [join(packageRoot, "dist", "loader.js")],
|
|
cwd: "/tmp/project-a",
|
|
});
|
|
});
|
|
|
|
test("resolveGsdCliEntry prefers the source loader for source-dev interactive sessions", (t) => {
|
|
const packageRoot = makeFixture([
|
|
"dist/loader.js",
|
|
"src/loader.ts",
|
|
"src/resources/extensions/gsd/tests/resolve-ts.mjs",
|
|
]);
|
|
|
|
t.after(() => { rmSync(packageRoot, { recursive: true, force: true }); });
|
|
|
|
const entry = resolveGsdCliEntry({
|
|
packageRoot,
|
|
cwd: "/tmp/project-b",
|
|
execPath: "/custom/node",
|
|
hostKind: "source-dev",
|
|
mode: "interactive",
|
|
});
|
|
|
|
assert.deepEqual(entry, {
|
|
command: "/custom/node",
|
|
args: [
|
|
"--import",
|
|
pathToFileURL(join(packageRoot, "src", "resources", "extensions", "gsd", "tests", "resolve-ts.mjs")).href,
|
|
"--experimental-strip-types",
|
|
join(packageRoot, "src", "loader.ts"),
|
|
],
|
|
cwd: "/tmp/project-b",
|
|
});
|
|
});
|
|
|
|
test("resolveGsdCliEntry appends rpc arguments for bridge sessions", (t) => {
|
|
const packageRoot = makeFixture(["dist/loader.js"]);
|
|
|
|
t.after(() => { rmSync(packageRoot, { recursive: true, force: true }); });
|
|
|
|
const entry = resolveGsdCliEntry({
|
|
packageRoot,
|
|
cwd: "/tmp/project-c",
|
|
execPath: "/custom/node",
|
|
hostKind: "packaged-standalone",
|
|
mode: "rpc",
|
|
sessionDir: "/tmp/.gsd/sessions/project-c",
|
|
});
|
|
|
|
assert.deepEqual(entry, {
|
|
command: "/custom/node",
|
|
args: [
|
|
join(packageRoot, "dist", "loader.js"),
|
|
"--mode",
|
|
"rpc",
|
|
"--continue",
|
|
"--session-dir",
|
|
"/tmp/.gsd/sessions/project-c",
|
|
],
|
|
cwd: "/tmp/project-c",
|
|
});
|
|
});
|