Skip to content

[Hackathon] fix(test): test run / cancel / delete-batch don't validate the id — empty id leaks an internal error, whitespace id fake-succeeds #395

Closed as duplicate

Description

@iamfirst

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

  1. iamfirst commented on Oct 14, 2026

    @iamfirst
    Author

    /assign

  2. testsprite-hob commented on Oct 14, 2026

    @testsprite-hob

    Thanks for the interest, @iamfirst! This issue hasn't been accepted for implementation yet — see the triage comment (a maintainer will label it accepted once it is). Feel free to check back, or ping us on Discord if it's been quiet.

  3. added
    duplicateThis issue or pull request already exists
    and removed
    needs-triageNew issue/PR awaiting first triage
    on Oct 20, 2026
  4. ruili-testsprite commented on Oct 20, 2026

    @ruili-testsprite
    Contributor

    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 /assign on #368.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    duplicateThis issue or pull request already existshackathonCLI hackathon submissions

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions