Skip to content
SarvexDocs
Esc
↑↓navigate↵open⌘Jpreview
On this page

Real-store test plan

Scope: the two supported platforms (WooCommerce, Magento) × the two active spec generations (2026-04-08, 2026-08-25). The frozen connectors are out of scope.

Generated from docs/REAL-STORE-TEST-PLAN.md in the Sarvex repository — edit the source there, not this page.

Status: not yet executed. Everything below was built and tested against the simulator (internal/planes/sync/sim) and connector fakes, which mirror the platforms’ documented REST shapes. They are not real stores. This document lists what a real-store run must confirm, ordered by how likely the simulator is to be hiding a difference.

Scope: the two supported platforms (WooCommerce, Magento) × the two active spec generations (2026-04-08, 2026-08-25). The frozen connectors are out of scope.

0. How to run and record

  • Use a staging store per platform, never production. Use a throwaway payment method (offline / test gateway) and disposable buyer data.
  • Drive the flows through Sarvex’s serving endpoints (a UCP agent or the conformance client), not the connector directly, so profile, negotiation, session store, idempotency and the order handoff are exercised too.
  • Repeat each flow at both spec versions (negotiate via UCP-Agent).
  • Record for each item: platform, version, store/plugin versions, PASS/FAIL, request/response excerpts, and any store-side state (order, meta, comment).
  • A failure that comes from the simulator being wrong is fixed in the simulator and the connector together (CLAUDE.md §8), with a regression test.

1. Highest-risk gaps (simulator ≠ real store)

# Area Why the simulator may be hiding a difference
1 WooCommerce shipping rate options The connector builds a checkout’s rate options from available_shipping_rates on the order. That is a simulator-only field; stock WooCommerce orders do not have it. On a real store the shipping method will be offered with no rate options until rates are sourced from the store’s shipping zones/methods (or a rate-quote endpoint). Expect this to fail.
2 WooCommerce charging The connector sets the order to processing and forwards payment_token. Stock WooCommerce ignores the token, so nothing is charged. Needs a gateway integration, which conflicts with CLAUDE.md §4 (thin plugin). Decide the approach before testing payment.
3 WooCommerce order totals REST-created orders do not necessarily compute shipping/tax/coupon totals the way the simulator does. Verify shipping_total, total_tax, discount_total, total after each write.
4 Magento guest checkout The connector uses the real Magento request shapes (addressInformation, cartItem, payment-information with email + billing address), written from the documentation. Never run against a real Magento.
5 Magento in-store pickup Detection reads MSI GET /inventory/sources for is_pickup_location_active; selection posts the instore / pickup carrier with extension_attributes.pickup_location_code. Both are from memory of the MSI module.
6 Magento consent storage Consent is written as an internal order comment (POST /orders/{id}/comments). Confirm the endpoint, payload and admin visibility.
7 Sim-only behaviours The sim accepts the fail_token payment token as a decline, uses a single flat rate, one coupon code (SPRING20), item ids equal to product ids, and a one-source store. None of these are real.

2. WooCommerce

Environment: WooCommerce with the REST API enabled, consumer key/secret with read/write, a shipping zone with a flat rate, at least one product with stock, the Sarvex plugin installed. Note WooCommerce and plugin versions.

2.1 Catalog and identifiers

  • Catalog lookup returns numeric product ids; checkout accepts SKUs (the connector resolves them) and numeric ids. Confirm both, and that an unknown SKU is a not_found rejection, not a 5xx.
  • Variable products: variant ids resolve; out-of-stock variants reject with out_of_stock.

2.2 Checkout

  • Create → update → complete creates exactly one WooCommerce order. Confirm no duplicate pending orders after retries or lost responses (create/complete use no-retry writes).
  • Line-item replacement (PUT): quantity change, removal, addition.
  • Currency, taxes and totals match what the WooCommerce admin shows (see 1.3).
  • Order status transitions: pending on create, processing on complete; the completed response carries the order id, number and a working permalink.

2.3 Fulfillment

  • Rate options (1.1): confirm what a real order returns and decide how rates are sourced. Check destination handling, chosen rate recorded as a shipping line with the right method_id / instance_id / total.
  • Pickup detection: enable Local Pickup (classic and block “Pickup Location”) in a zone; confirm /shipping/zones, /shipping/zones/{id}/methods (including zone 0) and /settings/general return what the connector reads. Check the store address maps correctly (woocommerce_default_country as CC:REGION), and that disabling pickup removes it within the 5-minute cache.
  • Pickup selection: a pickup order has a local-pickup shipping line and the store address; no shipping charge; the response does not also show it as a shipping destination/rate.
  • The pickup location is named generically (“Local pickup”) because the store name is not in the general settings. Confirm this is acceptable.

2.4 Discounts

  • Real coupons: percentage, fixed, expired, usage-limited, minimum-spend, free-shipping. Confirm applied amounts, the canonical code in applied, and that an invalid code is simply absent. Confirm an empty codes list clears.
  • Multiple coupons on one order.
  • Buyer maps to billing (name, email, phone). Consent is stored in order meta_data under _ucp_buyer_consent; an update without consent clears it.
  • Confirm the meta is not exposed to the customer (underscore-prefixed keys are hidden in the admin UI and emails by default).

2.6 Cart

  • A cart is a pending order. Confirm carts do not trigger emails, stock reservation surprises, or appear as real orders in reports; confirm abandoned carts are cleaned up (or decide a retention policy).
  • Agents only ever see Sarvex cart ids, never the order id.

