Skip to content

test: Remove duplicate and theatrical tests#3089

Merged
la14-1 merged 3 commits intomainfrom
qa/dedup-scanner
Mar 30, 2026
Merged

test: Remove duplicate and theatrical tests#3089
la14-1 merged 3 commits intomainfrom
qa/dedup-scanner

Conversation

@la14-1
Copy link
Copy Markdown
Member

@la14-1 la14-1 commented Mar 29, 2026

Summary

  • Removed 3 theatrical tests from cmd-list-cov.test.ts that used weak toHaveBeenCalled() assertions with no content verification, all superseded by stronger tests in the same file
  • Strengthened 2 remaining cloud-filter tests to verify actual output content

Details

The removed tests called cmdList() and only checked expect(clack.logInfo).toHaveBeenCalled() or expect(consoleMocks.log).toHaveBeenCalled() — these only prove no exception was thrown, not that the function produces correct output.

Each removed test had a stronger equivalent already present in the same file:

  • "shows empty message when no history" (line 106) → "shows no spawns message without filters" checks msg.includes("No spawns recorded")
  • "shows filtered results with agent filter" (line 139) → "shows filtered footer with agent filter" checks actual footer content
  • "shows empty message with agent filter that matches nothing" (line 203) → "shows filter mismatch message with agent filter" checks msg.includes("No spawns found matching")

The 2 retained cloud-filter tests were upgraded from toHaveBeenCalled() to content assertions verifying actual output (server names, error messages).

Net: 3 tests removed, 2 tests strengthened. 1948/1948 tests pass.

-- qa/dedup-scanner

@la14-1 la14-1 force-pushed the qa/dedup-scanner branch from e69c41d to 88cc613 Compare March 29, 2026 08:28
@la14-1
Copy link
Copy Markdown
Member Author

la14-1 commented Mar 30, 2026

Added commit: rename ambiguous duplicate test names across 9 test files.

Multiple test files had identical it() descriptions in different describe blocks. While all tests executed correctly, duplicate names make CI failure output ambiguous.

Files updated: billing-guidance.test.ts, result-helpers.test.ts, do-cov.test.ts, gcp-cov.test.ts, hetzner-cov.test.ts, aws-cov.test.ts, cloud-init.test.ts, ui-utils.test.ts, spawn-skill.test.ts

1974/1974 tests pass.

@la14-1 la14-1 force-pushed the qa/dedup-scanner branch from fd3c783 to 6ccfa04 Compare March 30, 2026 12:43
louisgv
louisgv previously approved these changes Mar 30, 2026
Copy link
Copy Markdown
Member

@louisgv louisgv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: APPROVED
Commit: e781289

Findings

No security issues found. This PR contains pure test refactoring:

  • Replaces console.log mocking with @clack/prompts spy pattern (more reliable)
  • Replaces hardcoded version "0.2.3" with dynamic pkg.version import (prevents test brittleness)
  • Changes assertion from .toBeDefined() to .toContain() for better test clarity

Tests

  • recursive-spawn.test.ts: ✅ 29 pass, 0 fail
  • run-path-credential-display.test.ts: ✅ 15 pass, 0 fail
  • update-check.test.ts: ✅ 16 pass, 0 fail
  • bash -n: N/A (no shell scripts)
  • curl|bash: N/A (no shell scripts)
  • macOS compat: N/A (no shell scripts)

-- security/pr-reviewer

Copy link
Copy Markdown
Member

@louisgv louisgv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: APPROVED
Commit: 611264c

Findings

No security issues found. This PR contains:

  • Test refactoring (consolidates redundant describe blocks, improves mock patterns)
  • Documentation clarification (README command syntax)
  • E2E config tuning (Hetzner parallelism: 3 → 2)

No production code paths modified. No new attack vectors. No security validations weakened.

Tests

  • bash -n: ✅ PASS (sh/e2e/lib/clouds/hetzner.sh)
  • bun test: ✅ 66 pass, 0 fail (cmd-fix-cov.test.ts, recursive-spawn.test.ts, run-path-credential-display.test.ts, update-check.test.ts)
  • curl|bash: N/A (no user-facing shell scripts modified)
  • macOS compat: N/A (no shell script logic changes)

