Repository navigation
[Hackathon] fix(test): test run / cancel / delete-batch don't validate the id — empty id leaks an internal error, whitespace id fake-succeeds #395
Description
Verified against (commit SHA or released version)
commit 988c035 (v0.14.0)
Discord Username / User ID
outrageous_guava_90469_03877
What does this improvement do?
Three dispatch/write commands in the test family — test run, test cancel, and test delete-batch — interpolate their positional id argument into the request path without any local validation. Sibling commands in the same file validate the same kind of argument with the existing requireNonEmpty helper (src/commands/test.ts:1810, used e.g. by runPlanPut at :1922 and runUpdate at :2319), but these three entry points never call it. The result is three different bad behaviours for an empty or whitespace-only id: an internal implementation error leaked to the user, or a fake success for an operation that never happened.
Details / implementation notes
Three dispatch/write commands in the test family — test run, test cancel, and test delete-batch — interpolate their positional id argument into the request path without any local validation. Sibling commands in the same file validate the same kind of argument with the existing requireNonEmpty helper (src/commands/test.ts:1810, used e.g. by runPlanPut at :1922 and runUpdate at :2319), but these three entry points never call it. The result is three different bad behaviours for an empty or whitespace-only id: an internal implementation error leaked to the user, or a fake success for an operation that never happened.
Details / implementation notes
Verified against commit 988c035 (v0.14.0), built from source, Node v24.20.0, Linux x86_64. All runs below are --dry-run, so no network is involved; in live mode the same unchecked id is interpolated into the request path the same way (e.g. the cancel dispatch at src/commands/test.ts:794 posts to /runs/${runId}/cancel).
$ testsprite test cancel "" --dry-run
Error: No dry-run sample registered for POST https://api.testsprite.com/api/cli/v1/runs//cancel
Add a sample to src/lib/dry-run/samples.ts and re-run.
exit 1 — a developer-facing internal error (note the double slash in the URL)
$ testsprite test cancel "" --dry-run --output json
{"error": {"code": "INTERNAL",
"message": "No dry-run sample registered for POST https://api.testsprite.com/api/cli/v1/runs//cancel",
"nextAction": "Add a sample to src/lib/dry-run/samples.ts and re-run.", ...}}
$ testsprite test cancel " " --dry-run
... status cancelled
exit 0 — reports a successful cancel of a run that does not exist
$ testsprite test delete-batch "" --dry-run
Deleted: 1 Skipped: 0 Failed: 0
exit 0 — ditto for " "
$ testsprite test run "" --dry-run
{ "method": "POST", "path": "/api/cli/v1/tests//runs", ... }
exit 0 — and " " reports status: queued
Control case, same CLI: testsprite test list --project "" is rejected locally with VALIDATION_ERROR (exit 5) and a message telling the user how to fix the input.
Expected
An empty or whitespace-only id in test run, test cancel, and test delete-batch (each id, when several are passed) is rejected locally before any dispatch, with the same typed VALIDATION_ERROR / exit 5 the rest of the CLI uses for this class of mistake.
Actual
runDeleteBatch (src/commands/test.ts:2552) guards the flag combination (confirm prompt, ids-vs---all, zero ids) but never checks that an individual id is non-empty, so a single "" passes every guard.
The cancel command (src/commands/test.ts:9146) and the test run dispatch path (:10911 builds /api/cli/v1/tests/${testId}/runs) likewise use the raw argument.
In dry-run the empty id surfaces as the internal "No dry-run sample registered" error (including an instruction to edit source code, shown to end users); a whitespace id is dispatched as-is and the canned response makes the command report success.
Suggested fix
Call the existing requireNonEmpty('run-id' / 'test-id', id) (which trims) at these three entry points — for delete-batch, for every id in the list — before any path is built. No new helper or behaviour change for valid ids. Add cases to the existing spec files for these commands covering "" and whitespace-only ids.
Relationship to existing issues
#368 covers read-by-id commands forwarding an empty id (test get, test result, …); none of the three write/dispatch commands here are in its list, and the whitespace fake-success is specific to these paths. #373 is about how multi-id cancel/delete-batch map server rejections to exit codes — this issue is the step before any server contact: the id argument itself is never validated. If maintainers prefer one umbrella issue for the whole empty-id class, I'm happy for this to be folded into #368 instead.
Environment
CLI version: 0.14.0 (built from source at 988c035)
Node: v24.20.0
OS: Linux x86_64
Confirmations
- I have searched existing issues and this is not a duplicate.
- I have provided my Discord identity above for reward coordination.
Activity
iamfirst commentedon Oct 14, 2026
/assign
testsprite-hob commentedon Oct 14, 2026
Thanks for the interest, @iamfirst! This issue hasn't been accepted for implementation yet — see the triage comment (a maintainer will label it
acceptedonce it is). Feel free to check back, or ping us on Discord if it's been quiet.ruili-testsprite commentedon Oct 20, 2026
Closing as a duplicate of #368. Its scope now covers empty and whitespace-only positional ids for every command in one change, including the commands listed here. Thanks for the report! If you'd like to work on it, comment
/assignon #368.