Skip to content

Commit 0530b28

Browse files
authored
Merge branch 'main' into fix/pr134-clean
2 parents cff19ae + b9e9601 commit 0530b28

67 files changed

Lines changed: 6813 additions & 385 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,32 +48,39 @@ jobs:
4848
- run: npm run typecheck
4949

5050
test:
51-
name: Unit Tests
51+
name: Unit Tests (Node ${{ matrix.node-version }})
5252
runs-on: ubuntu-latest
53+
strategy:
54+
matrix:
55+
node-version: [20, 22]
5356
steps:
5457
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
5558

5659
- name: Setup Node.js
5760
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
5861
with:
59-
node-version: 22
62+
node-version: ${{ matrix.node-version }}
6063
cache: 'npm'
6164

6265
- run: npm ci
66+
- run: npm run build
6367
- run: npm test
6468
env:
6569
CI: true
6670

6771
build:
68-
name: Build
72+
name: Build (Node ${{ matrix.node-version }})
6973
runs-on: ubuntu-latest
74+
strategy:
75+
matrix:
76+
node-version: [20, 22]
7077
steps:
7178
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
7279

7380
- name: Setup Node.js
7481
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
7582
with:
76-
node-version: 22
83+
node-version: ${{ matrix.node-version }}
7784
cache: 'npm'
7885

7986
- run: npm ci

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ All notable changes to `@testsprite/testsprite-cli` are documented here. The for
44

55
## [Unreleased]
66

7+
### Added
8+
9+
- **JUnit XML report export for batch `--wait` runs.** `test run --all` and batch `test rerun` (`--all` or multiple test ids) accept `--report junit --report-file <path>` to write a CI-friendly XML sidecar after polling completes. `--output json` is unchanged; the report is written even when the batch exits non-zero. `--dry-run` writes a canned sample without network calls.
10+
- **`testsprite test flaky <test-id>`** — repeat-run flaky-test detector. Replays a test N times (`--runs <n>`, default 5), aggregates the outcomes, and reports a stability verdict (`stable` / `flaky` / `failing`) plus the `runId` and `failureKind` of every attempt that did not pass. Replays run with auto-heal OFF (strict verbatim) so a healed drift can't mask a nondeterministic pass/fail. Exit code is 0 only when every attempt passed, so CI can gate a merge on flakiness (`testsprite test flaky <id> --runs 5 || exit 1`). Flags: `--runs <n>` (1–10), `--until-fail` (stop at the first non-passing attempt), `--timeout <s>` (per-attempt), and `--output json` for a machine-readable stability report. Frontend replays are free verbatim script replays; a one-line advisory is printed for backend tests, whose closure reruns may cost credits.
11+
712
## [0.2.0] - 2026-06-29
813

914
### Added

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ the thread or in Discord is welcome.
3434

3535
## Prerequisites
3636

37-
- Node 20 or newer (development happens on Node 22).
37+
- Node 20.19+, Node 22.13+, or Node 24+ (development happens on Node 22).
3838

3939
## Build from source
4040

DOCUMENTATION.md

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Or run it without installing:
3535
npx @testsprite/testsprite-cli --version
3636
```
3737

38-
Requires **Node.js ≥ 20**.
38+
Requires **Node.js 20.19+**, **22.13+**, or **24+**.
3939

4040
Confirm the binary works **without** configuring an API key:
4141

@@ -112,15 +112,17 @@ testsprite agent install claude # install the skill for Claude Code
112112
testsprite agent install codex # install into AGENTS.md for Codex (managed-section)
113113
testsprite agent install cursor # .cursor/rules/testsprite-verify.mdc
114114
testsprite agent install cline # .clinerules/testsprite-verify.md
115+
testsprite agent install windsurf # .windsurf/rules/testsprite-verify.md
115116
testsprite agent install antigravity # .agents/skills/testsprite-verify/SKILL.md
116-
testsprite agent list # list all 5 targets with status + mode + path
117+
testsprite agent install kiro # .kiro/skills/testsprite-verify/SKILL.md
118+
testsprite agent list # list all 7 targets with status + mode + path
117119
```
118120

119-
Supported targets: `claude` (GA), `codex` (experimental), `cursor` (experimental), `cline` (experimental), `antigravity` (experimental).
121+
Supported targets: `claude` (GA), `codex` (experimental), `cursor` (experimental), `cline` (experimental), `antigravity` (experimental), `kiro` (experimental), `windsurf` (experimental).
120122

121123
The `codex` target uses **managed-section mode** — it writes only a sentinel-delimited section inside your existing `AGENTS.md`, so your project instructions are never clobbered. Re-running without `--force` replaces the section in-place; user content outside the sentinels is always preserved.
122124