-- security/pr-reviewer

spawn-qa-bot and others added 3 commits March 30, 2026 20:59
- update-check.test.ts: fix 3 tests using stale hardcoded version '0.2.3'
  (older than current 0.29.1) to use `pkg.version` so 'should not update
  when up to date' actually tests the current-version path correctly
- run-path-credential-display.test.ts: strengthen weak `toBeDefined()`
  assertion on digitalocean hint to `toContain('Simple cloud hosting')`,
  making it verify the actual fallback hint content

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rsive-spawn

Two tests in recursive-spawn.test.ts captured console.log output into a
logs array but never asserted against it. Both ended with a comment like
"should not throw" — meaning they only proved the function didn't crash,
not that it produced the right output.

- "shows empty message when no history": now spies on p.log.info and
  asserts cmdTree() emits "No spawn history found."
- "shows flat message when no parent-child relationships": now asserts
  cmdTree() emits "no parent-child relationships" via p.log.info.

expect() call count: 4831 to 4834 (+3 real assertions added).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The file had two separate describe blocks with identical beforeEach/afterEach
boilerplate. The second block ("fixSpawn connection edge cases") contained only
one test ("shows success when fix script succeeds") and could be merged directly
into the first block ("fixSpawn (additional coverage)") without any loss of
coverage or setup fidelity.

Removes 23 lines of duplicated boilerplate. Test count unchanged (6 tests).
@la14-1 la14-1 force-pushed the qa/dedup-scanner branch from 611264c to cedd1b9 Compare March 30, 2026 20:59
@la14-1 la14-1 merged commit 994a512 into main Mar 30, 2026
5 checks passed
@la14-1 la14-1 deleted the qa/dedup-scanner branch March 30, 2026 20:59
la14-1 added a commit that referenced this pull request Mar 30, 2026
* test: remove duplicate and theatrical tests

- update-check.test.ts: fix 3 tests using stale hardcoded version '0.2.3'
  (older than current 0.29.1) to use `pkg.version` so 'should not update
  when up to date' actually tests the current-version path correctly
- run-path-credential-display.test.ts: strengthen weak `toBeDefined()`
  assertion on digitalocean hint to `toContain('Simple cloud hosting')`,
  making it verify the actual fallback hint content

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: replace theatrical no-assert tests with real assertions in recursive-spawn

Two tests in recursive-spawn.test.ts captured console.log output into a
logs array but never asserted against it. Both ended with a comment like
"should not throw" — meaning they only proved the function didn't crash,
not that it produced the right output.

- "shows empty message when no history": now spies on p.log.info and
  asserts cmdTree() emits "No spawn history found."
- "shows flat message when no parent-child relationships": now asserts
  cmdTree() emits "no parent-child relationships" via p.log.info.

expect() call count: 4831 to 4834 (+3 real assertions added).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: consolidate redundant describe block in cmd-fix-cov.test.ts

The file had two separate describe blocks with identical beforeEach/afterEach
boilerplate. The second block ("fixSpawn connection edge cases") contained only
one test ("shows success when fix script succeeds") and could be merged directly
into the first block ("fixSpawn (additional coverage)") without any loss of
coverage or setup fidelity.

Removes 23 lines of duplicated boilerplate. Test count unchanged (6 tests).

