diff --git a/src/repo2rlenv/pipelines/pr_runtime.py b/src/repo2rlenv/pipelines/pr_runtime.py index e0546447..5ce31917 100644 --- a/src/repo2rlenv/pipelines/pr_runtime.py +++ b/src/repo2rlenv/pipelines/pr_runtime.py @@ -640,9 +640,12 @@ def normalize_test_cmds_for_runtime(test_cmds: list[str]) -> list[str]: - Default output is already parseable; no transform needed cargo nextest run: - Add `--status-level pass` (or raise a lower one) and `--color never` - jest / mocha / npm test: + jest / npm test: - Add `--verbose` if not present, so per-test ✓/✕ lines are emitted - Some configs swallow stdout via `--silent`; we strip that + mocha: + - Use `--reporter spec` instead: mocha has no `--verbose` option and + reads the next word as its value, dropping a test file appended later vitest: - Use `--reporter=verbose` instead: vitest rejects `--verbose`, and its default reporter collapses fully passing files to one summary line @@ -721,7 +724,13 @@ def normalize_test_cmds_for_runtime(test_cmds: list[str]) -> list[str]: cleaned = re.sub(r"\s+--verbose\b", "", cleaned) if not re.search(r"\s--reporter\b", cleaned): cleaned = cleaned.rstrip() + " --reporter=verbose" - elif re.search(r"\b(?:jest|mocha)\b", cleaned) and not re.search( + elif re.search(r"\bmocha\b", cleaned): + # mocha has no `--verbose`: it reads the next word as the flag's + # value, which swallows a test file appended after it. + cleaned = re.sub(r"\s+--verbose\b", "", cleaned) + if not re.search(r"\s(?:--reporter|-R)\b", cleaned): + cleaned = cleaned.rstrip() + " --reporter spec" + elif re.search(r"\bjest\b", cleaned) and not re.search( r"\s--verbose\b|\s--reporter\b", cleaned ): cleaned = cleaned.rstrip() + " --verbose" diff --git a/tests/test_pipeline_pr_runtime.py b/tests/test_pipeline_pr_runtime.py index e877ee0d..4986f602 100644 --- a/tests/test_pipeline_pr_runtime.py +++ b/tests/test_pipeline_pr_runtime.py @@ -562,7 +562,25 @@ def test_normalize_vitest_uses_verbose_reporter(): assert normalize_test_cmds_for_runtime(["vitest run --reporter=junit"]) == [ "vitest run --reporter=junit" ] - assert normalize_test_cmds_for_runtime(["npx mocha"]) == ["npx mocha --verbose"] + + +def test_normalize_mocha_uses_spec_reporter(): + # mocha has no `--verbose`, so `mocha --verbose a.spec.js` reads the file + # as the flag's value and never runs it. + assert normalize_test_cmds_for_runtime(["npx mocha"]) == ["npx mocha --reporter spec"] + assert normalize_test_cmds_for_runtime(["mocha --verbose --silent"]) == [ + "mocha --reporter spec" + ] + # An explicit reporter is the repo's choice ⇒ keep + assert normalize_test_cmds_for_runtime(["mocha -R dot"]) == ["mocha -R dot"] + assert normalize_test_cmds_for_runtime(["mocha --reporter=tap"]) == ["mocha --reporter=tap"] + + +def test_targeted_mocha_keeps_every_test_file(): + cmds = targeted_test_cmds_for_pr( + normalize_test_cmds_for_runtime(["npx mocha"]), ["test/a.spec.js", "test/b.spec.js"] + ) + assert cmds == ["npx mocha --reporter spec test/a.spec.js test/b.spec.js"] def test_normalize_strips_trailing_pipe_head_or_tail():