123-
Re-running with `--force` on **own-file targets** (claude, cursor, cline, antigravity) backs up the existing file to `<path>.bak` first.
125+
Re-running with `--force` on **own-file targets** (claude, cursor, cline, antigravity, kiro, windsurf) backs up the existing file to `<path>.bak` first.
124126

125127
## Command reference
126128

@@ -319,10 +321,10 @@ testsprite test plan put test_xxxxxxxx --steps ./refined.plan.json --dry-run --o
319321

320322
#### `testsprite project create` / `project update`
321323

322-
Manage projects from the CLI. Both pre-flight `--target-url` against local addresses for fast feedback.
324+
Manage projects from the CLI. Both pre-flight `--url` against local addresses for fast feedback.
323325

324326
```bash
325-
testsprite project create --name "Checkout" --target-url https://staging.example.com
327+
testsprite project create --type frontend --name "Checkout" --url https://staging.example.com
326328
testsprite project update proj_xxxxxxxx --name "Checkout v2"
327329
```
328330

@@ -344,9 +346,19 @@ testsprite test run test_xxxxxxxx --target-url https://staging.example.com \
344346

345347
# Dry-run prints a canned queued response (no network, no credentials)
346348
testsprite test run test_xxxxxxxx --dry-run --output json
349+
350+
# Batch BE run with JUnit XML for CI (sidecar; --output json unchanged)
351+
testsprite test run --all --project proj_xxxxxxxx --wait \
352+
--report junit --report-file ./results.xml --output json
353+
354+
# Optional custom suite name (default: testsprite:<projectId>)
355+
testsprite test run --all --project proj_xxxxxxxx --wait \
356+
--report junit --report-file ./results.xml --report-suite-name my-ci-suite --output json
347357
```
348358

349-
`--target-url` must be a publicly reachable URL — the CLI pre-flights it against local addresses (`localhost`, `127.x`, `::1`, `0.0.0.0`, `169.254.x`, RFC1918) and the backend resolves it via DNS. For testing against localhost, use the [TestSprite MCP plugin](https://www.testsprite.com/docs), which handles the local tunnel. The CLI auto-mints an idempotency key (printed to stderr at `--verbose`); pass `--idempotency-key <uuid>` to control it explicitly.
359+
Batch `--report` flags apply only to `test run --all --wait` (and batch `test rerun --wait`). `--report junit --report-file <path>` writes a JUnit XML sidecar after polling completes (atomic write); `--output json` is unchanged. Optional `--report-suite-name <name>` overrides the default `testsprite:<projectId>` suite name.
360+
361+
`--target-url` must be a publicly reachable URL — the CLI pre-flights it against local addresses (`localhost`, `127.x`, `::1`, `0.0.0.0`, `169.254.x`, RFC1918) and the backend resolves it via DNS. For testing against localhost, use the [TestSprite MCP plugin](https://www.testsprite.com/docs), which handles the local tunnel. The CLI auto-mints an idempotency key (printed to stderr under `--output json`, `--verbose`, or `--debug`); pass `--idempotency-key <uuid>` to control it explicitly.
350362

351363
#### `testsprite test rerun [test-id...]`
352364

@@ -365,21 +377,55 @@ testsprite test rerun test_be_xxxx --skip-dependencies --output json
365377
# Rerun every test in a project (batch)
366378
testsprite test rerun --all --project proj_xxxxxxxx --wait --max-concurrency 4 --output json
367379

380+
# Batch rerun with JUnit XML for CI
381+
testsprite test rerun --all --project proj_xxxxxxxx --wait \
382+
--report junit --report-file ./results.xml --output json
383+
384+
# Optional custom suite name (default: testsprite:<projectId>)
385+
testsprite test rerun --all --project proj_xxxxxxxx --wait \
386+
--report junit --report-file ./results.xml --report-suite-name my-ci-suite --output json
387+
368388
# Several specific tests
369389
testsprite test rerun test_aaaa test_bbbb --wait --output json
370390
```
371391

392+
Batch `--report` flags apply only to batch `--wait` reruns (`--all` or multiple test ids). `--report junit --report-file <path>` writes a JUnit XML sidecar after polling completes (atomic write); `--output json` is unchanged. When `--project` is omitted, the CLI infers `projectId` from polled run rows for classname / default suite naming; if inference fails, pass `--project <id>` explicitly (required under `--dry-run`).
393+
372394
Flags:
373395

374396
- `--all` — rerun every test in the resolved project; requires `--project <id>`.
375397
- `--wait`, `--timeout <s>` — block until terminal; same exit matrix as `test run --wait`.
376398
- `--auto-heal` / `--no-auto-heal` — frontend AI heal-on-drift, **on by default** for FE reruns; opt out with `--no-auto-heal`. Verbatim-replay passes are free; a heal engage costs a small amount of credit. Ignored for backend tests.
377399
- `--skip-dependencies` — backend only: rerun just the named test without expanding the producer/teardown closure.
378400
- `--max-concurrency <n>` — with `--wait`, cap on in-flight polls during a batch rerun.
379-
- `--idempotency-key <key>` — auto-minted when omitted.
401+
- `--idempotency-key <key>` — auto-minted when omitted (the minted key is printed to stderr under `--output json`, `--verbose`, or `--debug`).
402+
- `--report junit --report-file <path>` — with batch `--wait`, write a JUnit XML sidecar after polling (atomic write). Optional `--report-suite-name <name>` overrides the default `testsprite:<projectId>` suite name. Requires `--wait`; not available on single-test reruns.
380403

