test: integration tests for hook entry points (GIT-58)#27
Conversation
Add end-to-end integration tests exercising hooks as child processes against real temp git repos: - session-start: stdout with memories, stderr summary, empty store graceful - session-stop: capture via liberate pipeline, summary output - prompt-submit: context surfacing when enabled, silent when disabled - init-hooks: file creation, correct schemas, remove cleanup, preserves other tools' hooks Shared helpers use tsx binary to support cwd in temp directories. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds integration test helpers and four end-to-end test suites for git-mem hooks (init-hooks, prompt-submit, session-start, session-stop). The helpers create and manage temporary git repos, run the CLI/hook entrypoints, and assert outputs and repository state. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@tests/integration/hooks/helpers.ts`:
- Around line 8-9: Consolidate the two separate imports from 'child_process'
into a single import statement: replace the two lines importing spawnSync and
execFileSync separately with one combined import that imports both spawnSync and
execFileSync from 'child_process' (target the existing import declarations for
spawnSync and execFileSync in tests/integration/hooks/helpers.ts).
- Around line 96-97: The current shallow merge at the config creation line
(using defaults, overrides, and hooks: { ...defaults.hooks, ...overrides })
replaces nested hook objects (e.g., sessionStart) and loses inner properties
like memoryLimit; change this to a deep merge for hooks so nested properties are
preserved — either call a deep-merge utility (e.g., lodash.merge) or add a small
recursive merge helper and use hooks: mergeDeep(defaults.hooks, overrides),
keeping the top-level defaults merging logic intact (referencing the variables
config, defaults, overrides and the hooks/sessionStart objects).
In `@tests/integration/hooks/hook-init-hooks.test.ts`:
- Around line 37-57: This test depends on settings.json created by a previous
spec and can flake if run alone; modify the test in hook-init-hooks.test.ts to
ensure idempotency by creating or initializing the settings before asserting:
check for settingsPath (join(workDir, '.claude', 'settings.json')) and if
missing call the same setup helper or CLI init used by the earlier test (the
helper or command that creates .claude/settings.json—use the existing setup
function or test titled "should create .claude/settings.json and .git-mem.json"
or its underlying initializer), then read and assert the hooks as currently
written so the test can run independently.
In `@tests/integration/hooks/hook-prompt-submit.test.ts`:
- Around line 44-53: The test manually writes a full .git-mem.json instead of
using the writeGitMemConfig helper; update
tests/integration/hooks/hook-prompt-submit.test.ts to call
writeGitMemConfig(repoDir, { promptSubmit: { enabled: true, recordPrompts:
false, surfaceContext: true } }) (and the similar call for the other case around
lines 93-101) and remove the manual JSON write; also fix writeGitMemConfig to
deep-merge nested hook objects (instead of the current shallow merge) so that
passing an overrides object like { promptSubmit: {...} } merges into existing
hooks.sessionStart/sessionStop defaults correctly.
There was a problem hiding this comment.
Pull request overview
Adds end-to-end integration coverage for git-mem’s Claude Code hook entry points by running the real CLI against temporary git repositories, validating stdout/stderr behavior and init-hooks install/remove semantics.
Changes:
- Adds integration tests for
git-mem hook session-start,session-stop, andprompt-submitexecuted via child processes. - Adds integration tests for
git-mem init-hooks --yesand--remove, including preservation of non–git-mem hooks in.claude/settings.json. - Introduces shared integration helpers for creating temp repos, writing config, and spawning the CLI.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/integration/hooks/helpers.ts | Shared utilities to create temp repos/config and spawn the CLI/hooks for integration tests. |
| tests/integration/hooks/hook-session-start.test.ts | Verifies session-start hook behavior with/without stored memories (stdout/stderr + exit code). |
| tests/integration/hooks/hook-session-stop.test.ts | Verifies session-stop hook runs end-to-end against a real repo and produces expected outputs. |
| tests/integration/hooks/hook-prompt-submit.test.ts | Verifies prompt-submit surfaces context when enabled and is silent when disabled. |
| tests/integration/hooks/hook-init-hooks.test.ts | Verifies init-hooks install/remove behavior and preserving other tools’ hooks. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const PROJECT_ROOT = resolve(__dirname, '../../..'); | ||
| const CLI_PATH = resolve(PROJECT_ROOT, 'src/cli.ts'); | ||
|
|
||
| // Use tsx binary from project node_modules — works even when cwd is a temp dir | ||
| const TSX_BIN = resolve(PROJECT_ROOT, 'node_modules/.bin/tsx'); | ||
|
|
There was a problem hiding this comment.
TSX_BIN is hard-coded to node_modules/.bin/tsx, which is not portable (e.g. Windows uses tsx.cmd, and some environments won’t have an executable file at that path). Consider invoking the CLI via process.execPath with --import tsx (matching the repo’s test scripts) or resolving the tsx entrypoint via Node resolution so integration tests run reliably across platforms/environments.
There was a problem hiding this comment.
Acknowledged — this is a macOS/Linux-only CLI tool at the moment (git notes backend). The tsx binary approach was chosen because node --import tsx doesn't resolve when cwd is a temp directory outside the project root. If Windows support is needed later we can switch to process.execPath with a loader, but for now the binary path works reliably in CI and local dev.
…helper (GIT-58) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@tests/integration/hooks/helpers.ts`:
- Around line 25-38: The runHook helper currently ignores a provided cwd in its
JSON input, so update runHook to read a cwd string (e.g., const { cwd } = input
or input.cwd) and pass it into the spawnSync options (alongside input, encoding,
timeout) so the spawned process runs in the intended working directory; locate
the runHook function that calls spawnSync with TSX_BIN and CLI_PATH and add the
cwd option only when it is a valid string to avoid changing behavior when not
provided.
In `@tests/integration/hooks/hook-prompt-submit.test.ts`:
- Around line 51-63: The test "should return context in stdout" uses runHook and
currently asserts that result.stdout includes any of "validate", "input", or
"security", which is flaky; update the assertion to check for a deterministic
indicator instead (for example a known memory snippet or a stable marker
inserted by the test fixture such as a specific sentence fragment or tag), by
replacing the loose includes(...) checks on result.stdout with a single assert
that result.stdout.includes('<expected memory fragment or marker>') so the test
reliably verifies the returned context from runHook('prompt-submit', ...).
Summary
git-mem hook session-start/stop/prompt-submitas child processes viaspawnSyncgit-mem init-hooks --yesand--removefor file creation/cleanuphelpers.ts) for running CLI, creating test repos, and config setupCloses GIT-58
Test plan
node --import tsx --test tests/integration/hooks/hook-session-start.test.ts— 4 passnode --import tsx --test tests/integration/hooks/hook-session-stop.test.ts— 3 passnode --import tsx --test tests/integration/hooks/hook-prompt-submit.test.ts— 3 passnode --import tsx --test tests/integration/hooks/hook-init-hooks.test.ts— 6 passnpm run pre-commit— type-check + lint clean🤖 Generated with Claude Code
Summary by CodeRabbit