Files
simple-pos-system/PLANS AND STRATEGIES/TESTING_CHECKLIST.md

9.7 KiB

POS System — End-to-End Testing Checklist

Work through this top-to-bottom. Each section depends on the one above it.
Mark [x] as you go. Note failures with a short comment.


0. Prerequisites

  • Docker Desktop is running
  • You are in the project root: c:\development\simple-pos-system
  • All .env files are filled in correctly (see below)

.env quick reference

cloud_backend/.env

SECRET_KEY=<long random string>
DATABASE_URL=sqlite:////app/data/cloud.db
ACCESS_TOKEN_EXPIRE_MINUTES=60
ADMIN_USERNAME=sysadmin
ADMIN_PASSWORD=<your password>

local_backend/.env

SITE_ID=<filled in after step 2.4>
SITE_KEY=<filled in after step 2.4>
CLOUD_URL=http://cloud_backend:8001
SECRET_KEY=<long random string>
LICENSE_GRACE_HOURS=24

sysadmin_panel/.env

VITE_CLOUD_URL=http://localhost:8001

waiter_pwa/.env

VITE_API_URL=http://<local-backend-ip>:8000

manager_dashboard/.env

VITE_API_URL=http://<local-backend-ip>:8000

1. Cloud Backend

1.1 Start

docker compose up cloud_backend -d
  • Container starts without errors (docker compose logs cloud_backend)

1.2 Health check

GET http://localhost:8001/health
  • Returns {"status": "ok"}

1.3 Sysadmin login

POST http://localhost:8001/api/auth/login
Body: { "username": "sysadmin", "password": "changeme" }
  • Returns a JWT access_token
  • Save token for next steps

1.4 List sites (empty)

GET http://localhost:8001/api/sites/
Header: Authorization: Bearer <token>
  • Returns [] (empty list)

2. Sysadmin Panel

2.1 Start

docker compose up sysadmin_panel -d
  • Container starts, npm install completes, dev server on port 5175

2.2 Open in browser

http://localhost:5175
  • Redirects to /login
  • Login form appears (username + password, NOT pin pad)

2.3 Login

  • Enter sysadmin / changeme → redirects to /sites
  • Sites page shows "0 registered", "Register New Site" button visible
  • Summary counts (Active / Locked / Expired) visible

2.4 Register a site

  • Click "Register New Site"
  • Form fields: Restaurant Name, Owner Name, Contact Email, License Expiry
  • Fill in test data, set expiry date to at least 1 year from now
  • Submit → success screen shows
  • Site ID and Secret Key are displayed
  • Warning banner "Copy this secret key now" is visible
  • "Copy .env vars" button works (copies to clipboard)
  • Copy the SITE_ID and SITE_SECRET values
  • Paste them into local_backend/.env as SITE_ID= and SITE_KEY=

