Skip to content

[Behat] Display API Errors Along With The Step Where The Error Occurred#16791

Merged
TheMilek merged 3 commits intoSylius:2.1from
Rafikooo:behat-step-explicit-errors
Aug 25, 2025
Merged

[Behat] Display API Errors Along With The Step Where The Error Occurred#16791
TheMilek merged 3 commits intoSylius:2.1from
Rafikooo:behat-step-explicit-errors

Conversation

@Rafikooo
Copy link
Copy Markdown
Contributor

@Rafikooo Rafikooo commented Aug 27, 2024

Q A
Branch? 2.0
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
License MIT

An example:
image

Summary by CodeRabbit

  • New Features

    • Introduces an API debugging context that collects API response errors per step and prints a formatted summary at scenario end.
    • Automatically records non-successful API responses in test runs for later inspection.
  • Tests

    • Enables the new API debugging context across numerous API suites (account, cart, channel, checkout, currency, inventory, locale, order, payment, product, promotion, shipping, taxation, taxon, user, and homepage scenarios).
  • Chores

    • Updates service wiring to support centralized error collection within API testing flows.

@GSadee GSadee changed the base branch from api-platform-3 to 2.0 September 4, 2024 10:04
@Rafikooo Rafikooo force-pushed the behat-step-explicit-errors branch from d0c3a09 to 5532147 Compare September 26, 2024 10:31
@github-actions
Copy link
Copy Markdown

github-actions bot commented Sep 26, 2024

❌ Preview Environment deleted from Bunnyshell

Available commands:

  • 🚀 /bns:deploy to redeploy the environment

@Rafikooo Rafikooo force-pushed the behat-step-explicit-errors branch 2 times, most recently from caa7085 to 7cf217d Compare October 8, 2024 22:43
@Rafikooo Rafikooo marked this pull request as ready for review October 10, 2024 13:38
@Rafikooo Rafikooo requested review from a team as code owners October 10, 2024 13:38
@Rafikooo Rafikooo force-pushed the behat-step-explicit-errors branch from 7cf217d to fe11320 Compare October 10, 2024 13:49
@Rafikooo Rafikooo force-pushed the behat-step-explicit-errors branch from fe11320 to eeb9638 Compare March 31, 2025 08:59
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 31, 2025

Walkthrough

Introduces ResponseChecker error collection and injects it into ApiPlatformClient to record non-success API responses. Adds a new DebugContext and DebugErrorType to collect and print errors after steps/scenarios. Wires services and enables the debug context across many Behat API suites, with a few suite context replacements/removals. One file contains duplicated methods.

Changes

Cohort / File(s) Summary
API client integration
src/Sylius/Behat/Client/ApiPlatformClient.php
Constructor now requires ResponseCheckerInterface. On 4xx/5xx responses, calls appendError($response) before storing last response.
Response checker error stack
src/Sylius/Behat/Client/ResponseChecker.php, src/Sylius/Behat/Client/ResponseCheckerInterface.php
Adds error stack API: appendError(Response), cleanErrors(), getDebugErrors(), and a constructor. Note: duplicate insertion of methods exists in ResponseChecker.php. Interface extended accordingly.
Debugging context & types
src/Sylius/Behat/Context/Api/DebugContext.php, src/Sylius/Behat/Context/Api/DebugErrorType.php
New context collects errors after each step and prints a formatted JSON report after scenarios. Adds DebugErrorType enum with API_RESPONSE and EXCEPTION.
Service wiring
src/Sylius/Behat/Resources/config/services/api.xml, src/Sylius/Behat/Resources/config/services/contexts/api/common.xml
Wires ResponseCheckerInterface into api_platform_client; updates ResponseChecker service definition (no constructor args). Registers sylius.behat.context.api.debug service.
Behat suites: additions
src/Sylius/Behat/Resources/config/suites/api/account/*, .../addressing/*, .../admin/dashboard.yaml, .../admin/locale.yaml, .../admin/login.yml, .../admin/security.yml, .../cart/*, .../channel/*, .../checkout/*, .../contact/*, .../currency/*, .../homepage/*, .../inventory/*, .../locale/*, .../order/*, .../payment/*, .../product/adding_product_review.yml, .../product/managing_product_*, .../product/viewing_*, .../promotion/*, .../shipping/*, .../taxation/*, .../taxon/*, .../user/managing_administrators.yml, .../user/managing_customers.yml
Adds sylius.behat.context.api.debug to numerous API suites’ contexts. No other behaviors changed in these files.
Behat suites: context replacements/removals
src/Sylius/Behat/Resources/config/suites/api/product/viewing_price_history.yml, src/Sylius/Behat/Resources/config/suites/api/promotion/managing_promotions.yml, src/Sylius/Behat/Resources/config/suites/api/user/managing_customer_groups.yml, src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml
Updates contexts with additions plus removals: some admin contexts removed/replaced (e.g., translation, response, save, shop.login) while adding debug context.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Test as Behat Step
  participant Client as ApiPlatformClient
  participant HTTP as API Server
  participant RC as ResponseChecker

  Test->>Client: request(method, url, payload, headers)
  Client->>HTTP: HTTP request
  HTTP-->>Client: Response
  alt status >= 400
    Client->>RC: appendError(Response)
  end
  Client-->>Test: Response (stored as last response)
Loading
sequenceDiagram
  autonumber
  participant Behat as Behat Engine
  participant Step as Step Execution
  participant RC as ResponseChecker
  participant Debug as DebugContext
  participant Console as Console Output

  Note over Step,RC: AfterStep hook
  Behat->>Debug: @AfterStep(scope)
  Debug->>RC: getDebugErrors()
  alt errors present
    Debug->>Debug: push {step, type: API_RESPONSE, error[]}
    Debug->>RC: cleanErrors()
  end

  Note over Behat,Console: AfterScenario hook
  Behat->>Debug: @AfterScenario()
  alt any collected errors
    Debug->>Console: print formatted JSON error stack
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

DX, API

Suggested reviewers

  • GSadee
  • NoResponseMate
  • bartek-sek

Poem

In moonlit logs I thump and peer,
I catch each 4xx, crisp and clear.
A stack of squeaks, then hop, erase—
Next step, fresh tracks, a cleaner chase.
When scenes conclude, I proudly show
The JSON burrow’s tale below. 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Rafikooo Rafikooo force-pushed the behat-step-explicit-errors branch from eeb9638 to d46f6b1 Compare April 22, 2025 11:47
@TheMilek TheMilek force-pushed the behat-step-explicit-errors branch from d46f6b1 to 266b735 Compare August 21, 2025 10:43
@TheMilek TheMilek changed the base branch from 2.0 to 2.1 August 21, 2025 11:16
@TheMilek TheMilek force-pushed the behat-step-explicit-errors branch from 266b735 to 7d77406 Compare August 22, 2025 10:59
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/Sylius/Behat/Client/ResponseCheckerInterface.php (1)

34-36: Add missing appendError to the interface to satisfy ApiPlatformClient’s usage.

ApiPlatformClient calls $this->responseChecker->appendError($response), but this method is not declared on the interface. That breaks LSP for any alternative implementation and will trip static analysis/IDE support.

Apply this diff to declare the method on the interface:

     public function getError(Response $response): ?string;
 
+    /**
+     * Collects an error derived from the given response for later debugging/printing.
+     */
+    public function appendError(Response $response): ResponseCheckerInterface;
src/Sylius/Behat/Resources/config/suites/api/user/managing_administrators.yml (1)

4-27: Missing debug context in inventory API suites

The following API suite files are missing the new sylius.behat.context.api.debug entry under their contexts blocks. Please update each file to include the debug context as the last item in the list:

  • src/Sylius/Behat/Resources/config/suites/api/inventory/cart_inventory.yml
  • src/Sylius/Behat/Resources/config/suites/api/inventory/checkout_inventory.yaml

For example, your contexts section should end with:

 contexts:
     - sylius.behat.context.hook.doctrine_orm
     - sylius.behat.context.transform.admin
     # … other contexts …
     - sylius.behat.context.api.save
+    - sylius.behat.context.api.debug

After applying these changes, re-run the verification script to ensure full coverage:

find src/Sylius/Behat/Resources/config/suites/api -type f \( -name '*.yaml' -o -name '*.yml' \) \
  -exec grep -L 'sylius\.behat\.context\.api\.debug' {} +
src/Sylius/Behat/Resources/config/suites/api/product/managing_product_variants.yml (1)

4-51: Remove duplicate context entries in managing_product_variants.yml

The suite configuration currently declares two contexts twice, which can lead to redundant initializations:

sylius.behat.context.transform.channel appears 2×
sylius.behat.context.setup.locale appears 2×

Please remove the redundant lines so each context is only listed once.

🧹 Nitpick comments (38)
src/Sylius/Behat/Client/ResponseCheckerInterface.php (1)

95-104: Adding methods to a public interface is a BC break — prefer a dedicated, optional interface.

The PR adds new methods (cleanErrors, getDebugErrors, and implicitly needed appendError) to ResponseCheckerInterface. Any custom implementation (common in plugins/suites) will break. To avoid BC breaks and keep ApiPlatformClient loosely coupled, introduce a small DebugErrorCollectorInterface and have ResponseChecker implement it; inject that into ApiPlatformClient and DebugContext instead of expanding ResponseCheckerInterface.

Proposed new interface (outside this file), and minimal wiring changes:

<?php
// src/Sylius/Behat/Client/DebugErrorCollectorInterface.php
declare(strict_types=1);

namespace Sylius\Behat\Client;

use Symfony\Component\HttpFoundation\Response;

/**
 * Narrow contract dedicated to debug error collection.
 */
interface DebugErrorCollectorInterface
{
    /** @return list<string> */
    public function getDebugErrors(): array;

    public function cleanErrors(): void;

    public function appendError(Response $response): self;
}
  • Make ResponseChecker implement DebugErrorCollectorInterface.
  • Type-hint DebugErrorCollectorInterface in ApiPlatformClient and DebugContext constructors.
  • Keep ResponseCheckerInterface unchanged (remove cleanErrors/getDebugErrors from it) to preserve BC.
    Do you want me to prepare a full patch across the affected files?
src/Sylius/Behat/Resources/config/suites/api/addressing/managing_zones.yml (1)

24-24: Gate verbose debug output behind a profile or env var.

Continuous debug logs can bloat CI output. Consider enabling the context only under a “debug” Behat profile or via an env flag to keep default runs quiet.

src/Sylius/Behat/Resources/config/suites/api/product/managing_product_options.yml (1)

27-27: Keep context ordering consistent across suites.

Minor: in other suites debug appears near other API response/save contexts. Aligning order helps scanability during maintenance.

src/Sylius/Behat/Resources/config/suites/api/taxon/managing_taxons.yml (1)

28-28: Avoid duplicate/overlapping error prints.

