From c46a116fca7756cc1fd9213c5d6588fd5668a277 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sun, 29 Mar 2026 08:43:08 -0500 Subject: [PATCH] test(commands): add GSDNoProjectError handling tests Verify GSDNoProjectError is thrown for blocked directories and the dispatcher catches it with a friendly cd suggestion. --- .../gsd/tests/gsd-no-project-error.test.ts | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts diff --git a/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts b/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts new file mode 100644 index 000000000..1ceaa5f2d --- /dev/null +++ b/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts @@ -0,0 +1,73 @@ +/** + * GSDNoProjectError — tests for friendly home-directory error handling. + * + * Verifies that GSDNoProjectError is thrown for blocked directories and + * that the dispatcher catches it with a user-friendly message. + */ + +import test from "node:test"; +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import { join, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +const contextSrc = readFileSync(join(__dirname, "..", "commands", "context.ts"), "utf-8"); +const dispatcherSrc = readFileSync(join(__dirname, "..", "commands", "dispatcher.ts"), "utf-8"); + +// ─── GSDNoProjectError class ────────────────────────────────────────────── + +test("GSDNoProjectError class is exported from context.ts", () => { + assert.ok( + contextSrc.includes("export class GSDNoProjectError extends Error"), + "GSDNoProjectError should be an exported Error subclass", + ); +}); + +test("GSDNoProjectError sets name property", () => { + assert.ok( + contextSrc.includes('this.name = "GSDNoProjectError"'), + "GSDNoProjectError should set its name for instanceof checks", + ); +}); + +// ─── projectRoot blocked directory handling ─────────────────────────────── + +test("projectRoot uses validateDirectory and checks for blocked severity", () => { + assert.ok( + contextSrc.includes("validateDirectory(pathToCheck)"), + "projectRoot should call validateDirectory", + ); + assert.ok( + contextSrc.includes('result.severity === "blocked"'), + "projectRoot should check for blocked severity", + ); +}); + +test("projectRoot throws GSDNoProjectError on blocked directory", () => { + assert.ok( + contextSrc.includes("throw new GSDNoProjectError"), + "projectRoot should throw GSDNoProjectError when directory is blocked", + ); +}); + +// ─── Dispatcher catch ───────────────────────────────────────────────────── + +test("dispatcher catches GSDNoProjectError with user-friendly message", () => { + assert.ok( + dispatcherSrc.includes("err instanceof GSDNoProjectError"), + "dispatcher should catch GSDNoProjectError specifically", + ); + assert.ok( + dispatcherSrc.includes("cd"), + "error message should suggest cd-ing into a project directory", + ); +}); + +test("dispatcher re-throws non-GSDNoProjectError exceptions", () => { + assert.ok( + dispatcherSrc.includes("throw err"), + "dispatcher should re-throw unexpected errors", + ); +});