test(replay-test): cover failFast, retry exhaustion, plan-prep failure, JUnit escaping - #1550
Merged
Conversation
…e, and JUnit escaping
Closes four untested failure paths flagged by the 2026-08-01 test-strength
audit of packages/replay-test:
- request.failFast=true now has a test proving the suite stops after the
first failure and leaves the rest in the notRun bucket.
- Retry exhaustion (every attempt fails) is pinned to attempts === maxAttempts,
guarding the attemptIndex <= retries loop bound.
- A malformed .ad source (bad env directive) is fed through discovery to
prove the suite-level try/catch in session-test.ts converts the thrown
AppError into a {status:'failed'} response instead of escaping uncaught.
- The JUnit reporter's escaping is exercised directly for the first time,
round-tripping a title/message containing <, &, ", and a newline through
parseXmlDocumentSync.
Each test was verified red: the production condition was temporarily broken,
the test observed failing, then the code was restored (see PR body for the
four before/after runs).
Size Report
Startup median (7 runs, lower is better):
Top changed chunks:
|
Member
Author
|
Reviewed exact head |
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes four untested failure paths in the replay test harness, flagged by the 2026-08-01 test-strength audit of
packages/replay-test:failFast— no test anywhere setrequest.failFast=true. Added a test with 3 explicit entries where the first fails: asserts the suite invokes only the first entry, andnotRunaccounts for the other two (shouldStopReplayTestExecutioninpackages/replay-test/src/internal/session-test.ts).retries: 2where every attempt fails: assertsattempts === 3exactly, guarding theattemptIndex <= params.retriesloop bound inpackages/replay-test/src/internal/session-test-attempt.ts..adsource (env BROKEN— missing=) through discovery soreadReplayScriptMetadatathrows before any entry is runnable. Asserts the suite-level try/catch (packages/replay-test/src/internal/session-test.ts~L73-132) converts the thrownAppErrorinto{ok: false, error: {code: 'INVALID_ARGS', ...}}instead of letting it escape.src/replay/test/reporters/junit.tshad no direct test, only reporter-spec parsing. Addedsrc/replay/test/reporters/__tests__/junit.test.ts: writes a suite with a failing case whose title/message contain<,&,", and a newline, then parses the written file back with@agent-device/xml'sparseXmlDocumentSyncand asserts the values round-trip.All four tests were verified red per
docs/agents/testing.md's counterfactual rule — the production condition was temporarily broken, the test observed failing, then restored:failFastbranch inshouldStopReplayTestExecution→invoked.lengthwent from expected1to actual3(notRunfrom2to0).attemptIndex <= params.retriestoattemptIndex < params.retries→attemptCountwent from expected3to actual2.prepareReplayTestSuitePlanoutside the try/catch → theAppErrorescaped uncaught instead of the daemon returning{ok: false}.escapeXmlTextAndAttributeon the testcasenameattribute →parseXmlDocumentSyncthrewMissing value for XML attribute "quoted".on the tricky title.Design question for @thymikee
While writing the retry-exhaustion test I hit a contract asymmetry in
packages/contracts/src/replay.ts:ReplaySuiteTestPassedcarriesattemptFailures(so a flaky-then-passed test reports its earlier failed attempts), butReplaySuiteTestFaileddoes not. So when every attempt fails, only the last attempt's error survives in the result — the earlier attempts' failure messages are silently dropped. I did not change this (out of scope, and it's an API-widening decision), but flagging it: shouldReplaySuiteTestFailedalso carryattemptFailuresfor the attempts prior to the final one?Test plan
npx vitest run packages/replay-test src/daemon/handlers/__tests__/session-test-suite.test.ts src/replay/test— 75 tests passedpnpm typecheckpnpm lintpnpm format:check