Skip to content

Move servicing event journeys to Cucumber - #1921

Merged
stefan-burke merged 3 commits into
mainfrom
feature/servicing-cucumber-specs
Jul 25, 2026
Merged

Move servicing event journeys to Cucumber#1921
stefan-burke merged 3 commits into
mainfrom
feature/servicing-cucumber-specs

Conversation

@stefan-burke

@stefan-burke stefan-burke commented Jul 25, 2026

Copy link
Copy Markdown
Member

Summary

  • replace the servicing e2e narrative test with one executable Cucumber Feature
  • cover creating a hold, duplicating, deleting, and recording a cost through the real rendered form
  • drive every form submission through the real rendered HTML form (CSRF token + fields extracted from the served page per AGENTS.md guidance)
  • assert exact redirect paths and exact formatted cost amounts
  • assert that deletion restores the held listing capacity
  • keep direct tests for capacity, deletion cascades, route guards, token 404s, ledger validation, and cost editing
  • add direct in-process coverage for the delete and duplicate route success paths
  • remove the old narrative test and its now-dead e2e browser helpers
  • extract assertRedirectPathname helper for exact redirect-path assertions

Why

The six servicing e2e tests were narrative scenarios driven through a TestBrowser. Four described observable operator journeys; two were weak (a custom-question test that never created a question, and a URL-poke test already covered by direct route-guard tests). The four strong scenarios now live in one plain-language Feature.

Rules covered

  • a service hold appears on the organiser dashboard but not on the public site
  • duplicating a hold creates an independent copy
  • deleting a hold removes it and restores the reserved capacity
  • recording a cost against a hold shows the exact amount on the service event page

Validation

  • nix develop -c deno task specs:files specs/servicing/hold-and-cost.feature: 4 scenarios and 21 steps passed
  • nix develop -c deno task precommit
  • git diff --check origin/main...HEAD

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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: 45 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: 2d22e38b-9312-4ee3-8cc2-cf8e1d46625c

📥 Commits

Reviewing files that changed from the base of the PR and between 51f02f2 and 954621a.

📒 Files selected for processing (3)
  • test/integration/servicing/route-guards.test.ts
  • test/specs/steps/servicing-hold.ts
  • test/test-utils/servicing.ts
📝 Walkthrough

Walkthrough

Adds a servicing hold BDD specification and Cucumber steps covering visibility, duplication, deletion, capacity restoration, and cost recording. It also expands mutation-route assertions, updates story catalog expectations, and removes obsolete browser-based servicing helpers.

Changes

Servicing hold acceptance coverage