If api.admin.response already logs failures, ensure DebugContext only prints aggregated details on non-2xx responses (and preferably only on scenario failure) to prevent noisy duplication.

src/Sylius/Behat/Resources/config/suites/api/product/managing_products.yml (1)

54-54: Makes sense to expose debug info in product management scenarios

Including the debug context in product admin API tests should speed up failure triage. Order within the contexts list is not critical for After* hooks, so placement here is acceptable.

If this context is now required across all API suites, consider centralizing it (e.g., a shared include or a base API suite template) to avoid future drift. I can propose a consolidation plan if helpful.

src/Sylius/Behat/Resources/config/suites/api/checkout/paying_for_order.yml (1)

48-48: Review DebugContext Registration Across Suites

The DebugContext correctly cleans up errors after each scenario (cleanErrors in afterScenario), preventing cross-scenario leakage. However, the debug context is registered in multiple related suites, which can lead to redundant output and noise.

Affected registrations:

  • src/Sylius/Behat/Resources/config/suites/api/cart/shopping_cart.yml (line 30): - sylius.behat.context.api.debug
  • src/Sylius/Behat/Resources/config/suites/api/cart/accessing_cart.yml (line 32): - sylius.behat.context.api.debug
  • src/Sylius/Behat/Resources/config/suites/api/checkout/checkout.yml (line 57): - sylius.behat.context.api.debug
  • src/Sylius/Behat/Resources/config/suites/api/checkout/paying_for_order.yml (line 48): - sylius.behat.context.api.debug

Recommendation:
• Consolidate debug context registration by removing duplicate entries in suites that don’t strictly need it.
• For example, if you only require detailed responses during checkout flows, keep the debug context in paying_for_order.yml (and/or checkout.yml) and remove it from the cart suites.

src/Sylius/Behat/Resources/config/suites/api/product/managing_product_association_types.yml (1)

25-25: Right call for association types as well

The debug context will help pinpoint failing API responses in association-type scenarios. No conflicts with existing contexts.

If DebugContext prints errors on every non-success response, consider adding a toggle (env var or Behat parameter) to mute output for scenarios that intentionally assert failing responses, to reduce log noise in green runs.

src/Sylius/Behat/Resources/config/suites/api/shipping/managing_shipping_methods.yml (1)

26-27: Duplicate context registration detected (setup.shipping).

The context sylius.behat.context.setup.shipping appears twice. This can instantiate the same context twice, leading to duplicated hooks (e.g., AfterStep/AfterScenario) and potentially noisy or duplicated side effects.

Apply this diff to drop the duplicate:

                 - sylius.behat.context.setup.product
-                - sylius.behat.context.setup.shipping
                 - sylius.behat.context.setup.shipping
                 - sylius.behat.context.setup.zone

If you prefer, I can scan the rest of the suite configs for similar duplicates.

src/Sylius/Behat/Resources/config/suites/api/locale/locales.yaml (1)

15-24: Noise control in CI logs.

If this suite executes many steps that intentionally probe error conditions, consider ensuring DebugContext prints only on failures or when verbose mode is enabled, to keep CI output manageable.

src/Sylius/Behat/Resources/config/suites/api/product/managing_product_variants.yml (2)

11-12: Remove duplicated transform context entry for channel

The channel transform context is listed twice. Duplicate context wiring can slow suite boot and make step resolution/order harder to reason about without functional benefits.

Apply this minimal cleanup:

                 - sylius.behat.context.transform.channel
-                - sylius.behat.context.transform.channel

30-31: De-duplicate setup.locale context

The locale setup context appears twice. Keep a single entry.

                 - sylius.behat.context.setup.locale
-                - sylius.behat.context.setup.locale
src/Sylius/Behat/Resources/config/suites/api/user/managing_customer_groups.yml (1)

16-19: Consider ordering: place debug context after response/save

You already did this; noting that keeping debug last among admin API contexts is a sane convention and matches other suites. If you standardize this position across all API suites, maintenance improves.

src/Sylius/Behat/Resources/config/suites/api/payment/managing_payment_methods.yaml (1)

4-39: Optional: ensure consistent debug context placement across suites

For readability and predictability, keep sylius.behat.context.api.debug immediately after sylius.behat.context.api.admin.translation (or after ...admin.save if translation is absent) in all suites.

src/Sylius/Behat/Resources/config/suites/api/promotion/managing_catalog_promotions.yml (1)

8-34: Sanity check: mixed admin and shop contexts

This suite mixes admin and shop contexts, which is fine here. Confirm the debug context’s hooks won’t produce noisy output for shop steps; if that becomes an issue, consider scoping the debug context to admin-only scenarios via tags.

src/Sylius/Behat/Context/Api/DebugErrorType.php (1)

16-20: Optional: mark as internal for test/debug scope

If this enum is intended solely for Behat diagnostics, consider marking it internal to avoid accidental usage in production code.

 namespace Sylius\Behat\Context\Api;
 
+/** @internal Diagnostic enum used by Behat debug context for error categorization. */
 enum DebugErrorType: string
 {
     case API_RESPONSE = 'API_RESPONSE';
     case EXCEPTION = 'EXCEPTION';
 }
src/Sylius/Behat/Resources/config/suites/api/homepage/viewing_products.yml (1)

19-19: Add debug context — consider placing it at the end of the contexts list.

Functional change looks fine. For consistency across suites and to hint that it’s observational-only, consider keeping debug context as the last context entry.

Apply if you prefer this ordering:

-                - sylius.behat.context.api.debug
                 - sylius.behat.context.api.shop.homepage
+                - sylius.behat.context.api.debug
src/Sylius/Behat/Resources/config/suites/api/product/viewing_product_in_admin_panel.yaml (1)

42-42: Add debug context — also align file extension convention if needed.

Change looks correct. Two small consistency points:

  • Keep debug context last for readability and predictable hook expectations.
  • This directory mixes .yml and .yaml. If the project has a preferred extension, consider aligning.

Proposed ordering tweak:

-                - sylius.behat.context.api.debug
                 - Sylius\Behat\Context\Api\Admin\BrowsingCatalogPromotionProductVariantsContext
+                - sylius.behat.context.api.debug

If standardizing extensions is desired:

  • Rename viewing_product_in_admin_panel.yamlviewing_product_in_admin_panel.yml and update any references (if any).
src/Sylius/Behat/Resources/config/suites/api/cart/shopping_cart.yml (1)

30-30: Add debug context — sanity-check noise in high-traffic suites.

Cart flows generate many API calls; printing errors is great, but ensure duplicates are cleared after printing to avoid repeated output across steps. If DebugContext does not call ResponseChecker::cleanErrors() after emitting, consider doing so.

Optionally keep debug context last:

-                - sylius.behat.context.api.debug
                 - sylius.behat.context.api.shop.cart
                 - sylius.behat.context.api.shop.registration
+                - sylius.behat.context.api.debug
src/Sylius/Behat/Resources/config/suites/api/account/email_verification.yml (1)

19-23: Check noise for expected 4xx flows

Email verification scenarios often expect 4xx responses (invalid/missing token). If DebugContext prints every >=400, this may add noise on passing scenarios.

  • Ensure DebugContext only outputs on failed steps/scenarios, or filters out “expected” errors for steps asserting specific 4xx statuses.
  • If needed, I can propose a small guard in DebugContext to check step result status before printing.
src/Sylius/Behat/Resources/config/suites/api/channel/managing_channels.yml (1)

29-35: Nit: keep the debug context at the start of API admin contexts for consistency

Purely organizational: placing the debug context immediately before the first api.admin.* context helps keep suites uniform.

Apply this reorder:

                 - sylius.behat.context.api.admin.managing_channels
                 - sylius.behat.context.api.admin.response
                 - sylius.behat.context.api.admin.save
-                - sylius.behat.context.api.debug
+                - sylius.behat.context.api.debug
                 - Sylius\Behat\Context\Api\Admin\ManagingChannelPriceHistoryConfigContext
                 - Sylius\Behat\Context\Api\Admin\ManagingChannelsBillingDataContext

Or, alternatively, move it just above the first api.admin.* line:

                 - sylius.behat.context.setup.zone

+                - sylius.behat.context.api.debug
                 - sylius.behat.context.api.admin.managing_channels
                 - sylius.behat.context.api.admin.response
                 - sylius.behat.context.api.admin.save
src/Sylius/Behat/Resources/config/suites/api/order/modifying_placed_order_address.yaml (1)

37-42: Nit: standardize placement of the debug context among admin API contexts

For readability across suites, consider placing the debug context consistently just before the first api.admin.* entry.

Reorder like so:

                 - sylius.behat.context.api.admin.managing_orders
                 - sylius.behat.context.api.admin.managing_placed_order_addresses
                 - sylius.behat.context.api.admin.response
                 - sylius.behat.context.api.admin.save
-                - sylius.behat.context.api.debug
+                - sylius.behat.context.api.debug

Or move it above the admin block:

                 - sylius.behat.context.setup.taxonomy

+                - sylius.behat.context.api.debug
                 - sylius.behat.context.api.admin.managing_orders
                 - sylius.behat.context.api.admin.managing_placed_order_addresses
                 - sylius.behat.context.api.admin.response
                 - sylius.behat.context.api.admin.save
src/Sylius/Behat/Resources/config/suites/api/promotion/managing_promotion_coupons.yml (1)

32-32: Optional: standardize context ordering for readability

Across suites, consider placing sylius.behat.context.api.debug near other diagnostic contexts (often right after sylius.behat.context.api.admin.response) to keep debugging-related contexts grouped. No functional change—purely for consistency and discoverability.

                 - sylius.behat.context.api.admin.managing_promotion_coupons
-                - sylius.behat.context.api.admin.response
-                - sylius.behat.context.api.admin.save
-                - sylius.behat.context.api.debug
+                - sylius.behat.context.api.admin.response
+                - sylius.behat.context.api.debug
+                - sylius.behat.context.api.admin.save
src/Sylius/Behat/Resources/config/suites/api/product/viewing_price_history_after_catalog_promotions.yml (1)

25-25: Minor consistency suggestion: position debug context near response context

If this suite ever adds sylius.behat.context.api.admin.response, consider grouping the debug context immediately after it for uniformity with other suites.

src/Sylius/Behat/Resources/config/suites/api/order/managing_orders.yml (1)

54-56: Add debug context: placement looks correct; trim trailing spaces on email context

  • Good call placing sylius.behat.context.api.debug right after the admin managing orders context and before the email context.
  • Line 56 has trailing spaces after sylius.behat.context.api.email. Trim to avoid YAML linters or future diffs churn.

Apply this diff:

-                - sylius.behat.context.api.email                
+                - sylius.behat.context.api.email
src/Sylius/Behat/Resources/config/suites/api/order/order_history.yaml (1)

34-34: OK, but consider normalizing file extensions to .yml for consistency

