Repository navigation
Conversation
node:test semantics: a failing `todo` test (and a `skip` test, for consistency) doesn't fail the overall run. The `test:fail` handler was unconditionally setting process.exitCode=1 and recording the file in failedFiles, turning any todo-marked known failure into a red CI job. Dispatch-Task: integration-testing-todo-not-failure Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FRu37LkthRcNpozRAsiodp
…test
- data.todo/data.skip can be a falsy-but-present reason string (e.g. { todo: '' });
the || check treated that as a real failure. Match node's own CLI logic
(todo/skip !== undefined && !== false).
- The skip fixture used { skip: true }, which skips the body entirely and
never reaches the data.skip branch; drive it with t.skip() from inside
the body instead.
- runCli silently turned a signal-killed child into exit 0; assert no signal.
- Guard the after() hook against fixtureDir being unset if before() throws.
- Strip HARPER_INTEGRATION_TEST_* from the spawned CLI's env so an
inherited HARPER_INTEGRATION_TEST_SHARD/ONLY can't change file selection.
- Bound each test with an explicit timeout instead of an unbounded wait.
Found by the pre-push cross-model review (codex + gemini + cursor-composer).
Dispatch-Task: integration-testing-todo-not-failure
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRu37LkthRcNpozRAsiodp
- Wire each test's t.signal into runCli -> spawn, so an abort (the test
timeout, or a future node:test cancellation) sends SIGTERM to the
child instead of leaving it running and holding its process handle,
which was the one way these new timeouts could still hang npm test.
- Add a regression fixture for the exact edge case this fix closes:
a todo test with a falsy-but-present reason ({ todo: '' }).
- Trim two comments that spoke to this review round rather than the
next reader.
Found by round 2 of the pre-push cross-model review (codex + gemini).
Dispatch-Task: integration-testing-todo-not-failure
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FRu37LkthRcNpozRAsiodp
There was a problem hiding this comment.
Code Review
This pull request updates the test runner in src/run.ts to ensure that failing todo or skip tests do not cause the test run to fail, aligning with node:test semantics. It also introduces integration tests in test/run.test.ts to verify this behavior. Feedback suggests propagating process.execArgv when spawning the child process in tests to ensure any necessary Node.js flags or loaders are correctly applied.
kriszyp
marked this pull request as ready for review
October 8, 2026 15:36
Ethan-Arrowood
requested changes
Oct 8, 2026
node:test emits the todo/skip marker as `reason ?? true`, so the values a failing todo/skip test carries are `true` or the reason string, which can be empty. Accept exactly those, inline, instead of every non-undefined, non-false value (per review). Dispatch-Task: fix-kriszyp_integration-testing_41-da7fa633 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixture tests as real files instead of JS inside template strings, so they read and edit like any other test file (per review). Drops the mkdtemp/write/cleanup hooks they needed. Dispatch-Task: fix-kriszyp_integration-testing_41-da7fa633 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
⊙ Problem
harper-integration-test-run'stest:failhandler setsprocess.exitCode = 1and records the file infailedFilesfor every node:test failure, including tests markedtodoorskip. node:test's own semantics are that a failingtodo/skiptest doesn't fail the run, so a deliberately-failingtodotest (used to track a known issue without blocking CI) turns the whole run red — exactly the case thetodomarker exists to avoid.💡 Solution
The
test:failhandler now returns early for a todo/skip failure, before it setsprocess.exitCodeor adds the file tofailedFiles. node:test emits the marker asreason ?? true(same code on Node 22, 24 and 26), so a failing todo/skip test carriestrueor the reason string, which can be empty. The guard accepts exactly those:data.todo || data.todo === '' || data.skip || data.skip === ''. A real failure is unaffected: eachtest:failevent is handled independently, so a todo/skip test can never suppress a later real failure'sexitCode = 1.⚖️ Alternatives
process.exitCodefrom the finaltest:summaryevent'ssuccessfield.failedFileswould still need the per-event handler, so the switch would not shrink the change. Reversible if node ever adds another non-failing failure kind.failedFiles, so its Harperhdb.logtail is not printed either. Low stakes: it only affects diagnosing a known-broken todo test.--isolation=noneonly. The production default (processisolation) is covered by code trace: the guard does not branch on isolation mode, and node setstodo/skipon the event the same way in either mode.🔧 Changes
src/run.ts— thetest:failguard described above.test/run.test.ts(new) — spawns the real CLI under--isolation=noneagainst each fixture and checks the exit code.runClipasses each test'st.signalto the child, so a timeout kills it instead of leaking it, and fails if the child died from a signal. It also stripsHARPER_INTEGRATION_TEST_*from the child's env, so an exported shard/only setting cannot change which fixture runs.test/fixtures/run/(new) — one failing test per file, named without.test.so thenpm testglob does not run them as suites:todo-fail.ts—{ todo: true }.skip-fail.ts— callst.skip()inside the body. The{ skip: true }option would skip the body, so the test would never fail and never reach thedata.skipbranch.empty-reason-todo-fail.ts—{ todo: '' }.real-fail.ts— the control: an unmarked failure.✅ Verification
npm run check(tsc) andnpm run build— clean.npm test— 68 tests, 0 failures; the 4 new cases pass.src/run.tsfromorigin/main, the todo, skip and empty-reason cases fail (exit 1) and the real-failure control still passes.''clauses fails only the empty-reason case; removing the skip clauses fails only the skip case.324c7f6: all jobs green (ubuntu/macOS/Windows × Node 22/24/26, plus commitlint).🤖 Generated by Claude Sonnet 5, review updates by Claude Opus 5.5; posted via @kriszyp.
Dispatch-Task: integration-testing-todo-not-failure
Related PRs: none found
Complexity: easy
Origin — the dispatch brief this PR was written from
Runner: a failing {todo} test must not fail the run
In
src/run.ts(~:127) of HarperFast/integration-testing, thetest:failhandler setsprocess.exitCode = 1and adds the file tofailedFilesfor every failure, including tests marked{ todo }. node:test semantics are that a failing todo test does not fail the run, so theharper-integration-test-runCLI turns any todo-marked known failure into a red CI job. Fix: skip both the exitCode assignment andfailedFiles.addwhendata.todois set (also checkdata.skiphandling for consistency). Add a self-test with a deliberately failing{ todo }assertion that asserts the run exits 0, and a control with a real failure that exits 1. Bump the patch version per the repo's release convention.Acceptance
A suite whose only failure is a todo test exits 0; a real failure still exits 1.
Dispatch: task
integration-testing-todo-not-failure· queued by finding-triage/wave-29 · ran by claude/sonnet/xhigh · worker kzyp-xps-1Review-Coverage: authored=claude; ran=cursor-composer,gemini,codex; adjudicated=domain; declined=cursor-grok,cursor-kimi,cursor-muse; rounds=5; full=3 @ 324c7f6
Review-Attention: skim ~2m (decisions: marker-predicate, exit-status-source, self-test-isolation) @ 324c7f6