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_foundrejection, 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:
pendingon create,processingon 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/generalreturn what the connector reads. Check the store address maps correctly (woocommerce_default_countryasCC: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 emptycodeslist clears. - Multiple coupons on one order.
2.5 Buyer and consent
- Buyer maps to billing (name, email, phone). Consent is stored in order
meta_dataunder_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_failedrejection 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}/V1path 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 viaDELETE. Confirm quantity replacement and removal semantics, configurable/bundle products, and out-of-stock messages (The requested qty is not availableetc. →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-methodswith an address returns the rates offered; confirm carrier/method codes join ascarrier_methodand that carriers with underscores in their code parse correctly (the id is split at the first_).POST .../shipping-informationwithaddressInformation: confirm required address fields for your country (region, postcode, telephone) and the resulting quoteshipping_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}andDELETE .../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-informationfor a guest needsemailandbillingAddress. 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 topayment_failed. - Offline methods leave the order
pending; the connector still reports the checkoutcompleted. Confirm this is the desired semantics, and that the response’s order id is the entity id (used for/orders/{id}lookups) withincrement_idas 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).
3.6 Consent and buyer
- 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 spellingcanceled,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.consentas a map keyed by reverse-DNS purpose withsourceanddescription; 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 haveid,name,address(spec-required:id,name,type). - Fulfillment option
descriptionis 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 onlyhandler_idand 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/ucpadvertises 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
TestCapabilityMatrixstill passes. - The WooCommerce rate-option source (1.1) and payment approach (1.2) are decided before the WooCommerce fulfillment/payment sections are considered testable.