Change is correct. For repo-wide consistency (most files in this tree use .yml), consider renaming this file to .yml. This avoids minor tooling surprises and keeps conventions uniform.

You can do:

git mv src/Sylius/Behat/Resources/config/suites/api/order/order_history.yaml \
       src/Sylius/Behat/Resources/config/suites/api/order/order_history.yml
src/Sylius/Behat/Resources/config/suites/api/promotion/removing_catalog_promotions.yml (1)

29-29: LGTM: debug context added between admin and shop contexts

Solid placement. Small nit: standardize placement across suites (e.g., always just before the first sylius.behat.context.api.* context, or always at the end of the contexts block) to ease scanning and future maintenance.

src/Sylius/Behat/Resources/config/suites/api/taxation/applying_taxes.yml (1)

40-40: Optional: standardize placement of the debug context

To keep suites consistent and to avoid any hook interleaving surprises, consider appending the debug context at the end of the contexts list in all suites.

src/Sylius/Behat/Resources/config/suites/api/promotion/applying_promotion_coupon.yml (1)

35-35: Optional: control verbosity via env/config if CI logs become noisy

If the debug output is always-on, large feature runs might get verbose. Consider an env flag (e.g., BEHAT_DEBUG_API_ERRORS) checked in DebugContext to toggle printing while keeping error collection active.

If you want, I can sketch how to inject a boolean parameter into DebugContext via services XML and toggle printing based on an env var.

src/Sylius/Behat/Resources/config/suites/api/shipping/applying_shipping_method_rules.yml (1)

36-36: Minor consistency nit: keep debug context grouped or last across all suites

For easier maintenance and predictable hook execution, consider keeping the debug context consistently last in the list across all suites.

src/Sylius/Behat/Resources/config/suites/api/promotion/managing_promotions.yml (1)

41-41: Optional ordering consistency

If DebugContext relies on AfterStep/AfterScenario hooks, consider moving it to the end of the context list to standardize execution sequence across suites.

src/Sylius/Behat/Resources/config/suites/api/payment/managing_payments.yml (1)

28-28: Good addition; placement within admin API contexts is consistent

Sits with the other admin API contexts; should integrate cleanly with existing hooks.

Consider standardizing the position of the debug context across admin suites (e.g., always just before the first api.* context) for easier scanning in reviews.

src/Sylius/Behat/Resources/config/suites/api/promotion/applying_promotion_rules.yml (1)

40-40: LGTM — debug context added before api.shop contexts

This aligns with other promotion-related suites and should provide useful per-step diagnostics.

If other promotion suites place the debug context immediately before the api.* contexts, mirror that here for uniformity across promotion configs.

src/Sylius/Behat/Resources/config/suites/api/checkout/checkout.yml (1)

57-57: LGTM — debug context for checkout suite

Placed just after CatalogPromotionContext and before api.* contexts; matches the broader convention in this PR.

While unrelated to this change, noticed duplicated context entries earlier (Lines 42–43: sylius.behat.context.setup.geographical appears twice). Consider removing the duplicate to keep the suite concise.

src/Sylius/Behat/Client/ApiPlatformClient.php (2)

356-359: Use expressive helpers for 4xx/5xx detection and simplify condition

isSuccessful() check is redundant when you already guard on >= 400. Prefer the dedicated helpers for clarity.

Apply:

-        if (!$response->isSuccessful() && $response->getStatusCode() >= 400) {
-            $this->responseChecker->appendError($response);
-        }
+        if ($response->isClientError() || $response->isServerError()) {
+            $this->responseChecker->appendError($response);
+        }

336-364: Optional: capture thrown exceptions as debug entries

If the BrowserKit client throws (transport/runtime) before a Response exists, these errors won’t be recorded. Since DebugErrorType includes EXCEPTION, consider wrapping the request dispatch in try/catch and delegating an “exception” record to the checker (or a dedicated collector). This would give parity with API response logging.

Example sketch (requires a new method on the checker or a separate DebugErrorCollector):

try {
    $this->client->request(
        $request->method(),
        $request->url(),
        $request->parameters(),
        $request->files(),
        $request->headers(),
        $request->content(),
    );
} catch (\Throwable $e) {
    // e.g. $this->responseChecker->appendException($request, $e);
    throw $e;
}

If you’d like, I can prepare a minimal change set (plus tests) to add this capability.

src/Sylius/Behat/Resources/config/services/api.xml (1)

32-32: Prefer aliasing the interface to the implementation (Symfony convention).

Defining the service with the interface id works, but using a concrete service id for the implementation and aliasing the interface improves clarity and tooling support.

Apply:

-        <service id="Sylius\Behat\Client\ResponseCheckerInterface" class="Sylius\Behat\Client\ResponseChecker"/>
+        <service id="Sylius\Behat\Client\ResponseChecker" class="Sylius\Behat\Client\ResponseChecker">
+            <!-- Optional: auto-reset between Symfony kernel resets -->
+            <!-- <tag name="kernel.reset" method="reset"/> -->
+        </service>
+        <service id="Sylius\Behat\Client\ResponseCheckerInterface" alias="Sylius\Behat\Client\ResponseChecker"/>

If you decide to enable kernel resets later, uncomment the tag and add a simple reset() method to the class (see comment on ResponseChecker.php).

src/Sylius/Behat/Client/ResponseChecker.php (1)

305-321: Add a reset hook to avoid any cross-scenario leakage (optional).

The service is stateful by design and relies on DebugContext to clear errors after each step. As a safety net (e.g., on abrupt failures), consider adding a reset() method and tagging the service with kernel.reset so the container clears state on kernel resets.

Apply in this class:

     public function getDebugErrors(): array
     {
         return $this->errors;
     }
+
+    /**
+     * Optional: allows Symfony's "kernel.reset" to clear service state.
+     * Tag the service with <tag name="kernel.reset" method="reset"/> to activate.
+     */
+    public function reset(): void
+    {
+        $this->cleanErrors();
+    }

And (if you choose to adopt it) add the XML tag as shown in the api.xml comment. I can wire this across the PR if you want.

src/Sylius/Behat/Context/Api/DebugContext.php (1)

49-66: Harden JSON formatting and consider a scenario-level reset.

  • Guard against json_encode returning false and preg_replace returning null.
  • Optional: clear stacks at scenario start to avoid any leftovers if previous cleanup was skipped.
     /** @AfterScenario */
     public function afterScenario(): void
     {
         if (!empty($this->errorStack)) {
             $output = new ConsoleOutput();
             $styleKey = new OutputFormatterStyle('cyan');
             $styleValue = new OutputFormatterStyle('green');
             $output->getFormatter()->setStyle('key', $styleKey);
             $output->getFormatter()->setStyle('value', $styleValue);
 
-            $json = json_encode($this->errorStack, \JSON_PRETTY_PRINT);
-
-            $formattedJson = preg_replace('/"([^"]+)":/', '<key>"$1"</key>:', $json);
-            $formattedJson = preg_replace('/: "([^"]+)"/', ': <value>"$1"</value>', $formattedJson);
-
-            $output->writeln($formattedJson);
+            $json = json_encode($this->errorStack, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE);
+            if ($json === false) {
+                $output->writeln('<error>Failed to encode API debug errors</error>');
+                return;
+            }
+
+            $formattedJson = preg_replace('/"([^"]+)":/', '<key>"$1"</key>:', $json) ?? $json;
+            $formattedJson = preg_replace('/: "([^"]+)"/', ': <value>"$1"</value>', $formattedJson) ?? $formattedJson;
+
+            $output->writeln($formattedJson);
         }
     }
+
+    /** @BeforeScenario */
+    public function beforeScenario(): void
+    {
+        // Defensive cleanup in case a previous scenario aborted mid-step
+        $this->errorStack = [];
+        $this->responseChecker->cleanErrors();
+    }

If you’d like, I can also switch the pretty-printing to VarDumper for richer CLI output.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 24d544a and 7d77406.

📒 Files selected for processing (73)
  • src/Sylius/Behat/Client/ApiPlatformClient.php (2 hunks)
  • src/Sylius/Behat/Client/ResponseChecker.php (2 hunks)
  • src/Sylius/Behat/Client/ResponseCheckerInterface.php (1 hunks)
  • src/Sylius/Behat/Context/Api/DebugContext.php (1 hunks)
  • src/Sylius/Behat/Context/Api/DebugErrorType.php (1 hunks)
  • src/Sylius/Behat/Resources/config/services/api.xml (2 hunks)
  • src/Sylius/Behat/Resources/config/services/contexts/api/common.xml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/account/address_book.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/account/customer.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/account/customer_registration.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/account/email_verification.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/account/login.yaml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/addressing/managing_countries.yaml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/addressing/managing_zones.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/admin/dashboard.yaml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/admin/locale.yaml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/admin/login.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/admin/security.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/cart/accessing_cart.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/cart/shopping_cart.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/channel/channels.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/channel/managing_channels.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/checkout/checkout.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/checkout/paying_for_order.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/contact/requesting_contact.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/currency/currencies.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/currency/managing_currencies.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/currency/managing_exchange_rates.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/currency/viewing_exchange_rates.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/homepage/viewing_products.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/inventory/managing_inventory.yaml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/locale/locales.yaml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/locale/managing_locales.yaml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/order/managing_orders.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/order/modifying_placed_order_address.yaml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/order/order_history.yaml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/payment/managing_payment_methods.yaml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/payment/managing_payments.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/product/adding_product_review.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/product/managing_product_association_types.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/product/managing_product_attributes.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/product/managing_product_options.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/product/managing_product_reviews.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/product/managing_product_variants.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/product/managing_products.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/product/viewing_price_history.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/product/viewing_price_history_after_catalog_promotions.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/product/viewing_product_in_admin_panel.yaml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/product/viewing_product_reviews.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/product/viewing_product_variants.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/product/viewing_products.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/promotion/applying_catalog_promotions.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/promotion/applying_promotion_coupon.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/promotion/applying_promotion_rules.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/promotion/managing_catalog_promotions.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/promotion/managing_promotion_coupons.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/promotion/managing_promotions.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/promotion/receiving_discount.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/promotion/removing_catalog_promotions.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/shipping/applying_shipping_fee.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/shipping/applying_shipping_method_rules.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/shipping/managing_shipments.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/shipping/managing_shipping_categories.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/shipping/managing_shipping_methods.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/shipping/viewing_shipping_methods.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/taxation/applying_taxes.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/taxation/managing_tax_categories.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/taxation/managing_tax_rates.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/taxon/managing_taxons.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/user/managing_administrators.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/user/managing_customer_groups.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/user/managing_customers.yml (1 hunks)
  • src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (8)
src/Sylius/Behat/Resources/config/suites/api/account/email_verification.yml (1)
src/Sylius/Behat/Context/Setup/UserContext.php (6)
  • UserContext (27-213)
  • aVerificationEmailHasBeenSentTo (132-137)
  • iHaveReceivedVerificationEmail (124-127)
  • accountIsNotVerified (114-119)
  • prepareUserVerification (157-165)
  • iHaveAlreadyVerifiedMyAccount (142-147)
