Skip to content

[#209] Documented mock behaviour changes and fixed multi-line handling in command steps. - #210

Merged
AlexSkrypnyk merged 2 commits into
mainfrom
feature/209-mock-escapes-docs
Aug 5, 2026
Merged

AlexSkrypnyk merged 2 commits into
mainfrom
feature/209-mock-escapes-docs

Conversation

@AlexSkrypnyk

Copy link
Copy Markdown
Member

Closes #209

Summary

Closes #209, which reported that two mock behaviour changes on main - literal mock responses and strict mocking by default - reach consumers with no MIGRATION.md entry, and that the literal-response change left the step runner with no way at all to give a mock a multi-line response. Rather than the issue's preferred fix of restoring escape expansion inside mock_set_output and friends with printf '%b', this keeps that API literal, since docs/mocking.md already documents the literal reading as deliberate and restoring expansion there would reintroduce the mirror-image bug - a Windows path, a regular expression, or a JSON fixture piped in through - would have its backslash sequences silently rewritten, and a side effect, which is Bash code rather than text, would be rewritten too; a direct caller already has the idiomatic fix in ANSI-C quoting, mock_set_output "${mock}" $'AccessDenied\n403'. The actual capability lost was in the step runner, where a step is a single-line DSL parsed with read, so expanding backslash escapes in the step's output field alone restores a multi-line response from a step, while the arguments and the side effect stay literal. Alongside it, a @ step whose text contained a real newline - previously truncated at it, silently dropping its status, output and side effect - is now rejected with a message naming the single-line rule, and the library's own multi-line arg test, which had fallen into exactly that trap, is corrected to assert the output it always claimed to set. All three behaviour changes are now rows in the Behaviour changes table in MIGRATION.md.

Changes

Step runner (src/steps.bash)

  • Rejects a @ command step whose text contains a real newline instead of silently truncating it at the first newline during parsing, with a flunk message naming the single-line rule and the \n escape.
  • Expands backslash escapes in the step's output field only (printf -v mock_output '%b' "${mock_output}"), so \n in a step's output produces a multi-line mock response again; the command arguments and the side effect are read literally.
  • Updates the steps_run docblock to state the single-line rule and the output escape.

Documentation

  • MIGRATION.md: adds three Behaviour changes rows - literal mock responses (with the ANSI-C quoting workaround), strict mocking by default (with the diagnostic and both ways forward), and the rejected multi-line step.
  • docs/mocking.md: documents the ANSI-C quoting idiom for a multi-line response and points to the step runner's escape expansion as the equivalent for a step.
  • docs/steps.md: documents that the output field expands backslash escapes and that a step is rejected if it carries a real newline.

Tests (tests/steps.bats)

  • Corrects the existing multi-line arg test, which had silently dropped its # 0 # multi-line arg tail to the same truncation bug this branch fixes; it now continues the argument line with a trailing \ and asserts the output it always claimed to set.
  • Adds six tests written and watched failing before the implementation: the newline rejection, the caller's ability to recover from it, and the escape expansion for a newline, a tab, a backslash, and the shorthand output form.
  • Adds three scope-guard tests that stay green throughout, proving the change touches the output field alone: a real newline in a substring-presence step, an escaped newline in the arguments, and an escaped newline in the side effect.

Before / After

Scenario 1 - a step's output contains an escaped newline (\n)

  STEPS=( "@curl # 0 # AccessDenied\n403" )

BEFORE (main, unreleased)
┌──────────────────────────────────────────────────┐
│ mock output is one line: AccessDenied\n403       │
│ (the backslash and the n are literal characters) │
└──────────────────────────────────────────────────┘

AFTER (this branch)
┌───────────────────────────┐
│ mock output is two lines: │
│   AccessDenied            │
│   403                     │
└───────────────────────────┘

Scenario 2 - a step carries a real newline

  STEPS=( "@somebin --opt1
      # 0 # someval" )

BEFORE (main, unreleased)
┌────────────────────────────────────────────────────┐
│ read stops at the newline; status, output and side │
│ effect are silently dropped; mock is created with  │
│ status 0 and empty output                          │
└────────────────────────────────────────────────────┘

AFTER (this branch)
┌───────────────────────────────────────────────────────┐
│ rejected before parsing, naming the single-line rule: │
│ A command step must be a single line. Continue a      │
│ long step with a trailing backslash and write a       │
│ newline in the output as the \n escape.               │
└───────────────────────────────────────────────────────┘

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 20 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3a6006cc-7525-4d56-8bbf-265c50bf960c

📥 Commits

Reviewing files that changed from the base of the PR and between 66a9ad8 and 2f99cc2.

📒 Files selected for processing (5)
  • MIGRATION.md
  • docs/mocking.md
  • docs/steps.md
  • src/steps.bash
  • tests/steps.bats

Comment @coderabbitai help to get the list of available commands.

@AlexSkrypnyk
AlexSkrypnyk merged commit a4b0f44 into main Aug 5, 2026
12 checks passed
@AlexSkrypnyk
AlexSkrypnyk deleted the feature/209-mock-escapes-docs branch August 5, 2026 07:33
@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.12%. Comparing base (66a9ad8) to head (2f99cc2).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #210   +/-   ##
=======================================
  Coverage   98.12%   98.12%           
=======================================
  Files          16       16           
  Lines        2397     2401    +4     
=======================================
+ Hits         2352     2356    +4     
  Misses         45       45           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

Document the mock behaviour changes that reach consumers without a notice

1 participant