2.7 Payment

  • See 1.2. Also confirm a rejected payment yields a payment_failed rejection and leaves the order recoverable, and that no token or card data appears in Sarvex logs, session store, events or responses.

3. Magento

Environment: Magento 2.4.x Open Source with REST enabled, an integration/admin account, a shipping method (flat rate), an offline payment method (e.g. checkmo), products with stock. For pickup: MSI enabled with at least one source marked as a pickup location. Note Magento version and enabled modules.

3.1 Auth and store scope

  • Admin token issuance and refresh; the rest/{store_code}/V1 path with the configured store code; multi-store-view stores.

3.2 Cart and checkout

  • Guest cart create returns a masked id; every response uses the masked id the agent addressed the cart by, never the numeric quote id.
  • Add item is by SKU and adds to an existing line; the connector changes an existing line via PUT .../items/{item_id} and removes via DELETE. Confirm quantity replacement and removal semantics, configurable/bundle products, and out-of-stock messages (The requested qty is not available etc. → out_of_stock).
  • Totals come from GET .../totals; the quote itself carries none. Confirm subtotal, tax, shipping, grand total, and that discount is negative and reported once.
  • Quote currency vs the configured store currency (multi-currency stores).

3.3 Fulfillment

  • POST .../estimate-shipping-methods with an address returns the rates offered; confirm carrier/method codes join as carrier_method and that carriers with underscores in their code parse correctly (the id is split at the first _).
  • POST .../shipping-information with addressInformation: confirm required address fields for your country (region, postcode, telephone) and the resulting quote shipping_assignments.
  • Pickup (1.5): confirm source fields (is_pickup_location_active, name, address, frontend_name), the carrier/method for in-store pickup, and the address extension attribute. Only the first active source (by code) is offered; decide whether multiple locations are needed. Stores without MSI must read as “no pickup” (404/403 from /inventory/sources).

3.4 Discounts

  • PUT .../coupons/{code} and DELETE .../coupons. Magento allows one coupon per cart: the connector applies the first code the store accepts. Confirm cart-price-rule coupons (percentage, fixed, free shipping), refused codes, and auto-applied rules without a coupon (reported as a discount with no code).

3.5 Placing the order

  • payment-information for a guest needs email and billingAddress. The connector derives the billing address from the quote’s shipping destination (a UCP buyer has no postal address). Confirm this is accepted, including for pickup orders, and that virtual/no-shipping carts behave.
  • Payment: the opaque token is sent as paymentMethod.additional_data. payment_token. Confirm the chosen payment method module accepts/ignores it and that a decline returns a client error mapped to payment_failed.
  • Offline methods leave the order pending; the connector still reports the checkout completed. Confirm this is the desired semantics, and that the response’s order id is the entity id (used for /orders/{id} lookups) with increment_id as the label.
  • Placement is not retried. Confirm a timeout after the order was placed does not produce a second order on client retry (Sarvex idempotency key path).
  • Consent flags recorded as an internal order comment (not customer-visible, no customer notification) — see 1.6. Buyer contact appears on the order.

3.7 Orders

  • GET /orders/{entity_id} status mapping, including Magento’s spelling canceled, closed, holded, payment_review.

4. Spec versions (both platforms)

  • Negotiate 2026-08-25 and repeat 2.x / 3.x. Encoded responses are checked against the generation’s typed schema, but only with simulator data — confirm against a real UCP client/validator:
    • buyer.consent as a map keyed by reverse-DNS purpose with source and description; a platform’s own detail is echoed only when it agrees with the merchant’s answer.
    • Fulfillment destinations carry type (shipping_address / business_location); pickup destinations have id, name, address (spec-required: id, name, type).
    • Fulfillment option description is a Description object.
    • Pickup: the platform selects with selected_destination_id; an unknown location is rejected (invalid_destination). The spec also lets a business accept a valid location id it did not list; we do not.
  • A request with no UCP-Agent (not negotiated) is served as 2026-04-08.
  • Payment credentials: 2026-08-25 adds raw-PAN-shaped fields (pan, network_token). Confirm none is stored, logged or echoed, and that only handler_id and the opaque token are used.
  • Order webhooks are rendered in the version the session negotiated; confirm the platform’s webhook endpoint accepts them.

5. Sarvex-side flows to cover with a real store

  • Order handoff: completion emits the order intent with the order id; the sync plane records the sale and can re-fetch the order by that id (WooCommerce: post id; Magento: entity id). Check console order counts.
  • Idempotency: replay create/update/complete with the same Idempotency-Key (identical response) and a different body (409).
  • Tenancy: two stores with the same idempotency key and the same cart/order ids never see each other’s sessions or carts.
  • Freshness/stock: price or stock changed between create and complete.
  • Profile: the served /.well-known/ucp advertises only functional capabilities/extensions (catalog, checkout, order, cart; fulfillment, discount, buyer_consent) at both versions, with pickup absent from the profile.
  • Resilience: store 5xx/timeouts during create, update and complete surface as connector-unavailable, not as business rejections; no partial state is reported as success.
  • Logging/secrets: no credentials, tokens, emails or addresses in logs beyond what policy allows.

6. Exit criteria

  • Every item above PASS on both platforms at both versions, or has a filed defect and a decision recorded here.
  • Any simulator difference found is fixed in the simulator + connector with a test, and TestCapabilityMatrix still passes.
  • The WooCommerce rate-option source (1.1) and payment approach (1.2) are decided before the WooCommerce fulfillment/payment sections are considered testable.

Was this page helpful?