src/Sylius/Behat/Resources/config/suites/api/product/viewing_product_reviews.yml (1)
src/Sylius/Bundle/CoreBundle/Fixture/Factory/ProductReviewExampleFactory.php (1)
  • ProductReviewExampleFactory (32-102)
src/Sylius/Behat/Resources/config/suites/api/cart/accessing_cart.yml (1)
src/Sylius/Behat/Context/Setup/UserContext.php (1)
  • UserContext (27-213)
src/Sylius/Behat/Client/ApiPlatformClient.php (1)
src/Sylius/Behat/Client/ResponseChecker.php (1)
  • appendError (305-310)
src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml (1)
src/Sylius/Behat/Context/Setup/UserContext.php (6)
  • UserContext (27-213)
  • iveChangedMyPasswordFromTo (200-212)
  • hisAccountWasDeleted (102-108)
  • theCustomerCreatedAccountWithPassword (74-83)
  • accountIsNotVerified (114-119)
  • accountWasDeleted (89-97)
src/Sylius/Behat/Client/ResponseCheckerInterface.php (1)
src/Sylius/Behat/Client/ResponseChecker.php (2)
  • cleanErrors (312-315)
  • getDebugErrors (317-320)
src/Sylius/Behat/Client/ResponseChecker.php (2)
src/Sylius/Behat/Client/ApiPlatformClient.php (1)
  • __construct (28-36)
src/Sylius/Behat/Client/ResponseCheckerInterface.php (3)
  • getError (34-34)
  • cleanErrors (96-96)
  • getDebugErrors (104-104)
src/Sylius/Behat/Resources/config/suites/api/user/managing_customer_groups.yml (1)
src/Sylius/Bundle/CoreBundle/Fixture/Factory/CustomerGroupExampleFactory.php (1)
  • CustomerGroupExampleFactory (25-59)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Static checks / PHP 8.2, Symfony ^6.4
  • GitHub Check: Static checks / PHP 8.4, Symfony ^7.2
  • GitHub Check: Static checks / PHP 8.3, Symfony ^7.2
🔇 Additional comments (63)
src/Sylius/Behat/Resources/config/suites/api/user/managing_administrators.yml (1)

22-23: LGTM — enabling the debug context for this suite is appropriate.

Placement after API response/save contexts makes sense; the context only uses hooks and has no step definitions, so ordering is safe.

src/Sylius/Behat/Resources/config/suites/api/admin/locale.yaml (1)

23-24: LGTM — consistent addition of the debug context.

No ordering conflicts with existing transform/setup contexts.

src/Sylius/Behat/Resources/config/suites/api/addressing/managing_countries.yaml (1)

23-24: LGTM — debug context added.

Consistent with other suites. No functional concerns.

src/Sylius/Behat/Resources/config/suites/api/promotion/applying_catalog_promotions.yml (1)

32-33: LGTM — debug context placement makes sense.

Positioned after admin save; hooks-only context so ordering is flexible.

src/Sylius/Behat/Resources/config/suites/api/account/login.yaml (2)

21-21: Add debug context — looks good.

Registering sylius.behat.context.api.debug in this suite is consistent with the PR’s goal and won’t affect step resolution.


21-21: DebugContext Hook and State Reset Verified – No Changes Required

I’ve confirmed that:

  • The DebugContext::afterStep() method is annotated with @AfterStep and, since the debug context is registered last in common.xml, it will run after other contexts at the default priority.
  • Within that hook, any collected errors are output before calling $this->responseChecker->cleanErrors(), ensuring the checker’s state is reset at the end of each step.
  • Although ResponseChecker is a shared service, its per-step cleanup guarantees no stale errors persist between steps.

No further changes are needed here.

src/Sylius/Behat/Resources/config/suites/api/addressing/managing_zones.yml (1)

24-24: Add debug context — looks good.

The placement alongside admin API contexts is sensible.

src/Sylius/Behat/Resources/config/suites/api/product/managing_product_options.yml (1)

27-27: Add debug context — looks good.

Matches the pattern used in other API suites.

src/Sylius/Behat/Resources/config/suites/api/taxon/managing_taxons.yml (1)

28-28: Add debug context — looks good.

No conflicts with existing admin contexts.

src/Sylius/Behat/Resources/config/suites/api/account/customer.yml (1)

37-37: Add debug context — looks good.

Helpful in customer flows with multiple chained API calls.

src/Sylius/Behat/Resources/config/suites/api/shipping/managing_shipping_categories.yml (1)

20-20: Debug context presence confirmed

  • Verified that sylius.behat.context.api.debug appears exactly once at line 20 in src/Sylius/Behat/Resources/config/suites/api/shipping/managing_shipping_categories.yml.

No further action required—changes are aligned with other admin API suites.

src/Sylius/Behat/Resources/config/suites/api/shipping/managing_shipping_methods.yml (2)

35-35: Add debug context for API error surfacing — looks good.

Including sylius.behat.context.api.debug here will help correlate failing API responses with their originating steps.


31-36: Hook execution order — confirm DebugContext priorities.

If DebugContext relies on running last to print/flush collected errors, ensure its hook priority is lower (runs later) than other AfterStep/AfterScenario hooks in this suite. Config order isn’t guaranteed to control hook order; Behat priorities do.

src/Sylius/Behat/Resources/config/suites/api/product/managing_product_attributes.yml (2)

24-24: Debug context inclusion acknowledged.

Good addition; it should improve failure diagnostics for product attribute API steps.


20-25: Consistency check across product-related suites.

For consistent diagnostics, ensure all product-oriented API suites (options, association types, taxons, etc.) also include the debug context in this PR or a follow-up, to avoid uneven visibility of API errors.

src/Sylius/Behat/Resources/config/suites/api/account/customer_registration.yml (2)

22-22: Adding debug context to customer registration — approved.

This should help when registration flows return non-2xx responses (validation, uniqueness, etc.).


22-25: Verify hook priority vs. email context.

If email assertions/cleanups have AfterStep/AfterScenario hooks, confirm DebugContext’s priority ensures errors are printed after those hooks have had a chance to act, or that order doesn’t matter for your printing logic.

src/Sylius/Behat/Resources/config/suites/api/locale/locales.yaml (1)

19-19: Locales suite gains debug context — approved.

Placement among shop contexts is fine; it should capture non-success locale/cart/channel endpoints used in these scenarios.

src/Sylius/Behat/Resources/config/suites/api/locale/managing_locales.yaml (2)

20-20: Managing locales now debuggable — good change.

This will surface API validation/permission errors next to the failing step for admin locale management.


19-21: Service wiring sanity check.

Please confirm sylius.behat.context.api.debug is registered in services/contexts/api/common.xml for the 2.1 target and that ApiPlatformClient is injecting ResponseCheckerInterface in this branch, otherwise the debug context may have nothing to print.

src/Sylius/Behat/Resources/config/suites/api/product/managing_product_variants.yml (1)

46-46: Add debug context — LGTM

The placement right after admin translation keeps the admin API contexts grouped and should allow the debug hooks to observe responses from prior steps.

src/Sylius/Behat/Resources/config/suites/api/taxation/managing_tax_categories.yml (2)

19-19: Add debug context — LGTM

Placed after admin save/response which is consistent with other suites and should ensure response collection is available for the following steps.


4-24: Service wiring verification successful

All checks confirm that the Behat API debugging context and related interfaces are correctly wired:

  • The sylius.behat.context.api.debug service is defined in src/Sylius/Behat/Resources/config/services/contexts/api/common.xml and injects the ResponseCheckerInterface as expected.
  • The ResponseCheckerInterface declares both cleanErrors(): void and getDebugErrors(): array methods in ResponseCheckerInterface.php.
  • The ApiPlatformClient constructor (in ApiPlatformClient.php) receives a ResponseCheckerInterface instance via a readonly property, ensuring the updated interface is used.

No further changes are required.

src/Sylius/Behat/Resources/config/suites/api/user/managing_customer_groups.yml (1)

19-19: Add debug context — LGTM

Keeping admin managing/response/save contexts and appending the debug context is safe and preserves existing step definitions while enabling error printing.

src/Sylius/Behat/Resources/config/suites/api/payment/managing_payment_methods.yaml (1)

34-34: Add debug context — LGTM

Inserted after admin translation; consistent with other suites and should capture non-2xx responses during steps.

src/Sylius/Behat/Resources/config/suites/api/promotion/managing_catalog_promotions.yml (1)

31-31: Add debug context — LGTM

Placed before shop contexts so it participates in hooks for admin-side steps and still remains available for later steps if needed.

src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml (2)

21-21: Enable API debug context — good addition

Adding sylius.behat.context.api.debug should help surface API failures tied to steps without affecting existing steps.


20-22: Contexts are not redundant – no changes needed

Each of the contexts loaded in managing_users.yml (lines 20–22) has a distinct responsibility and should all remain:

  • sylius.behat.context.api.admin.response provides step definitions for asserting API response success or handling violations via the shared ResponseContext.
  • sylius.behat.context.api.debug captures and pretty-prints debug errors after each scenario, without affecting response assertions.
  • sylius.behat.context.api.shop.login implements the customer login flow, which is separate from admin login and required by the suite’s scenarios.

Removing any of these would break existing step definitions or disable the debug output; there’s no overlap in functionality.

Likely an incorrect or invalid review comment.

src/Sylius/Behat/Resources/config/suites/api/product/viewing_products.yml (1)

36-36: LGTM: Debug context added to product viewing suite

Good, consistent with other API suites; should improve failure diagnosability without affecting step definitions.

src/Sylius/Behat/Context/Api/DebugErrorType.php (1)

16-20: LGTM: Minimal, clear string-backed enum

Enum cases are explicit and future-proof. Works well for structured reporting and serialization.

src/Sylius/Behat/Resources/config/suites/api/currency/currencies.yml (1)

18-18: LGTM: Debug context introduced to currencies suite

Consistent adoption; no config pitfalls spotted.

src/Sylius/Behat/Resources/config/suites/api/account/address_book.yml (1)

36-36: LGTM: Debug context added to address book suite

Alignment with the broader test suites; should aid triage of API-related failures.

src/Sylius/Behat/Resources/config/suites/api/channel/channels.yml (1)

15-15: Debug context wiring verified—nothing critical outstanding

  • The sylius.behat.context.api.debug service is declared exactly once in src/Sylius/Behat/Resources/config/services/contexts/api/common.xml.
  • The DebugContext class implements both @AfterStep and @AfterScenario hooks (default priority). If you need deterministic “last-run” behavior, you can add explicit negative priorities (e.g. @AfterStep(priority=-10), @AfterScenario(priority=-10)) or simply move this context entry to the end of your suite.
  • The ResponseCheckerInterface exposes cleanErrors() and getDebugErrors() methods.
  • The ApiPlatformClient appends non-success HTTP responses via $this->responseChecker->appendError().

