Skip to content

Test against MaxoMart (demo shop)

MaxoMart (demo.maxoperf.com) is a synthetic e-commerce application maintained by Maxoperf specifically for load and browser testing. It behaves like a real store — product catalog, shopping cart, multi-step checkout, JWT authentication, session cookies — without involving real payments or inventory.

Use it to:

  • Practise browser automation against a realistic multi-page flow.
  • Run load tests against a publicly reachable REST API.
  • Try Maxoperf features (test recording, HAR inspection, run results) without needing your own staging environment.

MaxoMart homepage showing the hero banner and featured products

MaxoMart has eight pages that cover the classic e-commerce user journey:

PageURLWhat to test
Home/Hero rendering, category nav, featured products
Catalog/catalogFiltering, pagination, product cards
Product detail/product/:slugImage, price, stock badge, Add to cart
Cart/cartQuantity changes, remove, subtotal, Proceed to Checkout
Checkout/checkoutAddress → Payment → Review multi-step form
Order confirmation/order/:idSuccess state with order ID
Login/loginJWT auth, redirect after sign-in
Register/registerNew account creation

Product catalog showing the grid of items with Add to cart buttons

Product detail page for Advanced Drone with Add to cart button


MaxoMart exposes a fully documented REST API at https://demo.maxoperf.com/api. The interactive Swagger UI is at https://demo.maxoperf.com/api/docs — try any endpoint directly in the browser without writing a line of code.

MaxoMart Swagger UI listing Auth, Products, Cart, Checkout, and Orders endpoints

AuthPOST /api/auth/register, POST /api/auth/login, GET /api/auth/me

ProductsGET /api/products, GET /api/products/:slug, GET /api/categories

CartGET /api/cart, POST /api/cart/items, PATCH /api/cart/items/:id, DELETE /api/cart/items/:id

Checkout / OrdersPOST /api/checkout, GET /api/orders/:id

Demo credentialsdemo@maxomart.test / demo1234 (pre-seeded, always available)

Two auth schemes are supported:

  • JWT bearer token — obtained from POST /api/auth/login, sent as Authorization: Bearer <token>
  • Session cookiemm_sid set automatically on first request; no login required for guest checkout

MaxoMart is ideal for practising browser automation because every interactive element carries a data-testid attribute. The purchase funnel (catalog → product → cart → checkout) gives you a realistic multi-step workflow to automate.

Cart page with the Advanced Drone item, quantity stepper, and Proceed to Checkout button

Multi-step checkout form showing the Address step

import { test, expect } from '@playwright/test';
const BASE = 'https://demo.maxoperf.com';
test('add to cart and reach checkout', async ({ page }) => {
// Browse catalog
await page.goto(`${BASE}/catalog`);
await expect(page.locator('[data-testid^="product-card-"]').first()).toBeVisible();
// Open first product
await page.locator('[data-testid^="product-card-"]').first().click();
await expect(page.locator('button:has-text("Add to cart")')).toBeVisible();
// Add to cart
await page.locator('button:has-text("Add to cart")').click();
// Go to cart
await page.goto(`${BASE}/cart`);
await expect(page.locator('text=Your Cart')).toBeVisible();
await expect(page.locator('[data-testid^="cart-item-"]')).toHaveCount(1);
// Proceed to checkout
await page.locator('text=Proceed to Checkout').click();
await expect(page.locator('text=Shipping Address')).toBeVisible();
// Fill address form
await page.fill('input[name="fullName"]', 'Jane Tester');
await page.fill('input[name="address"]', '123 Load Ave');
await page.fill('input[name="city"]', 'San Francisco');
await page.fill('input[name="postalCode"]', '94105');
await page.locator('text=Continue to Payment').click();
await expect(page.locator('text=Payment')).toBeVisible();
});

Run the test with:

Terminal window
npx playwright test --project=chromium

Record your own test script with the Maxoperf browser recorder — see Record browser tests.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
BASE = "https://demo.maxoperf.com"
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)
try:
# Open catalog
driver.get(f"{BASE}/catalog")
wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, "[data-testid^='product-card-']")
))
# Click first product card
driver.find_element(By.CSS_SELECTOR, "[data-testid^='product-card-'] a").click()
# Add to cart
add_btn = wait.until(EC.element_to_be_clickable(
(By.XPATH, "//button[contains(text(), 'Add to cart')]")
))
add_btn.click()
# Navigate to cart
driver.get(f"{BASE}/cart")
wait.until(EC.presence_of_element_located(
(By.XPATH, "//h1[contains(text(), 'Your Cart')]")
))
items = driver.find_elements(By.CSS_SELECTOR, "[data-testid^='cart-item-']")
assert len(items) == 1, f"Expected 1 cart item, got {len(items)}"
# Proceed to checkout
driver.find_element(
By.XPATH, "//button[contains(text(), 'Proceed to Checkout')]"
).click()
wait.until(EC.presence_of_element_located(
(By.XPATH, "//h2[contains(text(), 'Shipping Address')]")
))
print("Reached checkout — test passed")
finally:
driver.quit()