Layer / File(s) Summary
Story registration and catalog coverage
specs/owners.json, specs/servicing/hold-and-cost.feature, test/scripts/specs/catalog.test.ts
Registers servicing ownership, adds servicing hold scenarios, and updates the repository story catalog expectation.
Cucumber servicing flow
test/specs/support/world.ts, test/specs/steps/servicing-hold.ts
Adds shared servicing event state and steps for creating, duplicating, deleting, costing, and verifying servicing holds.
Mutation routes and helper cleanup
test/integration/servicing/route-guards.test.ts, test/test-utils/servicing.ts
Adds success-path assertions for servicing deletion and duplication, and removes browser-driven servicing helper exports.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: moving servicing event journey coverage from a narrative test to a Cucumber feature.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/servicing-cucumber-specs
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feature/servicing-cucumber-specs

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@specs/servicing/hold-and-cost.feature`:
- Line 2: Change the feature tag in specs/servicing/hold-and-cost.feature at
lines 2-2 from `@owner`:attendees to `@owner`:servicing. Update
test/scripts/specs/catalog.test.ts at lines 12-23 to assert this story’s
servicing owner or verify that `@owner`:servicing selection includes it,
preventing future tag mismatches.

In `@test/integration/servicing/route-guards.test.ts`:
- Around line 93-100: Remove the unrelated createTestServicingEvent assertion
from the delete test after the deletion assertion, including the "unused" event
creation and positive-ID check. Keep the test focused solely on verifying
deletion; cover any creation-after-deletion invariant separately if required.
- Around line 113-119: Strengthen the assertions in the redirect-copy test
around the Location header and copied servicing event: assert that the header
exists, the servicing ID match and capture are present, the copied event exists,
and its first booking exists before reading fields. Then use the established
values directly with justified non-null narrowing, removing ?? "", optional
chaining, and fallback-driven NaN/undefined failures while preserving the
existing value checks.

In `@test/specs/steps/servicing-hold.ts`:
- Around line 152-158: Strengthen the assertions in
test/specs/steps/servicing-hold.ts at lines 152-158 and 181-187: identify the
rendered servicing entries and verify that exactly two are Annual Inspection
holds, rather than counting arbitrary servicing links and one label; for the
Boiler part cost record, assert the formatted amount is exactly 90.00, avoiding
substring matches such as 190.00.
- Line 107: Update the override object passed by the scenario in
servicing-hold.ts to use the helper’s camelCase key maximumDaysAfter instead of
maximum_days_after, so createHoldViaProduction applies the intended 1000-day
booking horizon.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ca9bd074-471b-48ac-98cd-e7f8206e5dab

📥 Commits

Reviewing files that changed from the base of the PR and between 63f350c and edc7e2a.

📒 Files selected for processing (8)
  • specs/owners.json
  • specs/servicing/hold-and-cost.feature
  • test/e2e/servicing/e2e-narrative.test.ts
  • test/integration/servicing/route-guards.test.ts
  • test/scripts/specs/catalog.test.ts
  • test/specs/steps/servicing-hold.ts
  • test/specs/support/world.ts
  • test/test-utils/servicing.ts
💤 Files with no reviewable changes (2)
  • test/e2e/servicing/e2e-narrative.test.ts
  • test/test-utils/servicing.ts

Comment thread specs/servicing/hold-and-cost.feature Outdated
Comment thread test/integration/servicing/route-guards.test.ts Outdated
Comment thread test/integration/servicing/route-guards.test.ts Outdated
Comment thread test/specs/steps/servicing-hold.ts Outdated
Comment thread test/specs/steps/servicing-hold.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: edc7e2a79f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread test/specs/steps/servicing-hold.ts
Comment thread test/specs/steps/servicing-hold.ts Outdated
Comment thread test/specs/steps/servicing-hold.ts Outdated
Comment thread test/specs/steps/servicing-hold.ts
@stefan-burke
stefan-burke force-pushed the feature/servicing-cucumber-specs branch from edc7e2a to bc91f4c Compare July 25, 2026 13:27

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bc91f4c28a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread specs/servicing/hold-and-cost.feature Outdated
Comment thread test/integration/servicing/route-guards.test.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
test/specs/steps/servicing-hold.ts (1)

153-159: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert exactly two duplicated holds.

Line 158 accepts an erroneous duplicate operation that creates three or more holds. Require the expected count of two.

Proposed fix
-    expect(count).toBeGreaterThanOrEqual(2);
+    expect(count).toBe(2);

As per coding guidelines, tests must use strong non-tautological assertions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/specs/steps/servicing-hold.ts` around lines 153 - 159, Update the
assertion in the “the admin dashboard shows two Annual Inspection holds” step to
require the match count to equal exactly 2 rather than accepting any count of 2
or greater. Keep the existing page rendering and match-count calculation
unchanged.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/integration/servicing/route-guards.test.ts`:
- Around line 87-95: Update the delete redirect test and the adjacent duplicate
test to validate required response fields before using them: assert that the
delete response contains a location header before constructing the URL, and
assert the duplicate test’s capture and first-booking values before using them.
Replace unchecked non-null assertions with contextual assertions followed by
justified narrowing, while preserving the existing redirect and booking
expectations.

---

Duplicate comments:
In `@test/specs/steps/servicing-hold.ts`:
- Around line 153-159: Update the assertion in the “the admin dashboard shows
two Annual Inspection holds” step to require the match count to equal exactly 2
rather than accepting any count of 2 or greater. Keep the existing page
rendering and match-count calculation unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3dd8c406-9daa-4066-a31a-bf386918cfd0

📥 Commits

Reviewing files that changed from the base of the PR and between edc7e2a and 51f02f2.

📒 Files selected for processing (8)
  • specs/owners.json
  • specs/servicing/hold-and-cost.feature
  • test/e2e/servicing/e2e-narrative.test.ts
  • test/integration/servicing/route-guards.test.ts
  • test/scripts/specs/catalog.test.ts
  • test/specs/steps/servicing-hold.ts
  • test/specs/support/world.ts
  • test/test-utils/servicing.ts
💤 Files with no reviewable changes (2)
  • test/e2e/servicing/e2e-narrative.test.ts
  • test/test-utils/servicing.ts

Comment thread test/integration/servicing/route-guards.test.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 51f02f2db5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread test/integration/servicing/route-guards.test.ts
Comment thread test/specs/steps/servicing-hold.ts Outdated
@stefan-burke
stefan-burke added this pull request to the merge queue Jul 25, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 954621a04d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +308 to +312
export const assertRedirectPathname = (
response: Response,
expected: string,
): void => {
expect(response.status).toBe(302);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Replace the existing redirect assertion helper

This adds assertRedirectPathname beside assertRedirectTo at lines 301–304, leaving the validation tests on the weaker substring check while new tests use exact pathname semantics. Keeping two helpers for the same redirect contract lets future tests choose the assertion that accepts broken nested destinations; replace the existing helper and migrate its callers instead of maintaining parallel implementations.

AGENTS.md reference: AGENTS.md:L72-L72

Useful? React with 👍 / 👎.

Comment on lines +39 to +43
const findForms = (html: string): Array<{ action: string; body: string }> => {
const re = /<form\s[^>]*action="([^"]*)"[^>]*>([\s\S]*?)<\/form>/gi;
const forms: Array<{ action: string; body: string }> = [];
for (const match of html.matchAll(re)) {
forms.push({ action: match[1]!, body: match[2]! });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reuse the shared rendered-form submission mechanism

This introduces a second HTML form finder and submission pipeline beside the one in test/test-utils/test-browser.ts: the existing implementation already parses forms, decodes actions, identifies the clicked button, preserves repeated controls, and applies overrides, while this copy separately reimplements those responsibilities through line 69. The two paths have already diverged—for example, this one neither decodes the action nor submits a clicked button's name/value and collapses repeated fields through Object.fromEntries—so future servicing-form changes can make Cucumber send a request different from a browser; expose and reuse the underlying form mechanism instead.

AGENTS.md reference: AGENTS.md:L72-L72

Useful? React with 👍 / 👎.

Merged via the queue into main with commit 15fbd30 Jul 25, 2026
3 checks passed
@stefan-burke
stefan-burke deleted the feature/servicing-cucumber-specs branch July 25, 2026 14:42
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.

1 participant