Optional readability tweak—place debug context last in your suite:

-                - sylius.behat.context.api.debug
                 - sylius.behat.context.api.shop.channel
                 - sylius.behat.context.api.shop.homepage
+                - sylius.behat.context.api.debug
src/Sylius/Behat/Resources/config/suites/api/product/viewing_price_history.yml (1)

25-25: Confirm admin API contexts for viewing price history
The sylius.behat.context.api.debug entry is present and already last in the contexts: list of
src/Sylius/Behat/Resources/config/suites/api/product/viewing_price_history.yml.
Please double-check that all required admin API contexts (e.g., channel_pricing_log_entry, managing_product_variants, save) remain in the PR, as scenarios tagged @viewing_price_history && @api depend on them.

src/Sylius/Behat/Resources/config/suites/api/shipping/viewing_shipping_methods.yml (1)

35-39: Debug context present in all API suites

  • Verified that every file in src/Sylius/Behat/Resources/config/suites/api/ contains exactly one occurrence of sylius.behat.context.api.debug.
  • No suites are missing the debug context, and there are no duplicate entries.
src/Sylius/Behat/Resources/config/suites/api/product/viewing_product_reviews.yml (1)

21-24: LGTM; consider ensuring the debug hook runs last

If DebugContext uses AfterStep/AfterScenario hooks, make sure its hook priority ensures it runs after other API contexts manipulating responses. YAML order isn’t a reliable execution guarantee in Behat.

Please confirm DebugContext’s hook annotations explicitly set priority (e.g., a higher magnitude to run deterministically last among AfterStep hooks).

src/Sylius/Behat/Resources/config/suites/api/product/viewing_product_variants.yml (2)

21-21: LGTM: Debug context added to API suite

Adding sylius.behat.context.api.debug here aligns with the PR goal and should improve post-step diagnostics for API failures in this suite. Placement before the api.shop.* contexts is fine.


21-21: Debug context service verified – no duplicates detected

  • The sylius.behat.context.api.debug service is defined in src/Sylius/Behat/Resources/config/services/contexts/api/common.xml (line 36).
  • The DebugContext class exists at src/Sylius/Behat/Context/Api/DebugContext.php (namespace Sylius\Behat\Context\Api, class declared on line 22).
  • No suite YAML file includes the sylius.behat.context.api.debug entry more than once.

All checks pass.

src/Sylius/Behat/Resources/config/suites/api/promotion/managing_promotion_coupons.yml (1)

32-32: LGTM: Debug context enabled for promotion coupons management

Good addition; this will surface failing API responses alongside the step.

src/Sylius/Behat/Resources/config/suites/api/taxation/managing_tax_rates.yml (2)

23-23: LGTM: Debug context included for tax rates management

Looks correct and consistent with the broader PR pattern.


23-23: DebugContext hook compatibility confirmed: ordering is safe
The DebugContext only defines @AfterStep and @AfterScenario hooks—no before hooks are present—so its position in the suite’s context list does not affect initialization.

  • If any @BeforeStep or @BeforeScenario logic is ever added to DebugContext, ensure this context is listed before other API contexts to initialize early.
src/Sylius/Behat/Resources/config/suites/api/user/managing_customers.yml (1)

33-33: LGTM: Debug context added to customers management suite

This should help correlate failing API calls with the exact Behat step during customer management scenarios. Placement between admin save and shop login contexts is acceptable.

src/Sylius/Behat/Resources/config/suites/api/product/viewing_price_history_after_catalog_promotions.yml (1)

25-25: LGTM: Debug context appended to price history after catalog promotions

Good call—errors during catalog promotion operations can be opaque; this will improve troubleshooting.

src/Sylius/Behat/Resources/config/suites/api/order/managing_orders.yml (1)

55-55: Confirm debug context service registration and usage

  • The service sylius.behat.context.api.debug is declared in
    src/Sylius/Behat/Resources/config/services/contexts/api/common.xml (line 36).
  • It is referenced exactly once in each API suite (including managing_orders.yml at line 55).
  • No suite file includes this context multiple times.

No changes required.

src/Sylius/Behat/Resources/config/suites/api/shipping/managing_shipments.yml (1)

34-36: Add debug context: ordering matches the intended pattern

Placed right after sylius.behat.context.api.admin.managing_shipments and before sylius.behat.context.api.email, which is consistent with other suites.

If not already done, please run the verification script from my other comment to ensure there are no duplicate inclusions across suites.

src/Sylius/Behat/Resources/config/suites/api/contact/requesting_contact.yml (1)

16-19: Add debug context: fits correctly before API email context

Ordering looks good: after setup contexts and before sylius.behat.context.api.email. This should allow the debug hook to capture API errors tied to steps without affecting step resolution.

Use the shared verification script to confirm single inclusion and proper service registration.

src/Sylius/Behat/Resources/config/suites/api/admin/login.yml (1)

19-22: Add debug context: consistent placement in admin suite

Inserted after admin API contexts and before email; consistent with the pattern used elsewhere. No issues spotted.

Leverage the shared verification script to ensure consistency across all admin-related suites.

src/Sylius/Behat/Resources/config/suites/api/product/adding_product_review.yml (1)

21-25: Add debug context: sensible positioning with shop API contexts

Positioned immediately before shop API contexts and after security setup; this should work well with AfterStep/AfterScenario hooks in the debug context.

Run the shared verification script to validate presence and uniqueness across product-related suites as well.

src/Sylius/Behat/Resources/config/suites/api/shipping/applying_shipping_fee.yml (1)

43-43: LGTM: consistent placement among shop API contexts

The debug context is added right before the shop API contexts, consistent with other suites in this PR. This should reliably print API errors tied to the failing step without interfering with step matching.

src/Sylius/Behat/Resources/config/suites/api/cart/accessing_cart.yml (1)

32-32: LGTM: enables per-step API error visibility for cart scenarios

The addition is correct and positioned analogously to other API shop suites. No ordering concerns since the context only contributes hooks.

src/Sylius/Behat/Resources/config/suites/api/inventory/managing_inventory.yaml (2)

33-33: Adding sylius.behat.context.api.debug here looks good

The context is correctly added to the api_managing_inventory suite and placed near admin API response/save contexts, which makes sense for debugging API-related steps.


33-33: DebugContext ordering is already correct

  • Verified that DebugContext in src/Sylius/Behat/Context/Api/DebugContext.php declares both @AfterStep and @AfterScenario hooks, confirming its role in gathering post-step and post-scenario debug output.
  • In src/Sylius/Behat/Resources/config/suites/api/inventory/managing_inventory.yaml, the entry
    - sylius.behat.context.api.debug
    is already the last context listed (immediately before the filters: section), ensuring that debug hooks run after all other contexts in this suite.
  • No adjustments needed for hook ordering in this file.
src/Sylius/Behat/Resources/config/suites/api/taxation/applying_taxes.yml (1)

40-40: Good addition of sylius.behat.context.api.debug to the taxation suite

Enables unified API error visibility during tax application scenarios without altering suite tags/JS settings.

src/Sylius/Behat/Resources/config/suites/api/promotion/applying_promotion_coupon.yml (1)

35-35: LGTM: debug context added to promotion coupon suite

This aligns the suite with the broader debugging capability introduced in the PR.

src/Sylius/Behat/Resources/config/suites/api/shipping/applying_shipping_method_rules.yml (1)

36-36: Debug context correctly enabled for shipping method rules suite

No conflicts with existing contexts; consistent with other API suites in this PR.

src/Sylius/Behat/Resources/config/suites/api/promotion/managing_promotions.yml (1)

41-41: Nice: debug context added without removing existing admin translation context

Both translation and debug contexts being present should preserve existing steps while adding error debugging. Good balance between functionality and safety.

src/Sylius/Behat/Resources/config/suites/api/admin/security.yml (1)

21-21: LGTM — debug context enabled for admin security suite

No ordering concerns; DebugContext should not interfere with step definitions.

src/Sylius/Behat/Resources/config/suites/api/currency/managing_currencies.yml (1)

19-19: Added API debug context to the suite — looks good

This enables per-step API error surfacing for the currency suite. No ordering conflicts detected with existing transform/setup contexts.

src/Sylius/Behat/Resources/config/services/contexts/api/common.xml (1)

36-38: DI registration of DebugContext is correct

  • Public service fits Behat’s context discovery via service IDs.
  • Injecting the ResponseCheckerInterface keeps the context decoupled from the client.

No issues from a wiring perspective given other contexts already reference the same interface service.

src/Sylius/Behat/Resources/config/suites/api/product/managing_product_reviews.yml (1)

25-25: Added API debug context to product reviews — OK

Consistent with other API suites and placed after response/save contexts. Good for consolidated debugging output.

src/Sylius/Behat/Resources/config/suites/api/admin/dashboard.yaml (1)

36-36: Admin dashboard suite now includes API debug context — OK

This should help pinpoint failing steps on dashboard-related API interactions.

src/Sylius/Behat/Resources/config/services/api.xml (1)

16-22: ApiPlatformClient wiring: constructor arg order looks correct.

The injected ResponseCheckerInterface is placed after RequestFactory and before the authorization header, matching ApiPlatformClient’s constructor. Child services supply the "section" argument, so the inheritance chain remains valid.

src/Sylius/Behat/Client/ResponseChecker.php (1)

23-29: State initialization for error buffer is fine.

Private typed array + explicit constructor initialization is clear and safe.

private readonly AbstractBrowser $client,
private readonly SharedStorageInterface $sharedStorage,
private readonly RequestFactoryInterface $requestFactory,
private readonly ResponseCheckerInterface $responseChecker,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Constructor signature change — verify DI definitions and direct instantiations

Adding ResponseCheckerInterface is fine, but please ensure:

  • All service definitions for ApiPlatformClient (admin and shop) are updated to pass this dependency.
  • There are no direct new ApiPlatformClient(...) usages that will now be arity-incompatible.

Run the script to confirm wiring and detect any manual instantiations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "==> Check service definitions referencing ApiPlatformClient"
rg -n --type=xml -C3 'ApiPlatformClient' src | sed -n '1,200p'

echo
echo "==> Look for direct instantiations of ApiPlatformClient"
rg -nP --type=php -C2 '\bnew\s+ApiPlatformClient\s*\(' || true

echo
echo "==> Verify ResponseChecker has the new methods and (optionally) detect accidental duplicates"
rg -nP --type=php '\bclass\s+ResponseChecker\b|function\s+(appendError|cleanErrors|getDebugErrors)\s*\(' src | sed -n '1,200p'

Length of output: 3393


Constructor signature change — update service definitions for ResponseChecker injection