The MaxoMart REST API is the right target when you want to isolate backend performance from browser rendering overhead. All endpoints return JSON and accept standard HTTP headers.

Terminal window
# List products (first page, 12 per page)
curl https://demo.maxoperf.com/api/products
# Filter by category
curl "https://demo.maxoperf.com/api/products?category=electronics&limit=20"
# Get a single product
curl https://demo.maxoperf.com/api/products/advanced-drone
# Login and capture the JWT token
TOKEN=$(curl -s -X POST https://demo.maxoperf.com/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"demo@maxomart.test","password":"demo1234"}' \
| jq -r '.token')
# Get authenticated user profile
curl -H "Authorization: Bearer $TOKEN" \
https://demo.maxoperf.com/api/auth/me
# Add item to cart (session-based, no login needed)
curl -c cookies.txt -b cookies.txt \
-X POST https://demo.maxoperf.com/api/cart/items \
-H "Content-Type: application/json" \
-d '{"slug":"advanced-drone","quantity":1}'
# Place an order
curl -c cookies.txt -b cookies.txt \
-X POST https://demo.maxoperf.com/api/checkout \
-H "Content-Type: application/json" \
-d '{
"fullName": "Jane Tester",
"address": "123 Load Ave",
"city": "San Francisco",
"postalCode": "94105",
"country": "US",
"cardLast4": "4242"
}'

The script below models a realistic purchase funnel: browse products, view a detail page, add to cart, and complete checkout.

import http from 'k6/http';
import { check, sleep } from 'k6';
import { SharedArray } from 'k6/data';
const BASE = 'https://demo.maxoperf.com';
// Load product slugs once, shared across VUs
const products = new SharedArray('products', () => [
'advanced-drone',
'advanced-tablet',
'advanced-cap',
'solar-headphones',
'advanced-perfume',
]);
export const options = {
stages: [
{ duration: '30s', target: 20 },
{ duration: '1m', target: 20 },
{ duration: '15s', target: 0 },
],
thresholds: {
http_req_duration: ['p(95)<500'],
http_req_failed: ['rate<0.01'],
},
};
export default function () {
const jar = http.cookieJar();
const slug = products[Math.floor(Math.random() * products.length)];
// 1. Browse catalog
let res = http.get(`${BASE}/api/products?limit=12`, { jar });
check(res, { 'catalog 200': r => r.status === 200 });
sleep(1);
// 2. View product detail
res = http.get(`${BASE}/api/products/${slug}`, { jar });
check(res, { 'product 200': r => r.status === 200 });
sleep(0.5);
// 3. Add to cart
res = http.post(
`${BASE}/api/cart/items`,
JSON.stringify({ slug, quantity: 1 }),
{ headers: { 'Content-Type': 'application/json' }, jar },
);
check(res, { 'add-to-cart 201': r => r.status === 201 });
sleep(0.5);
// 4. Checkout
res = http.post(
`${BASE}/api/checkout`,
JSON.stringify({
fullName: 'Load Tester',
address: '1 Perf Street',
city: 'Austin',
postalCode: '78701',
country: 'US',
cardLast4: '4242',
}),
{ headers: { 'Content-Type': 'application/json' }, jar },
);
check(res, { 'checkout 201': r => r.status === 201 });
sleep(1);
}

Run it with:

Terminal window
k6 run maxomart-load.js

Or upload this script to Maxoperf and run it from cloud locations — see Run your first test.

Paste the MaxoMart k6 script into a new test's Scenario and files section, then pick a load profile and locations.

  • Record browser tests — use the Maxoperf browser recorder with demo.maxoperf.com to generate a test script automatically.
  • Upload test files — bring your k6 or JMeter script into Maxoperf.
  • Run tests from CI — trigger a Maxoperf run against MaxoMart on every pull request.
  • Read run results — interpret latency percentiles and error rates from your runs.