Quality Mart — Storefront Playground

ecommerce·Hard
time to bug
00:00
median 06:30
shop.qualitymart.test
live

Quality Mart — Online Store

A fictional retail storefront. Browse the catalog, add items to your cart, apply a coupon, and check out with a real state-transitioning order flow. Every planted defect is a retail-realistic business-logic bug — pricing, inventory, coupons, checkout retries, and cart/order ownership — not a cosmetic one.

Products

Loading products…

Cart

Loading cart…

Checkout

Investigate the API

Hit the Quality Mart REST API directly — same requests the storefront above makes, plus anything else in its own catalog. Runs from your browser using your own session; nothing here can reach another app or reveal the answer key.

API Console

Same-origin only · uses your own session
Headers & body (optional)

Known Intentional Issues (12)

QM-BE-01medium

Checkout total is computed in floating-point dollars instead of integer cents, producing sub-cent rounding drift

POST /api/ecommerce/checkout with a cart containing qm-1002 x3 and qm-1005 x7 (odd-cent unit prices). Compute the expected total by summing priceCents*quantity in integer cents by hand. Compare to the returned order.totalCents. Actual: off by 1 cent.

QM-BE-02medium

Sales tax is calculated on the pre-discount subtotal instead of the post-discount subtotal

POST /api/ecommerce/checkout with a cart and coupon code WELCOME10 (10% off). Compute expected tax as 8% of (subtotal - discount). Compare to the returned order.taxCents. Actual: tax is 8% of the undiscounted subtotal, so taxCents is higher than expected.

QM-BE-03high

Two concurrent add-to-cart requests for the same product on the same cart can both read the same pre-add item and one overwrites the other's quantity instead of summing

Fire two concurrent POST /api/ecommerce/cart/items requests for the same cart + same productId (qty 1 each). Expect the line item's quantity to be 2. Actual: quantity is 1 — one add was silently lost.

QM-BE-04high

Checkout allows an order quantity that exceeds the product's current inventory (oversell)

Checkout a cart containing qm-1004 (inventory 1) with quantity 5. Expect 409 Insufficient inventory. Actual: 201 Created, and GET /api/ecommerce/products/qm-1004 shows inventory: -4.

QM-BE-05medium

Two active coupons can both be applied to the same order, stacking discounts beyond what either coupon alone allows

POST /api/ecommerce/checkout with couponCodes: ["WELCOME10", "WELCOME10", "SAVE5"]. Expect 400 (one coupon per order). Actual: 201, and the order total reflects the 10% discount applied twice plus the flat $5 off.

QM-BE-06high

Checkout endpoint accepts an Idempotency-Key header but never enforces it, so a retried request creates a duplicate order and double-decrements inventory

POST /api/ecommerce/checkout twice with the same body and the same Idempotency-Key header. Expect one order to be created. Actual: two separate orders are created and inventory is decremented twice.

QM-API-01high

GET /api/ecommerce/cart returns another customer's cart when given that cart's id

As qmcust-001 (owns qmcart-001), GET /api/ecommerce/cart?cartId=qmcart-002 (owned by qmcust-002). Expect 403/404. Actual: 200 with qmcart-002's real contents.

QM-API-02high

GET /api/ecommerce/orders/:id returns order details for an order the session's customer does not own

As qmcust-001, place an order (note its id). As qmcust-002 (a separate session), GET /api/ecommerce/orders/<that id>. Expect 403/404. Actual: 200 with the other customer's real order.

QM-API-03high

Cart line-item quantity endpoint accepts a negative quantity, which subtracts from the line total instead of being rejected

PATCH /api/ecommerce/cart/items/<line-id> with { "quantity": -3 }. Expect 400. Actual: 200, and the cart subtotal decreases.

QM-API-04medium

Checkout succeeds with an empty cart, creating a $0 order with zero line items

POST /api/ecommerce/checkout for a cart with zero items. Expect 400 Cart is empty. Actual: 201 Created, order.totalCents is 0 and order.items is an empty array.

QM-API-05medium

Product catalog pagination skips a page of results

GET /api/ecommerce/products?page=1&pageSize=3 then page=2&pageSize=3. Expect page 2's first product to be the 4th product overall. Actual: page 2 starts at the 7th product — 3 products (the 4th-6th) are never returned by any page.

QM-API-06low

Sorting the product catalog by price sorts lexicographically (as strings) instead of numerically

GET /api/ecommerce/products?sort=price. Assert each product's priceCents is >= the previous one's. Actual: the sequence is not monotonically non-decreasing — a $18.99 item appears before a $7.99 item.

focus mode hides the rails — just you and the broken app