The ApiPlatformClient constructor now requires a ResponseCheckerInterface. While no direct instantiations (new ApiPlatformClient(...)) were found and your ResponseChecker implementation already exposes appendError(), cleanErrors(), and getDebugErrors(), the DI config must be updated to avoid runtime errors.

Please update src/Sylius/Behat/Resources/config/services/api.xml as follows:

• In the abstract service sylius.behat.api_platform_client, add the response_checker service argument after the authorization header.
• The shop and admin child services will inherit this new argument automatically.

--- a/src/Sylius/Behat/Resources/config/services/api.xml
+++ b/src/Sylius/Behat/Resources/config/services/api.xml
@@ -16,6 +16,7 @@
         <service id="sylius.behat.api_platform_client" class="Sylius\Behat\Client\ApiPlatformClient" abstract="true">
             <argument type="service" id="test.client" />
             <argument type="service" id="sylius.behat.shared_storage" />
             <argument type="service" id="sylius.behat.request_factory" />
             <argument>%sylius.api.authorization_header%</argument>
+            <argument type="service" id="sylius.behat.response_checker" />
         </service>
 
         <service id="sylius.behat.api_platform_client.shop" class="Sylius\Behat\Client\ApiPlatformClient" parent="sylius.behat.api_platform_client">
🤖 Prompt for AI Agents
In src/Sylius/Behat/Client/ApiPlatformClient.php around line 32, the constructor
now requires a ResponseCheckerInterface but the DI config wasn't updated; open
src/Sylius/Behat/Resources/config/services/api.xml and add the response_checker
service argument to the abstract service sylius.behat.api_platform_client
immediately after the authorization header argument so both child services (shop
and admin) inherit it; reference the concrete service that implements
ResponseCheckerInterface (for example sylius.behat.response_checker) as the new
argument.

Comment on lines +95 to +104

public function cleanErrors(): void;

/** @return array{
* step: string,
* type: string,
* error: string[]
* }
*/
public function getDebugErrors(): array;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Fix getDebugErrors() return description — shape does not match the implementation.

ResponseChecker::getDebugErrors() returns the raw list of error strings (see ResponseChecker.php:316-319), while this docblock declares a structured array with keys step, type, error. That structure is assembled by DebugContext, not returned by the checker.

Apply this diff to align the contract:

-    /** @return array{
-     *     step: string,
-     *     type: string,
-     *     error: string[]
-     * }
-     */
+    /** @return list<string> */
     public function getDebugErrors(): array;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public function cleanErrors(): void;
/** @return array{
* step: string,
* type: string,
* error: string[]
* }
*/
public function getDebugErrors(): array;
public function cleanErrors(): void;
/** @return list<string> */
public function getDebugErrors(): array;
🤖 Prompt for AI Agents
In src/Sylius/Behat/Client/ResponseCheckerInterface.php around lines 95 to 104,
the docblock for getDebugErrors() claims it returns a structured array with keys
step/type/error, but the implementation actually returns a raw list of error
strings; update the docblock to reflect the real return type (an array of
strings, e.g. string[] or array<int,string>) so the interface contract matches
ResponseChecker::getDebugErrors() and remove the incorrect structured shape
description.

Comment on lines +24 to +26
/** @var array<int, array{type: DebugErrorType, error: string}> */
private array $errorStack = [];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix phpdoc shape: it doesn’t match the stored payload.

The stack stores step (string), type (enum), and error (array of strings). Update the docblock accordingly and store a scalar for type to ensure predictable JSON.

-    /** @var array<int, array{type: DebugErrorType, error: string}> */
+    /** @var array<int, array{step: string, type: string, error: list<string>}> */
     private array $errorStack = [];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/** @var array<int, array{type: DebugErrorType, error: string}> */
private array $errorStack = [];
/** @var array<int, array{step: string, type: string, error: list<string>}> */
private array $errorStack = [];
🤖 Prompt for AI Agents
In src/Sylius/Behat/Context/Api/DebugContext.php around lines 24 to 26, the @var
phpdoc is wrong: the stack actually stores step (string), type as a scalar
string (not enum object), and error as an array of strings; update the docblock
shape to /** @var array<int, array{step: string, type: string, error: string[]}>
*/ and audit places that push into $errorStack to store the enum as a scalar
(e.g. use the enum's value or cast to string) and ensure the error field is an
array of strings before pushing.

Comment on lines +40 to +47
$this->errorStack[] = [
'step' => $scope->getStep()->getText(),
'type' => DebugErrorType::API_RESPONSE,
'error' => $debugErrors,
];

$this->responseChecker->cleanErrors();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Emit enum type as a string to guarantee JSON safety.

json_encode on unit enums is not guaranteed to produce a useful value. Use ->name (or ->value for backed enums).

         $this->errorStack[] = [
             'step' => $scope->getStep()->getText(),
-            'type' => DebugErrorType::API_RESPONSE,
+            'type' => DebugErrorType::API_RESPONSE->name,
             'error' => $debugErrors,
         ];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$this->errorStack[] = [
'step' => $scope->getStep()->getText(),
'type' => DebugErrorType::API_RESPONSE,
'error' => $debugErrors,
];
$this->responseChecker->cleanErrors();
}
$this->errorStack[] = [
'step' => $scope->getStep()->getText(),
'type' => DebugErrorType::API_RESPONSE->name,
'error' => $debugErrors,
];
$this->responseChecker->cleanErrors();
}
🤖 Prompt for AI Agents
In src/Sylius/Behat/Context/Api/DebugContext.php around lines 40 to 47, the enum
DebugErrorType is stored directly into the error stack which can produce
non-useful output when JSON-encoding; change the 'type' entry to emit a string
(for unit enums use ->name, for backed enums use ->value) — e.g. set 'type' =>
DebugErrorType::API_RESPONSE->name (or cast to (string) if using backed enums)
so the array contains a JSON-safe scalar before calling json_encode.

- sylius.behat.context.setup.user
- sylius.behat.context.setup.zone

- sylius.behat.context.api.debug
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Redact sensitive data before printing debug output.

Customer/account APIs often include PII and auth tokens. Ensure DebugContext/ResponseChecker redact headers (Authorization, Cookie, Set-Cookie) and sensitive JSON fields (password, token, email) before writing to logs to prevent leakage in CI artifacts.

Example sanitization helper to add in DebugContext (or ResponseChecker) before printing/storing:

<?php
private const SENSITIVE_HEADERS = ['authorization','cookie','set-cookie','x-api-key','x-auth-token'];
private const SENSITIVE_FIELDS  = ['password','currentPassword','newPassword','token','access_token','refresh_token','email'];

private function sanitize(array $entry): array
{
    if (isset($entry['request']['headers'])) {
        foreach ($entry['request']['headers'] as $k => $v) {
            if (in_array(strtolower($k), self::SENSITIVE_HEADERS, true)) {
                $entry['request']['headers'][$k] = '***REDACTED***';
            }
        }
    }
    if (isset($entry['response']['headers'])) {
        foreach ($entry['response']['headers'] as $k => $v) {
            if (in_array(strtolower($k), self::SENSITIVE_HEADERS, true)) {
                $entry['response']['headers'][$k] = '***REDACTED***';
            }
        }
    }
    foreach (['request','response'] as $side) {
        if (isset($entry[$side]['body']) && is_array($entry[$side]['body'])) {
            array_walk_recursive($entry[$side]['body'], function (&$value, $key) {
                if (in_array($key, self::SENSITIVE_FIELDS, true)) {
                    $value = '***REDACTED***';
                }
            });
        }
    }
    return $entry;
}

Verification script:


🏁 Script executed:

#!/bin/bash
# Expect to find a redaction step or explicit omission of sensitive data before printing.
rg -nC2 -i 'redact|sanitize|Authorization|Set-Cookie|password|access_token|refresh_token' \
  src/Sylius/Behat/Context/Api/DebugContext.php src/Sylius/Behat/Client/ResponseChecker.php

Length of output: 181


🏁 Script executed:

#!/bin/bash
# Confirm existence of DebugContext and ResponseChecker and inspect for sanitization code

# Locate the files
echo "Locating DebugContext.php..."
fd DebugContext.php -t f || echo "DebugContext.php not found"
echo "Locating ResponseChecker.php..."
fd ResponseChecker.php -t f || echo "ResponseChecker.php not found"

# Show the first 100 lines of each (verify presence of debug-printing methods)
for file in $(fd DebugContext.php -t f); do
  echo "=== $file (lines 1–100) ==="
  sed -n '1,100p' "$file"
done

for file in $(fd ResponseChecker.php -t f); do
  echo "=== $file (lines 1–100) ==="
  sed -n '1,100p' "$file"
done

# Search for any redaction/sanitization implementations in these directories
echo "Searching for sanitize/redact implementations..."
rg -nC2 -i 'sanitize|redact|mask|obfuscate|filter' src/Sylius/Behat/Context/Api src/Sylius/Behat/Client

Length of output: 91733


Sensitive Data Leakage: Add Redaction in Debug Logging

The current implementation of debug logging in DebugContext and error collection in ResponseChecker writes raw headers and JSON bodies to the console, which may include PII (emails, passwords, tokens) and sensitive headers (Authorization, Cookie). No sanitization was found in either class.

Please address the following critical fixes:

  • src/Sylius/Behat/Context/Api/DebugContext.php
    • In afterScenario(), sanitize each entry in $this->errorStack before json_encode/writeln.
    • Add a sanitize(array $entry): array helper (see example below) and apply it to both request and response data.

  • src/Sylius/Behat/Client/ResponseChecker.php
    • Before collecting or returning any response content that may be logged (e.g., in getDebugErrors()), redact sensitive headers and JSON fields.
    • Consider moving the sanitization helper into ResponseChecker so that DebugContext can rely on already-redacted data.

Example diff for DebugContext.php:

--- a/src/Sylius/Behat/Context/Api/DebugContext.php
+++ b/src/Sylius/Behat/Context/Api/DebugContext.php
@@ public function afterStep(AfterStepScope $scope): void
-        $debugErrors = $this->responseChecker->getDebugErrors();
+        // Sanitize all debug error entries before logging
+        $debugErrors = array_map(
+            [$this, 'sanitize'],
+            $this->responseChecker->getDebugErrors()
+        );
 
         if (empty($debugErrors)) {
             return;
         }
@@ class DebugContext implements Context
+    private const SENSITIVE_HEADERS = ['authorization','cookie','set-cookie','x-api-key','x-auth-token'];
+    private const SENSITIVE_FIELDS  = ['password','currentPassword','newPassword','token','access_token','refresh_token','email'];
+
+    private function sanitize(array $entry): array
+    {
+        foreach (['request','response'] as $side) {
+            // Redact headers
+            if (isset($entry[$side]['headers'])) {
+                foreach ($entry[$side]['headers'] as $k => $v) {
+                    if (in_array(strtolower($k), self::SENSITIVE_HEADERS, true)) {
+                        $entry[$side]['headers'][$k] = '***REDACTED***';
+                    }
+                }
+            }
+            // Redact JSON fields
+            if (isset($entry[$side]['body']) && is_array($entry[$side]['body'])) {
+                array_walk_recursive($entry[$side]['body'], function (&$value, $key) {
+                    if (in_array($key, self::SENSITIVE_FIELDS, true)) {
+                        $value = '***REDACTED***';
+                    }
+                });
+            }
+        }
+        return $entry;
+    }

