Skip to content

feat(run): --repeat <n> to run the selected tests n times and report flaky ones - #42

Merged
kevinccbsg merged 2 commits into
BRIKEV:mainfrom
YodHeVauHe:cursor/repeat-flaky-tests-57ff
Oct 18, 2026
Merged

kevinccbsg merged 2 commits into
BRIKEV:mainfrom
YodHeVauHe:cursor/repeat-flaky-tests-57ff

Conversation

@YodHeVauHe

Copy link
Copy Markdown
Contributor

Fixes #41

Description

--repeat <n> runs the selected tests n times in one browser and reports which ones are flaky. The page reloads between rounds (one page.goto and a wait for #twd-sidebar-root), so a round does not inherit the previous round's page state, and Chrome is not relaunched. Test ids are random per load, so rounds are joined by registration index.

The run-complete block counts every round and lists a test that both passed and failed under Flaky, with (passes/runs passed) and the last error. A test that failed every round stays under Failed tests with the same count. The run exits 1 if any round of any test failed.

Decisions for this first version:

  • --repeat accepts a positive integer in either --repeat 5 or --repeat=5 form and refuses anything else.
  • Retries are forced off (retryCount 1) for the run, so a pass on a second attempt cannot hide a flake. 0 is not used, because that crashes the in-page onFail.
  • maxFailures counts distinct tests that have failed at least once, not each failed round.
  • --record (including record.enabled in config) and --shard are refused before launch.
  • Coverage collection and contract validation are skipped.
  • run.json stays on schema v3. It adds repeat on the run header and runs, passes, and skips on each test. outcome is failed when any round failed. The HTML report and summary.md list flaky tests under Needs attention.

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Documentation update
  • Test addition or update

Testing

  • I have added tests that prove my fix is effective or that my feature works
  • All existing tests pass
  • New and existing unit tests pass locally

npx vitest run — 35 files, 796 tests passed.

There is no lint script in package.json.

Covered: flag parsing (both forms, rejection, suggestion), round aggregation across reloads, the exit code, maxFailures counting tests rather than rounds, refusal of --record and --shard, skipped coverage and contracts, the run-complete block, and the run.json / HTML / markdown fields.

Documentation

  • I have updated the documentation accordingly

README documents the flag. docs/cpu-throttling.md uses --repeat instead of the shell loop.

Run the selected tests n times in one browser, reloading the page
between rounds, and list each test that failed a round with its pass
count. A flaky result still fails the run.

Co-authored-by: ZaSourceCode <YodHeVauHe@users.noreply.github.com>
@kevinccbsg

Copy link
Copy Markdown
Member

Hi @YodHeVauHe thanks for the PR we will review it this week and if it is okay we will do the release today too

@kevinccbsg kevinccbsg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@YodHeVauHe thanks for this, the feature is exactly what #41 asked for and the overall shape is right: refusing --shard and --record before launch, skipping coverage and contracts, and forcing a single attempt are all how we want --repeat to behave. It is a debugging flag, so the rule is "plain run, nothing else". The full suite passes locally (796 tests).

A few things need to change before merging:

  1. Console counts must match the report (blocking). outcomeCounts() sums rounds while run.json, the HTML and summary.md count tests. For 3 tests x 10 rounds with one test failing 2 rounds, the terminal says Passed: 28 | Failed: 2 and the report says 2 passed, 1 failed. Count tests everywhere; the per-test (8/10 passed) line already carries the round detail.
  2. No layout snapshots under --repeat. Refuse --update-snapshots and --ci with --repeat, and disable snapshot matching for the run.
  3. Refuse in the parser. The --shard / --record refusal currently runs after cleanReportDir(), so a mistyped command deletes the previous report before exiting 1.
  4. record.enabled from the config. Keep refusing, but the message should name the config key, since the user never typed --record.
  5. Docs. Please drop the README section; docs/cpu-throttling.md is the right home for it.

Since the PR looks agent-assisted (which is fine), here is a prompt you can hand to your agent as is:

You are updating PR #42 in BRIKEV/twd-cli, which adds `twd-cli run --repeat <n>`.
Read CLAUDE.md at the repo root first and follow its conventions (terse code
comments, one test file per src module, no real browser or ffmpeg in tests).

Principle: --repeat is a debugging flag. A repeated run is a plain run: no
sharding, no recording, no coverage, no contracts, no layout snapshots, one
attempt per test.

Make these changes:

1. Console counts. In src/testSummary.js, `formatRunComplete` must count TESTS,
   not rounds, when `repeat > 1`, using the same rule as `finalizeReport` in
   src/runReport.js: a test with status "fail" (including a flaky one) counts as
   failed once. Remove the round-summing branch of `outcomeCounts`. Keep the
   per-test `(passes/runs passed)` suffix in the Failed and Flaky lists.
   Add a test that builds one repeated result (3 tests x 10 rounds, one test
   failing 2 rounds) and asserts the console block and `buildRunReport(...).summary`
   report the same passed/failed/skipped numbers (2 / 1 / 0).

2. Refusals move to the parser. In src/parseArgs.js `parseRunArgs`, throw a
   usage error when `--repeat` (n > 1) is combined with any of `--shard`,
   `--record`, `--update-snapshots`, `--ci`. The message lists every offending
   flag, e.g. "twd-cli run: --repeat cannot be combined with --shard and --ci."
   Remove the flag-based refusal from src/index.js. Add parseArgs tests for each
   combination, and a tests/cli.test.js case proving the command exits 1 with
   the message on stderr and nothing on stdout.

3. Config recording. `record.enabled: true` in twd.config.json cannot be
   checked in the parser, so keep that refusal in src/index.js, but move it
   ABOVE the `cleanReportDir()` call so a refused run never deletes the previous
   report, and word it as:
   "twd-cli run: --repeat cannot run with \"record.enabled\": true in twd.config.json."
   Add a runTests test asserting cleanReportDir is not called when it throws.

4. Layout snapshots off. When repeating, the `evaluateOnNewDocument` injection
   in src/index.js must set `window.__TWD_SNAPSHOTS__ = false` instead of true.
   Setting it is required: twd-js's vite plugin runs `__TWD_SNAPSHOTS__ ??= true`,
   so leaving it undefined would turn snapshots back on, while an explicit
   false survives `??=`. Do not set the update or ci flags. Log
   "Skipping layout snapshots (--repeat)." next to the coverage and contracts
   skip lines. Add a runTests test asserting the injected flags under --repeat.

5. Docs. Remove the "Repeating a selection" section from README.md entirely.
   Keep the docs/cpu-throttling.md change and add one sentence that --repeat
   skips coverage, contracts and layout snapshots. Update src/usage.js and the
   CLAUDE.md paragraph to list all four refused flags and the snapshot skip, and
   to say the console counts tests, not rounds. Do not use em dashes in docs.

Run `npx vitest run` and make sure the whole suite passes before pushing.
Do not change package.json, the lockfile, or anything under .github/.

@kevinccbsg kevinccbsg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @YodHeVauHe 🚀

@kevinccbsg
kevinccbsg merged commit 2d3b21b into BRIKEV:main Oct 18, 2026
6 checks passed
@kevinccbsg

Copy link
Copy Markdown
Member

@YodHeVauHe thanks, this looks great and it's merged. The review feedback was handled really well.

If you'd like to keep going, the flag isn't documented on twd.dev yet. I opened BRIKEV/twd#397 for a short "Hunting flaky tests" section covering --repeat and --cpu-throttle. It's yours if you want it, no pressure.

Also, if you have a minute, I'd love some quick feedback:

  • How did you come across twd-cli, and are you using it in a project?
  • Have you tried twd-js tests in a frontend project?
  • Did the agent prompt in the review work well for you, or would you have preferred the feedback in a different format?

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.

feat(run): --repeat <n> to run the selected tests n times and report flaky ones

3 participants