381404
A batch rerun returns `accepted[]` (one `runId` per dispatched test) plus `deferred[]` for any test shed by the per-key run-rate limit; under `--wait`, a non-empty `deferred[]` exits 7 with a `nextAction` you can retry with a fresh idempotency key.
382405

406+
#### `testsprite test flaky <test-id>`
407+
408+
Detect a **flaky** test by replaying it several times and reporting how often it passes. Each attempt is a rerun with auto-heal **off** (a strict verbatim replay), so healed drift can't disguise a nondeterministic pass/fail — this measures the replay stability of the saved script against the configured URL. Frontend replays are free verbatim script replays; backend tests re-run their dependency closure and may cost credits (a one-line stderr advisory is printed before the run).
409+
410+
```bash
411+
# Replay 10 times and print a stability score
412+
testsprite test flaky test_xxxxxxxx --runs 10
413+
414+
# Fast "is it flaky at all?" — stop at the first non-passing attempt
415+
testsprite test flaky test_xxxxxxxx --runs 10 --until-fail
416+
417+
# Machine-readable stability report for CI
418+
testsprite test flaky test_xxxxxxxx --runs 10 --output json
419+
```
420+
421+
Flags:
422+
423+
- `--runs <n>` — number of replays (1–10, default 5).
424+
- `--until-fail` — stop at the first attempt that does not pass.
425+
- `--timeout <s>` — per-attempt polling deadline (same semantics as `test wait`).
426+
427+
`--output json` emits `{ testId, runs, passed, failed, stableRatio, verdict, failures: [{ attempt, runId, outcome, failureKind }] }`. Exit codes: **0** when every observed attempt passed (`stable`); **1** when any attempt did not pass (`flaky` or `failing`); **4** when the test has no replayable run (trigger `testsprite test run <id>` first); **5** on a validation error.
428+
383429
#### `testsprite test wait <run-id>`
384430

385431
Block until a run reaches a terminal status. Same exit-code matrix as `test run --wait`. Used to resume polling after a timed-out `test run --wait`, or when an agent already has a `runId` from a previous invocation.
@@ -426,12 +472,25 @@ These apply to every command:
426472

427473
### Environment variables
428474

429-
| Variable | Purpose |
430-
| ------------------------------- | --------------------------------------------------------------------------------- |
431-
| `TESTSPRITE_API_KEY` | API key — overrides the credentials file |
432-
| `TESTSPRITE_API_URL` | API endpoint — overrides the credentials file |
433-
| `TESTSPRITE_PROFILE` | Active profile (below `--profile`, above `default`) |
434-
| `TESTSPRITE_REQUEST_TIMEOUT_MS` | Per-request timeout in **milliseconds** (default `120000`, range `1000``600000`) |
475+
| Variable | Purpose |
476+
| ------------------------------- | --------------------------------------------------------------------------------------- |
477+
| `TESTSPRITE_API_KEY` | API key — overrides the credentials file |
478+
| `TESTSPRITE_API_URL` | API endpoint — overrides the credentials file |
479+
| `TESTSPRITE_PROFILE` | Active profile (below `--profile`, above `default`) |
480+
| `TESTSPRITE_REQUEST_TIMEOUT_MS` | Per-request timeout in **milliseconds** (default `120000`, range `1000``600000`) |
481+
| `TESTSPRITE_NO_UPDATE_NOTIFIER` | Any non-empty value disables the once-per-24h "new version available" notice |
482+
| `NO_COLOR` | Suppress ANSI escape sequences in ticker output ([no-color.org](https://no-color.org/)) |
483+
484+
### Update notice
485+
486+
Interactive runs print a one-line "new version available" notice on stderr when
487+
a newer release exists. To learn this, the CLI contacts the public npm registry
488+
(`registry.npmjs.org`) at most once per 24 hours; the request carries the
489+
package name only — never your API key, project data, or command line. The
490+
check is skipped in CI, when stderr is not a TTY, under `--output json` /
491+
`--dry-run`, and entirely when `TESTSPRITE_NO_UPDATE_NOTIFIER` is set. Any
492+
failure is silent: the notice can never break or delay a command. This is the
493+
only outbound call the CLI makes besides your configured API endpoint.
435494

436495
### Scopes
437496

0 commit comments

Comments
 (0)