Ensure that any consumer of ResponseChecker::getDebugErrors() or other debug output paths also applies equivalent sanitization.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/Sylius/Behat/Context/Api/DebugContext.php (around afterScenario) and
src/Sylius/Behat/Client/ResponseChecker.php (methods that collect/return debug
errors like getDebugErrors), implement a sanitization strategy: add a
sanitize(array $entry): array helper in ResponseChecker (so DebugContext can
rely on it) that redacts sensitive headers (Authorization, Cookie, Set-Cookie)
and sensitive JSON fields (password, pass, pwd, token, access_token,
refresh_token, secret, api_key, email, username, card_number, ssn, and similar)
by replacing values with "[REDACTED]"; update ResponseChecker to apply this
sanitizer before storing or returning any debug/error payloads; update
DebugContext::afterScenario to call ResponseChecker::sanitize on each
$this->errorStack entry before json_encode()/writeln so no raw headers or bodies
are logged; ensure sanitizer handles nested arrays and JSON strings (decode,
sanitize, re-encode) and that all consumers of getDebugErrors() use the
sanitized output.

- sylius.behat.context.api.admin.managing_exchange_rates
- sylius.behat.context.api.admin.response
- sylius.behat.context.api.admin.save
- sylius.behat.context.api.debug
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Good addition: enabling API debug context for this suite

Adding sylius.behat.context.api.debug here aligns with the PR goal and should help surface failing API responses next to the failing step. Placement alongside other API/admin response contexts is fine.

Run the quick checks below to ensure the service is wired and to spot any suites still missing the debug context:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Ensure the debug context service is defined"
rg -n -C2 -g 'src/**' $'sylius\\.behat\\.context\\.api\\.debug\\b' src/Sylius/Behat/Resources/config/services || {
  echo "Missing service definition for sylius.behat.context.api.debug"; exit 1; }

echo -e "\n2) Ensure DebugContext exists and has After* hooks"
rg -n -C2 -g 'src/**' $'class\\s+DebugContext\\b' src/Sylius/Behat/Context/Api/DebugContext.php
rg -n -C2 -g 'src/**' '@After(Step|Scenario)' src/Sylius/Behat/Context/Api/DebugContext.php

echo -e "\n3) Ensure ResponseChecker supports error APIs"
rg -n -C2 -g 'src/**' $'interface\\s+ResponseCheckerInterface\\b' src/Sylius/Behat/Client
rg -n -C1 -g 'src/**' -e 'appendError' -e 'cleanErrors' -e 'getDebugErrors' src/Sylius/Behat/Client

echo -e "\n4) List API suites missing the debug context"
fd -t f -e yml src/Sylius/Behat/Resources/config/suites/api | while read -r f; do
  if ! rg -q $'sylius\\.behat\\.context\\.api\\.debug\\b' "$f"; then
    echo "MISSING: $f"
  fi
done

echo -e "\n5) Ensure no duplicate registrations in this file"
rg -n $'sylius\\.behat\\.context\\.api\\.debug\\b' src/Sylius/Behat/Resources/config/suites/api/currency/managing_exchange_rates.yml

Length of output: 4313


To complete verification, let’s correct the suite‐listing step and check for duplicates:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "4) List API suites missing the debug context (corrected)"
find src/Sylius/Behat/Resources/config/suites/api -type f -name '*.yml' | while read -r f; do
  if ! grep -q 'sylius\.behat\.context\.api\.debug' "$f"; then
    echo "MISSING: $f"
  fi
done

echo -e "\n5) Ensure no duplicate registrations in this file"
grep -n 'sylius\.behat\.context\.api\.debug\b' src/Sylius/Behat/Resources/config/suites/api/currency/managing_exchange_rates.yml

Length of output: 8370


API debug context wired correctly – one suite still missing

All checks pass for the new registration in managing_exchange_rates.yml:

  • Service sylius.behat.context.api.debug is defined in src/Sylius/Behat/Resources/config/services/contexts/api/common.xml (line 36).
  • DebugContext exists with both @AfterStep and @AfterScenario hooks (in src/Sylius/Behat/Context/Api/DebugContext.php).
  • ResponseCheckerInterface and its implementation support appendError(), cleanErrors(), and getDebugErrors(); errors are appended on non-2xx API responses (ApiPlatformClient, line 357).
  • No duplicate sylius.behat.context.api.debug entries in
    src/Sylius/Behat/Resources/config/suites/api/currency/managing_exchange_rates.yml.

However, one API suite is still missing the debug context:

  • MISSING: src/Sylius/Behat/Resources/config/suites/api/inventory/cart_inventory.yml

Please add the following to that suite (e.g. alongside the other contexts):

                - sylius.behat.context.api.debug

This will ensure consistent debugging coverage across all API suites.

🤖 Prompt for AI Agents
In src/Sylius/Behat/Resources/config/suites/api/inventory/cart_inventory.yml
around where other contexts are listed (add at the same indentation as the other
"- sylius.behat.context.*" entries), the API debug context
sylius.behat.context.api.debug is missing; add a line "-
sylius.behat.context.api.debug" alongside the other contexts in that suite to
enable the DebugContext hooks for this API suite so errors are collected and
cleared consistently.

- sylius.behat.context.setup.currency
- sylius.behat.context.setup.exchange_rate

- sylius.behat.context.api.debug
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Good addition: enable API error surfacing in this suite

Adding sylius.behat.context.api.debug will help correlate failing API calls with the exact Behat step. Placement before the first sylius.behat.context.api.shop.* context is fine as the debug context only provides hooks (no step definitions), so ordering has no functional side effects.

Run this script to ensure all API suites include the debug context exactly once and to spot any outliers:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

root='src/Sylius/Behat/Resources/config/suites/api'

# 1) List all suite files
fd -t f -e yml -e yaml "$root" | sort > /tmp/all_suites.txt
echo "Total suite files:" $(wc -l < /tmp/all_suites.txt)

# 2) Files that include the debug context
rg -l '^\s*-\s+sylius\.behat\.context\.api\.debug\s*$' $(cat /tmp/all_suites.txt) | sort > /tmp/with_debug.txt
echo "Suites with debug context:" $(wc -l < /tmp/with_debug.txt)

# 3) Files missing the debug context
echo "Suites missing debug context (if any):"
comm -23 /tmp/all_suites.txt /tmp/with_debug.txt || true

# 4) Detect duplicates (debug context added more than once per file)
echo "Suites with duplicate debug context lines (if any):"
rg -n '^\s*-\s+sylius\.behat\.context\.api\.debug\s*$' $(cat /tmp/all_suites.txt) \
  | cut -d: -f1 | sort | uniq -c | awk '$1 > 1 {print "duplicate count=" $1, "file=" $2}'

# 5) Show two surrounding lines for quick placement review
echo "Context placement preview (±2 lines around the debug context):"
rg -nC2 '^\s*-\s+sylius\.behat\.context\.api\.debug\s*$' $(cat /tmp/with_debug.txt)

Length of output: 630


This revised script uses find to correctly list all YAML suite files and then counts occurrences of the debug context line per file. It outputs suites missing the line, those with exactly one occurrence, and any with duplicates, followed by a context preview for manual placement verification.


🏁 Script executed:

#!/bin/bash
set -euo pipefail

root='src/Sylius/Behat/Resources/config/suites/api'
tmp_dir=$(mktemp -d)

# 1) List all suite files under the api directory
find "$root" -type f \( -iname '*.yml' -o -iname '*.yaml' \) | sort > "$tmp_dir/all_suites.txt"
echo "Total suite files: $(wc -l < "$tmp_dir/all_suites.txt")"

# 2) Identify files containing exactly one debug context line
grep -R -n '^\s*-\s\+sylius\.behat\.context\.api\.debug\s*$' -Hf "$tmp_dir/all_suites.txt" | \
  awk -F: '{ print $1 }' | sort | uniq -c | \
  tee "$tmp_dir/debug_counts.txt"

echo
echo "Suites with exactly one debug context (expected):"
awk '$1 == 1 { print $2 }' < <(awk '{print $1, $2}' "$tmp_dir/debug_counts.txt")

echo
echo "Suites missing debug context (count = 0):"
comm -23 "$tmp_dir/all_suites.txt" <(awk '$1 >= 1 { print $2 }' "$tmp_dir/debug_counts.txt")

echo
echo "Suites with duplicate debug context (count > 1):"
awk '$1 > 1 { print "count=" $1, "file=" $2 }' "$tmp_dir/debug_counts.txt" || true

# 3) Show placement preview around the debug context for review
echo
echo "Context placement preview (±2 lines around debug context) for files containing it:"
while read -r file count; do
  if [ "$count" -ge 1 ]; then
    echo
    echo "File: $file"
    grep -nC2 '^\s*-\s\+sylius\.behat\.context\.api\.debug\s*$' "$file"
  fi
done < <(awk '{print $2, $1}' "$tmp_dir/debug_counts.txt")

Length of output: 648


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

root='src/Sylius/Behat/Resources/config/suites/api'
tmp_dir=$(mktemp -d)

# 1) List all suite files
find "$root" -type f \( -iname '*.yml' -o -iname '*.yaml' \) | sort > "$tmp_dir/all_suites.txt"
echo "Total suite files: $(wc -l < "$tmp_dir/all_suites.txt")"

# 2) Count debug context occurrences per file
while IFS= read -r file; do
  count=$(grep -c -E '^\s*-\s+sylius\.behat\.context\.api\.debug\s*$' "$file" || true)
  printf "%d %s\n" "$count" "$file"
done < "$tmp_dir/all_suites.txt" > "$tmp_dir/debug_counts.txt"

# 3) Summarize
echo
echo "Suites missing debug context (count = 0):"
awk '$1 == 0 { print $2 }' "$tmp_dir/debug_counts.txt" || true

echo
echo "Suites with exactly one debug context (count = 1):"
awk '$1 == 1 { print $2 }' "$tmp_dir/debug_counts.txt" || true

echo
echo "Suites with duplicate debug context (count > 1):"
awk '$1 > 1 { print $1 " occurrences in " $2 }' "$tmp_dir/debug_counts.txt" || true

# 4) Show placement preview around debug context
echo
echo "Placement preview for suites containing the debug context:"
awk '$1 >= 1 { print $2 }' "$tmp_dir/debug_counts.txt" | while IFS= read -r file; do
  echo
  echo "File: $file"
  grep -nC2 -E '^\s*-\s+sylius\.behat\.context\.api\.debug\s*$' "$file"