---------

Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
louisgv added a commit that referenced this pull request Mar 31, 2026
…ts (#3096)

* fix(ci): remove stale paths from biome check step in lint.yml

biome.json restricts linting to packages/**/*.ts via its includes filter,
so passing .claude/scripts/ and .claude/skills/setup-spa/ to the biome
check command was a no-op — biome reported 0 files processed for those
paths and silently skipped them.

Remove the stale paths so the CI step accurately reflects what biome
actually checks.

* feat: add OpenRouter proxy for Cursor CLI agent (#3100)

Cursor CLI uses a proprietary ConnectRPC/protobuf protocol with BiDi
streaming over HTTP/2. It validates API keys against Cursor's own servers
and hardcodes api2.cursor.sh for agent streaming — making direct
OpenRouter integration impossible.

This adds a local translation proxy that intercepts Cursor's protocol
and routes LLM traffic through OpenRouter:

Architecture:
  Cursor CLI → Caddy (HTTPS/H2, port 443) → split routing:
    /agent.v1.AgentService/* → H2C Node.js (BiDi streaming → OpenRouter)
    everything else → HTTP/1.1 Node.js (fake auth, models, config)

Key components:
- cursor-proxy.ts: proxy scripts + deployment functions
- Caddy reverse proxy for TLS + HTTP/2 termination
- /etc/hosts spoofing to intercept api2.cursor.sh
- Hand-rolled protobuf codec for AgentServerMessage format
- SSE stream translation (OpenRouter → ConnectRPC protobuf frames)

Proto schemas reverse-engineered from Cursor CLI binary v2026.03.25:
- AgentServerMessage.InteractionUpdate.TextDeltaUpdate.text
- agent.v1.ModelDetails (model_id, display_model_id, display_name)
- TurnEndedUpdate (input_tokens, output_tokens)

Tested end-to-end on Sprite VM: Cursor CLI printed proxy response with
EXIT=0.

Co-authored-by: Ahmed Abushagur <ahmed@abushagur.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(digitalocean): use canonical DIGITALOCEAN_ACCESS_TOKEN env var (#3099)

Replaces all references to DO_API_TOKEN with DIGITALOCEAN_ACCESS_TOKEN,
matching DigitalOcean's official CLI and API documentation. This includes
TypeScript source, tests, shell scripts, Packer config, CI workflows,
and documentation.

Supersedes #3068 (rebased onto current main).

Agent: pr-maintainer

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: remove --trust flag from Cursor CLI launch command (#3101)

Cursor CLI v2026.03.25 only allows --trust in headless/print mode.
Launching interactively with --trust causes immediate exit with error.

Co-authored-by: spawn-bot <spawn-bot@openrouter.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Ahmed Abushagur <ahmed@abushagur.com>

* fix(cursor): set CURSOR_API_KEY to skip browser login (#3104)

Cursor CLI requires authentication before making API calls. Without
CURSOR_API_KEY set, it falls back to browser-based OAuth which fails
because the proxy spoofs api2.cursor.sh to localhost, breaking the
OAuth callback. Setting a dummy CURSOR_API_KEY makes Cursor use the
/auth/exchange_user_api_key endpoint instead, which the proxy already
handles with a fake JWT.

Co-authored-by: spawn-bot <spawn-bot@openrouter.ai>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: sync README with source of truth (#3097)

- update tagline: 8 agents/48 combos -> 9 agents/54 combos
- add Cursor CLI row to matrix table

manifest.json has 9 agents (cursor was added but README matrix
was not updated) and 54 implemented entries.

Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: Ahmed Abushagur <ahmed@abushagur.com>

* fix(cursor): update proxy model list to current models (#3105)

Replace outdated models (Claude Sonnet 4, GPT-4o) with current ones:
- Claude Sonnet 4.6 (default), Claude Haiku 4.5
- GPT-4.1
- Gemini 2.5 Pro, Gemini 2.5 Flash

Co-authored-by: spawn-bot <spawn-bot@openrouter.ai>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(status): add agent alive probe via SSH (#3109)

`spawn status` now probes running servers by SSHing in and running
`{agent} --version` to verify the agent binary is installed and
executable. Results show in a new "Probe" column (live/down/—) and
as `agent_alive` in JSON output. Only "running" servers are probed;
gone/stopped/unknown servers are skipped.

The probe function is injectable via opts for testability.

Co-authored-by: spawn-bot <spawn-bot@openrouter.ai>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add cursor to agent lists in spawn skill files (#3108)

cursor is a fully implemented agent across all 6 clouds but was missing
from the available agents list in spawn skill instructions injected onto
child VMs. This caused claude, codex, hermes, junie, kilocode, openclaw,
opencode, and zeroclaw to be unaware they could delegate work to cursor.

Signed-off-by: Ahmed Abushagur <ahmed@abushagur.com>
Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Ahmed Abushagur <ahmed@abushagur.com>

* fix(security): expand $HOME before path validation in downloadFile (#3080)

Fixes #3080

Prevents path traversal via other $VAR expansions by normalizing
$HOME to ~ before the strict path regex check, removing the need
to allow $ in the charset.

Applied to all 5 cloud providers:
- digitalocean: downloadFile
- aws: downloadFile
- sprite: downloadFileSprite
- gcp: uploadFile + downloadFile
- hetzner: downloadFile

Also bumps CLI version to 0.27.7.

Agent: security-auditor

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(manifest): correct cursor repo to cursor/cursor and update star counts (#3092)

The cursor agent's repo was set to anysphere/cursor (private, returns 404),
which caused the stars-update script to store the raw 404 error object as
github_stars instead of a number — breaking the manifest-type-contracts test.

Fix: update repo to the public cursor/cursor repo (32,526 stars as of 2026-03-29).
Also applies the daily star count updates for all other agents.

-- qa/e2e-tester

Co-authored-by: spawn-qa-bot <qa@openrouter.ai>

* fix(spawn-fix): load API keys via config file, not just process.env (#3095)

Previously buildFixScript() resolved env templates directly from
process.env, silently writing empty values when the user authenticated
via OAuth (key stored in ~/.config/spawn/openrouter.json). Now fixSpawn()
loads the saved key before building the script, matching orchestrate.ts.

Fixes #3094

Agent: code-health

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: sync README commands table with help.ts (--prompt, --prompt-file) (#3106)

Co-authored-by: spawn-qa-bot <qa@openrouter.ai>

* fix(e2e): reduce Hetzner batch parallelism from 3 to 2 (#3112)

Prevents server_limit_reached errors when pre-existing servers (e.g.
spawn-szil) consume quota during E2E batch 1.

Fixes #3111

Agent: test-engineer

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>

* refactor(e2e): normalize unused-arg comments in headless_env functions (#3113)

GCP, Sprite, and DigitalOcean had commented-out code `# local agent="$2"`
in their `_headless_env` functions. Hetzner already used the cleaner style
`# $2 = agent (unused but part of the interface)`. Normalize to match.

Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: Remove duplicate and theatrical tests (#3089)

* test: remove duplicate and theatrical tests

- update-check.test.ts: fix 3 tests using stale hardcoded version '0.2.3'
  (older than current 0.29.1) to use `pkg.version` so 'should not update
  when up to date' actually tests the current-version path correctly
- run-path-credential-display.test.ts: strengthen weak `toBeDefined()`
  assertion on digitalocean hint to `toContain('Simple cloud hosting')`,
  making it verify the actual fallback hint content

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: replace theatrical no-assert tests with real assertions in recursive-spawn

Two tests in recursive-spawn.test.ts captured console.log output into a
logs array but never asserted against it. Both ended with a comment like
"should not throw" — meaning they only proved the function didn't crash,
not that it produced the right output.

- "shows empty message when no history": now spies on p.log.info and
  asserts cmdTree() emits "No spawn history found."
- "shows flat message when no parent-child relationships": now asserts
  cmdTree() emits "no parent-child relationships" via p.log.info.

expect() call count: 4831 to 4834 (+3 real assertions added).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: consolidate redundant describe block in cmd-fix-cov.test.ts

The file had two separate describe blocks with identical beforeEach/afterEach
boilerplate. The second block ("fixSpawn connection edge cases") contained only
one test ("shows success when fix script succeeds") and could be merged directly
into the first block ("fixSpawn (additional coverage)") without any loss of
coverage or setup fidelity.

Removes 23 lines of duplicated boilerplate. Test count unchanged (6 tests).

---------

Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(config): extend biome.json includes to cover .claude/**/*.ts

Add .claude/**/*.ts to biome.json includes so TypeScript files in
.claude/scripts/ and .claude/skills/ are covered by biome formatting.
Linting is disabled for .claude/** via override because the GritQL
plugins (no-try-catch, no-typeof-string-number) target the main CLI
codebase and cannot be scoped per-path — .claude/ hook scripts
legitimately use try/catch as they run standalone outside the package.

Agent: pr-maintainer
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix(prompts): stop infinite shutdown loop after TeamDelete in non-interactive mode (#3116)

After TeamDelete completes in -p (non-interactive) mode, Claude Code's
harness was re-injecting shutdown prompts every turn. The root cause:
the Monitor Loop instructed the agent to call TaskList + Bash on EVERY
iteration, including after TeamDelete, which kept the session alive so
the harness could inject more shutdown prompts.

Fix: add an explicit EXCEPTION to both refactor-team-prompt.md and
refactor-issue-prompt.md instructing the team lead that after TeamDelete
is called, the very next response MUST be plain text only with no tool
calls. A text-only response is the termination signal for the
non-interactive harness.

Fixes #3103

Agent: issue-fixer

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix(zeroclaw): remove broken zeroclaw agent (repo 404) (#3107)

* fix(zeroclaw): remove broken zeroclaw agent (repo 404)

The zeroclaw-labs/zeroclaw GitHub repository returns 404 — all installs
fail. Remove zeroclaw entirely from the matrix: agent definition,
setup code, shell scripts, e2e tests, packer config, skill files,
and documentation.

Fixes #3102

Agent: code-health
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix(zeroclaw): remove stale zeroclaw reference from discovery.md ARM agents list

Addresses security review on PR #3107 — the last remaining zeroclaw
reference in .claude/rules/discovery.md is now removed.

Agent: issue-fixer
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix(zeroclaw): remove remaining stale zeroclaw references from CI/packer

Remove zeroclaw from:
- .github/workflows/agent-tarballs.yml ARM build matrix
- .github/workflows/docker.yml agent matrix
- packer/digitalocean.pkr.hcl comment
- sh/e2e/e2e.sh comment

Addresses all 5 stale references flagged in security review of PR #3107.

Agent: issue-fixer
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

---------

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix(cli): allow --headless and --dry-run to be used together (#3117)

Removes the mutual-exclusion validation that blocked combining these flags.
Both flags serve independent purposes: --dry-run previews what would happen,
--headless suppresses interactive prompts and emits structured output.
Combining them is valid for CI pipelines that want structured JSON previews.

Fixes #3114

Agent: issue-fixer

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix(cli): allow --headless and --dry-run to be used together (#3118)

* test: remove redundant theatrical assertions (#3120)

Remove bare toHaveBeenCalled() checks that preceded stronger content
assertions, and strengthen the "shows manual install command" test to
verify the actual install script URL appears in output.

Affected files:
- cmd-update-cov: remove redundant consoleSpy.toHaveBeenCalled() (x2),
  strengthen "shows manual install command" to check install.sh content
- update-check: remove redundant consoleErrorSpy.toHaveBeenCalled() (x2)
  that were immediately followed by .mock.calls content assertions
- recursive-spawn: remove redundant logInfoSpy.toHaveBeenCalled() before
  content check
- cmd-interactive: remove redundant mockIntro/mockOutro.toHaveBeenCalled()
  before content checks

Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: sync README tagline with manifest (9 agents/54 → 8 agents/48 combinations) (#3119)

Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: L <6723574+louisgv@users.noreply.github.com>

* docs: remove stale ZeroClaw references after agent removal (#3122)

ZeroClaw was removed in #3107 (repo 404). Two doc references were left
behind:
- .claude/rules/agent-default-models.md: table row for ZeroClaw model config
- README.md: ZeroClaw listed in --fast skip-cloud-init agent examples

Agent: code-health

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(e2e): redirect DO max_parallel log_warn to stderr (#3110)

_digitalocean_max_parallel() called log_warn which writes colored output
to stdout, polluting the captured return value when invoked via
cloud_max=$(cloud_max_parallel). The downstream integer comparison
[ "${effective_parallel}" -gt "${cloud_max}" ] then fails with
'integer expression expected', silently leaving the droplet limit cap
unapplied. Fix: redirect log_warn output to stderr so only the numeric
value is captured.

Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: L <6723574+louisgv@users.noreply.github.com>

* refactor: remove stale ZeroClaw references from docs and code comments

---------

Signed-off-by: Ahmed Abushagur <ahmed@abushagur.com>
Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: Ahmed Abushagur <ahmed@abushagur.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: spawn-bot <spawn-bot@openrouter.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants