OmniPizza is a multi-platform, test-friendly food ordering sandbox designed for practicing UI + API automation (web + mobile) with deterministic chaos users and multi-market pricing.
Users now select market directly on the login screen (web + mobile) before entering the app.
| Login | Catalog | Pizza Customizer |
![]() |
![]() |
![]() |
| Checkout | Order Success | |
![]() |
![]() |
| Login | Catalog | Pizza Customizer | Checkout | Order Success |
![]() |
![]() |
![]() |
![]() |
![]() |
| Login | Catalog | Pizza Builder | Checkout | Order Success |
![]() |
![]() |
![]() |
![]() |
![]() |
The backend exposes full OpenAPI documentation using Swagger UI and ReDoc.
Interactive documentation to explore and test endpoints.
Clean, readable API reference.
Raw OpenAPI specification (useful for contract testing tools).
- Render: https://omnipizza-backend.onrender.com/api/openapi.json
- Local: http://localhost:8000/api/openapi.json
Most endpoints rely on request headers to simulate multi-market behavior:
X-Country-Code: MX | US | CH | JPX-Language: en | es | de | fr | jaAuthorization: Bearer <token>(after login)
These headers are automatically sent by the Web and Mobile clients.
Atomic state setup endpoints exist for external automation runners (Playwright/Appium/Gatling).
POST /api/store/marketPOST /api/cart— seed cart items (pizza_id, quantity, size)GET /api/cart— retrieve enriched cart (joined with pizza catalog: name, price, image, currency)POST /api/session/resetGET /api/session
Access rules:
- Require:
Authorization: Bearer <token>X-Country-Codeheader (forGET /api/cartto resolve pricing/currency)
These endpoints reuse the same JWT generated by /api/auth/login.
Both web and mobile checkout screens automatically fetch GET /api/cart on load. This enables E2E test frameworks to inject cart state via the API:
- Login via
POST /api/auth/loginto get a token - Seed cart via
POST /api/cartwith items (pizza_id, quantity, size) - Navigate the browser/app to the checkout screen
- The frontend fetches
GET /api/cartand hydrates the cart from backend state
If the backend cart is empty or the request fails, the frontend falls back to the existing client-side cart.
| Username | Password | Behavior |
|---|---|---|
| standard_user | pizza123 | Normal flow |
| locked_out_user | pizza123 | Login fails (deterministic) |
| problem_user | pizza123 | $0 prices + broken images |
| performance_glitch_user | pizza123 | API delay (~3s) |
| error_user | pizza123 | Random checkout error (~50%) |
| Market | Currency | Required fields | Notes |
|---|---|---|---|
| MX | MXN | colonia |
Tip optional (propina) |
| US | USD | zip_code |
Tax applied |
| CH | CHF | plz |
Language toggle DE/FR |
| JP | JPY | prefectura |
No decimals |
- The app starts in English (web + mobile).
- The selected market at login sets the default UI language:
- MX → Spanish (es)
- US → English (en)
- CH → German (de) (with toggle to French (fr))
- JP → Japanese (ja)
- After login, market is no longer changeable from app navigation.
Checkout supports two selectable payment methods:
- Credit Card — Displays a full card form (Cardholder Name, Card Number, Expiry, CVV). Card details are UI-only and are not sent to the backend.
- Cash on Delivery — Hides the card form; order is placed without card details.
The payment method toggle uses data-testid="payment-card" and data-testid="payment-cash" for automation.
The Profile page stores delivery details (name/address/phone) and auto-fills Checkout.
After checkout, the Order Success screen is shown and the last order remains accessible (web persists it via local storage).
- Navbar includes a logout button.
- Checkout validates required fields before submit (country-specific + inline errors).
- Layouts are rotation-ready (portrait/landscape) for iOS and Android.
- Public icons/logos were standardized from
frontend-mobile/assets/icon.png. - Login page uses
frontend/public/login-bg-gradient.pngas the background.
OmniPizza/
├── backend/ # FastAPI backend + Swagger/OpenAPI
├── frontend/ # React + Vite web app
├── frontend-mobile/ # Expo / React Native app
├── tests/ # API integration tests (Vitest)
├── docs/ # Build/release notes
├── ordersuccess_ios/ # Product, design, and tech docs
└── screenshots/ # Reference UI captures
Both clients are being organized around feature slices instead of only technical folders.
frontend/src/features/*frontend-mobile/src/features/*
Current slices include auth, catalog, checkout, country, profile, and orderSuccess.
The pattern used in both web and mobile is:
- repository layer for API access
- use-case layer for orchestration / payload building / validation
- UI pages and screens consuming those feature modules
Compatibility wrappers still exist in a few older hook paths so migration can remain incremental.
Current supporting docs live here:
- docs/app-built.md — mobile release/build pipeline
ordersuccess_ios/Product_Requirement_Doc.md— product requirementsordersuccess_ios/Design_Doc.md— architecture and UX notesordersuccess_ios/UI_Design_Doc.md— visual systemordersuccess_ios/Tech_Stack_Doc.md— stack decisions
cd backend
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
python3 main.py- Swagger: http://localhost:8000/api/docs
cd frontend
pnpm install
pnpm devThe web client reads
VITE_API_URLwhen provided, otherwise defaults tohttp://localhost:8000. On macOS/Linux you can run:VITE_API_URL=http://localhost:8000 pnpm dev
cd frontend-mobile
pnpm install
pnpm ios # or pnpm androidConfiguration:
- Mobile is configured to use the Render API (
https://omnipizza-backend.onrender.com) strictly, with mock data fallback removed.- Real Authentication: Uses
/api/auth/loginto obtain valid JWT tokens.- Market selection at login: user picks market on the login screen (flag selector).
- Localization: Full i18n support for Profile, Checkout, and Navbar.
- Error Handling: Includes UI for connection retries.
- Orientation:
frontend-mobile/app.jsonuses"orientation": "default"for device rotation.
To run against local backend, change
API_ORIGINinfrontend-mobile/src/api/client.ts.
The tests/ directory contains automated API integration tests written in TypeScript with Vitest.
cd tests
pnpm install
pnpm test # Run all tests
pnpm test:watch # Watch mode
pnpm test:ui # Interactive UIRequires the backend running on http://localhost:8000 (or set API_BASE_URL).
Test suites: Auth login, Pizza catalog, Checkout validation, Locked-out user, E2E standard flow, Country-specific logic (MX/US/CH/JP), Debug endpoints.
Legacy Python contract tests (Schemathesis) are also available — see
tests/README.md.
The web app includes Cypress Component Testing for shared UI components.
cd frontend
pnpm install
pnpm test:ct
pnpm test:ct:openCurrent component specs live in frontend/cypress/component/.
- frontend-component-tests.yml
Runs Cypress component tests on pull requests touching
frontend/**. It is currently non-blocking (continue-on-error: true). - mobile-release.yml Builds Android and iOS simulator artifacts through manual dispatch.
/api/pizzasrequiresX-Country-Codeheader for market pricing.- Use the test users to validate reliability and chaos behaviors.
- All interactive elements have
data-testidattributes for stable selectors. - Checkout form fields are dynamic per market — ensure automation handles conditional rendering.
- Phone input uses
type="tel"with pattern validation (7-20 digits/spaces/+/-). - Cart state injection: Use
POST /api/cartto seed cart items, then navigate to checkout — the frontend auto-hydrates fromGET /api/cart. This skips the manual catalog-to-cart UI flow in E2E tests.
MIT