done

Length of output: 62334


Add missing debug context to all API suites

It looks like every API suite file now includes exactly one sylius.behat.context.api.debug entry (no duplicates), except for two inventory suites where it’s missing. To ensure consistent API error surfacing across all suites, please add the debug context to these files—ideally immediately before the first sylius.behat.context.api.shop.* or sylius.behat.context.api.admin.* context hook.

Files missing the debug context:

  • src/Sylius/Behat/Resources/config/suites/api/inventory/cart_inventory.yml
  • src/Sylius/Behat/Resources/config/suites/api/inventory/checkout_inventory.yaml

Suggested insertion (around line 20 in each file):

                 - sylius.behat.context.setup.zone
-
+                - sylius.behat.context.api.debug
                 - sylius.behat.context.api.shop.cart  # or appropriate first shop/admin context
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- sylius.behat.context.api.debug
- sylius.behat.context.setup.zone
- sylius.behat.context.api.debug
- sylius.behat.context.api.shop.cart # (or the first shop/admin context)
🤖 Prompt for AI Agents
In src/Sylius/Behat/Resources/config/suites/api/inventory/cart_inventory.yml and
src/Sylius/Behat/Resources/config/suites/api/inventory/checkout_inventory.yaml
around line 20, the test suites are missing the sylius.behat.context.api.debug
context; insert a single line with sylius.behat.context.api.debug immediately
before the first occurrence of a sylius.behat.context.api.shop.* or
sylius.behat.context.api.admin.* context hook in each file so the debug context
is present and consistent with other API suites.

- sylius.behat.context.setup.taxonomy
- Sylius\Behat\Context\Setup\CatalogPromotionContext

- sylius.behat.context.api.debug
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

API Debug context added — looks good

Placement between setup contexts and api.shop contexts is sensible; DebugContext should only add hooks, so step resolution order remains unaffected.

To avoid suite load failures from a missing service or interface drift, please run:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Ensure the debug context service is defined and points to the expected class"
rg -nC2 -P 'id=["'\'']sylius\.behat\.context\.api\.debug["'\'']' -g 'src/**/services/**/*.xml'
rg -nC2 -P 'Sylius\\\\Behat\\\\Context\\\\Api\\\\DebugContext' src

echo "2) Ensure ResponseCheckerInterface exposes error-related methods"
rg -n -P '\binterface\s+ResponseCheckerInterface\b' -nC2 src
rg -n -P '\b(getDebugErrors|cleanErrors)\s*\(' src/Sylius/Behat/Client

echo "3) Ensure ApiPlatformClient appends errors on non-2xx"
rg -n -P 'class\s+ApiPlatformClient\b' -nC3 src
rg -n -P 'appendError\s*\(' src/Sylius/Behat/Client

echo "4) Spot-check that multiple API suites include the debug context (consistency)"
rg -n -P 'sylius\.behat\.context\.api\.debug' src/Sylius/Behat/Resources/config/suites/api -g '!**/vendor/**'

Length of output: 933


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) DebugContext file presence"
ls src/Sylius/Behat/Context/Api/DebugContext.php && echo "Found DebugContext.php" || echo "DebugContext.php NOT found"

echo ""
echo "2) DebugContext class definition"
rg -nP 'class\s+DebugContext\b' src/Sylius/Behat/Context/Api/DebugContext.php || echo "No DebugContext class definition found"

echo ""
echo "3) ResponseCheckerInterface file presence"
ls src/Sylius/Behat/Client/ResponseCheckerInterface.php && echo "Found ResponseCheckerInterface.php" || echo "ResponseCheckerInterface.php NOT found"

echo ""
echo "4) ResponseCheckerInterface definition"
rg -nC2 -nP '\binterface\s+ResponseCheckerInterface\b' src/Sylius/Behat/Client/ResponseCheckerInterface.php || echo "ResponseCheckerInterface interface not found"

echo ""
echo "5) Methods getDebugErrors and cleanErrors in ResponseCheckerInterface"
rg -nP '\b(getDebugErrors|cleanErrors)\s*\(' src/Sylius/Behat/Client/ResponseCheckerInterface.php || echo "getDebugErrors/cleanErrors methods not found"

echo ""
echo "6) ApiPlatformClient class definition"
rg -nC3 -nP 'class\s+ApiPlatformClient\b' src/Sylius/Behat/Client || echo "ApiPlatformClient class not found"

echo ""
echo "7) appendError usage in client"
rg -nP 'appendError\s*\(' src/Sylius/Behat/Client || echo "appendError calls not found"

echo ""
echo "8) Debug context usage in all API suites"
rg -nC2 -nP 'sylius\.behat\.context\.api\.debug' src/Sylius/Behat/Resources/config/suites/api || echo "Debug context missing in one or more suites"

Length of output: 3582


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "3a) Confirm class declaration for ApiPlatformClient"
rg -nP 'class\s+ApiPlatformClient\b' src/Sylius/Behat/Client/ApiPlatformClient.php || echo "Class ApiPlatformClient not declared"

echo ""
echo "3b) Show context around appendError call in ApiPlatformClient"
rg -nC3 -nP 'appendError' src/Sylius/Behat/Client/ApiPlatformClient.php

echo ""
echo "4) Verify debug context in all API suite definitions"
find src/Sylius/Behat/Resources/config/suites/api -type f -name '*.yml' | sort | while read file; do
  echo "$file"
  grep -P -n 'sylius\.behat\.context\.api\.debug' "$file" || echo "  -> Missing debug context"
done

Length of output: 919


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) ResponseCheckerInterface definition"
grep -nP 'interface\s+ResponseCheckerInterface' src/Sylius/Behat/Client/ResponseCheckerInterface.php || echo "Interface not found"

echo ""
echo "2) Debug context presence in each API suite definition"
find src/Sylius/Behat/Resources/config/suites/api -type f -name '*.yml' | sort | while read file; do
  printf "%-80s" "$file"
  if grep -q 'sylius\.behat\.context\.api\.debug' "$file"; then
    echo ""
  else
    echo " MISSING"
  fi
done

Length of output: 18770


Add missing DebugContext to the inventory/cart_inventory suite

Verification confirms:

  • The sylius.behat.context.api.debug service is defined in
    src/Sylius/Behat/Resources/config/services/contexts/api/common.xml
    and the DebugContext class exists and implements Context.
  • ResponseCheckerInterface (in src/Sylius/Behat/Client/ResponseCheckerInterface.php) declares both
    cleanErrors(): void and getDebugErrors(): array as expected.
  • ApiPlatformClient (in src/Sylius/Behat/Client/ApiPlatformClient.php) is declared and invokes
    $this->responseChecker->appendError($response) on each non-2xx response.

However, one API suite is missing the debug context:

  • File:
    src/Sylius/Behat/Resources/config/suites/api/inventory/cart_inventory.yml
    Status: MISSING - sylius.behat.context.api.debug

Please add the debug context entry in the contexts: section—ideally between your setup contexts and the api.shop context—to ensure consistent error reporting and avoid suite load failures.

🤖 Prompt for AI Agents
In src/Sylius/Behat/Resources/config/suites/api/inventory/cart_inventory.yml
around line 39, the suite is missing the DebugContext entry; open the file and
add the line "- sylius.behat.context.api.debug" to the contexts: list (place it
between your setup contexts and the existing "api.shop" context) so the
DebugContext is registered for this API suite.

- sylius.behat.context.api.admin.managing_customers
- sylius.behat.context.api.admin.response
- sylius.behat.context.api.admin.save
- sylius.behat.context.api.debug
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Repository-wide coverage check (optional)

Given the widespread addition, double-check that all API suites gained the debug context (and non-API suites did not).


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# All API suites that should include the debug context
api_suite_dir='src/Sylius/Behat/Resources/config/suites/api'

# List suites missing the debug context
missing=$(rg -lZP '^default:\s*\n\s*suites:' "$api_suite_dir" | xargs -0 -I{} bash -c '
  file="{}"; rg -q "sylius\.behat\.context\.api\.debug" "$file" || echo "$file"
')
if [ -n "$missing" ]; then
  echo "Suites missing sylius.behat.context.api.debug:"
  echo "$missing"
else
  echo "All API suites contain sylius.behat.context.api.debug"
fi

Length of output: 690


I’ve updated the verification script to avoid the unsupported -Z flag and reliably check every .yml in the API suites directory:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

api_suite_dir='src/Sylius/Behat/Resources/config/suites/api'
missing=()

# Iterate all YAML suite files and check for the debug context
while IFS= read -r file; do
  if ! grep -q "sylius\.behat\.context\.api\.debug" "$file"; then
    missing+=("$file")
  fi
done < <(find "$api_suite_dir" -type f -name '*.yml')

# Report results
if [ ${#missing[@]} -gt 0 ]; then
  echo "Suites missing sylius.behat.context.api.debug:"
  printf "  %s\n" "${missing[@]}"
else
  echo "All API suites contain sylius.behat.context.api.debug"
fi

Length of output: 278


I’ve replaced the process substitution with a simple find … -exec grep -F -L approach:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

api_suite_dir='src/Sylius/Behat/Resources/config/suites/api'

# Find all .yml files that do NOT contain the debug context
missing=$(find "$api_suite_dir" -type f -name '*.yml' -exec grep -F -L "sylius.behat.context.api.debug" {} +)

if [ -z "$missing" ]; then
  echo "All API suites contain sylius.behat.context.api.debug"
else
  echo "Suites missing sylius.behat.context.api.debug:"
  echo "$missing"
fi

Length of output: 639


Missing debug context in one API suite

The script identified that cart_inventory.yml lacks the required debug context. Please add sylius.behat.context.api.debug to its contexts list under the default suite so that API debugging is enabled consistently.

• File needing update:

  • src/Sylius/Behat/Resources/config/suites/api/inventory/cart_inventory.yml

Suggested diff (insert as the first item under contexts):

 suites:
     default:
         contexts:
+            - sylius.behat.context.api.debug
             - sylius.behat.context.api.authentication
             - sylius.behat.context.api.inventory
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- sylius.behat.context.api.debug
suites:
default:
contexts:
- sylius.behat.context.api.debug
- sylius.behat.context.api.authentication
- sylius.behat.context.api.inventory
🤖 Prompt for AI Agents
In src/Sylius/Behat/Resources/config/suites/api/inventory/cart_inventory.yml
around line 33, the default suite's contexts list is missing the required debug
context; add sylius.behat.context.api.debug as the first entry under the
contexts key (preserving YAML indentation) so the contexts list begins with that
item before the existing contexts.

@TheMilek TheMilek merged commit 5b55172 into Sylius:2.1 Aug 25, 2025
55 of 57 checks passed
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.

3 participants