2.5 Verify site in list

  • Navigate to /sites → new site card appears
  • Status shows yellow "No Heartbeat" (expected — local backend hasn't connected yet)
  • Click site card → SiteDetailPage shows correct name, owner, expiry
  • Lock/Unlock/Extend License buttons are visible

3. Local Backend

3.1 Start

docker compose up backend -d
  • Container starts without errors
  • Logs show: Application startup complete
  • Logs show cloud sync attempt: either Cloud sync OK or Cloud sync failed (if cloud URL not yet reachable from inside Docker — check CLOUD_URL=http://cloud_backend:8001)

3.2 Health check

GET http://localhost:8000/api/system/health
  • Returns {"status": "ok"} (this endpoint is exempt from license check)

3.3 Heartbeat appears in sysadmin panel

  • In Sysadmin Panel → SiteDetailPage: "Last seen" updates to recent timestamp
  • Status indicator turns green "Active"
  • Last IP field shows the Docker container IP

Note: Cloud sync runs immediately on startup, so this should update within seconds.

3.4 Auth — create initial manager

If no manager user exists in the DB yet, seed one via the seed script or direct API call:

docker compose exec backend python seed.py
  • Seed runs without errors (or manager already exists)

3.5 Auth — login as manager

POST http://localhost:8000/api/auth/login
Body: { "username": "manager", "pin": "1234" }
  • Returns { access_token, user: { id, username, role: "manager" } }

3.6 Auth — login as waiter

POST http://localhost:8000/api/auth/login
Body: { "username": "<waiter-username>", "pin": "<pin>" }
  • Returns token with role: "waiter"

3.7 Tables endpoint

GET http://localhost:8000/api/tables/
Header: Authorization: Bearer <manager-token>
  • Returns list of tables (may be empty if not seeded)

3.8 Products endpoint

GET http://localhost:8000/api/products/
Header: Authorization: Bearer <manager-token>
  • Returns list of products and categories

4. Manager Dashboard

4.1 Start

docker compose up manager_dashboard -d
  • Dev server starts on port 5174

4.2 Open in browser

http://localhost:5174
  • Redirects to /login
  • PIN pad + username field visible

4.3 Login

  • Enter manager username + PIN → redirects to /dashboard
  • Dashboard shows table grid (empty or with existing tables)
  • No console errors

4.4 Tables page

  • Navigate to Tables → existing tables shown
  • Create a new table (e.g. Table 10) → appears in list
  • Table groups section visible

4.5 Products page

  • Navigate to Products → existing products shown
  • Create a new category
  • Create a new product in that category, assign a price
  • Toggle product availability → greyed out when unavailable
  • Assign a printer zone to a product (if printer is configured)
  • Product image upload works on an existing product

4.6 Waiters page

  • Navigate to Waiters → existing waiters shown
  • Create a new waiter (username + PIN)
  • Block/unblock a waiter works
  • Reset PIN works

4.7 Dashboard live grid

  • Open an order from the Waiter PWA (step 5 below), then return here
  • Table card updates within 30 seconds (polling interval)
  • Click table → OrderDetailPage loads with correct items

4.8 Reports page

  • Navigate to Reports → no crash
  • Date picker works, summary loads (may be empty)

4.9 Settings page

  • Navigate to Settings → no crash
  • Printer config visible

5. Waiter PWA

5.1 Open on phone (or browser)

http://<local-machine-ip>:5173
  • App loads, redirects to /login
  • Username field + PIN pad visible

5.2 Login as waiter

  • Enter waiter credentials → redirects to table list
  • Only active tables visible (not deactivated ones)

5.3 Open a table order

  • Tap a table → if no open order, "Open Order" button appears
  • Tap "Open Order" → order is created, table turns active

5.4 Add items

  • Category tabs visible at top
  • Tap a product → added to order
  • Products with options show option selector
  • Products with removable ingredients show toggle list
  • Item with note field → can add freetext note

5.5 Verify print routing

  • After adding items: check printer (if connected) received the ticket
  • If no physical printer: check docker compose logs backend — should show print attempt log (success or failure, NOT a crash)

5.6 View order total

  • Order total shows correct sum (base price + selected option deltas)
  • Individual item prices shown

5.7 Partial payment

  • Select some items → "Mark as Paid" → those items turn grey/paid
  • Order status changes to "partially_paid"
  • Remaining total updates

5.8 Full payment and close

  • Mark all items as paid → order status = "paid"
  • "Close Order" button becomes active
  • Tap "Close Order" → confirmation prompt
  • Confirm → order closes, table returns to "available"

5.9 Multi-waiter scenario

  • From Manager Dashboard, add a second waiter to the order
  • Second waiter can see and manage the table in their PWA

5.10 Blocked waiter

  • From Manager Dashboard, block a waiter
  • That waiter is immediately redirected to login on their next PWA request (401 interceptor)

6. License / Lock Testing

6.1 Lock site from sysadmin panel

  • In Sysadmin Panel → SiteDetailPage → Lock Site → enter reason → confirm
  • Site shows "Locked" status with red indicator
  • Within the next sync cycle (or restart local backend to force immediate sync):
    • Local backend logs show lock status received
    • All local backend endpoints return HTTP 423 (except /api/system/health)
    • Waiter PWA shows error / cannot load data
    • Manager Dashboard shows error

6.2 Unlock

  • In Sysadmin Panel → Unlock Site
  • After next sync: local backend resumes normal operation

6.3 Expired license

  • In Sysadmin Panel → Extend License → set expiry date in the PAST → save
  • After local backend sync: returns HTTP 402 on all endpoints
  • Restore to future date → normal operation resumes

6.4 Cloud unreachable (grace period)

  • Stop cloud backend: docker compose stop cloud_backend
  • Local backend continues to serve requests (last known state + 24h grace)
  • Logs show repeated Cloud sync failed warnings
  • Restart cloud backend → next sync succeeds

7. Known Issues to Watch For

  • Product image upload only works on existing products (not at creation time)
  • Printer zone must be assigned via Manager Dashboard before items will route to a printer
  • Some manager/PWA interactions have rough edges (noted in CLAUDE_CODE_INSTRUCTIONS.md)
  • SITE_KEY in local_backend/.env must match the secret generated at site registration (copy it immediately, it's shown only once)

Done?

All steps checked → the system is fully operational end-to-end.
Log any failures as GitHub issues or in CLAUDE_CODE_INSTRUCTIONS.md under a new "Phase 5 Known Issues" section.