# Testing SiteCraft

Four layers of automated tests, plus a short manual checklist for a release.

| Suite | What it is | Runs against | Command |
|---|---|---|---|
| Integration self-test | 312 checks of services and rules, inside a transaction that is rolled back | the configured database | `php spark sitecraft:selftest` |
| HTTP smoke tests | 697 end-to-end checks with curl, phase by phase (Phase 1–8) and the public marketing site | a running server, **development** database (it is reset) | `bash tests/smoke/run_all.sh` |
| Tenant isolation sweep | every private route called with another tenant's IDs | same as above (run by `run_all.sh`) | `python3 tests/smoke/isolation_sweep.py` |
| Browser tests | the real GrapesJS editor (19 checks) and a responsive/CSP/accessibility sweep (59 pages × 3 screen sizes) | a running server with smoke-test data | `cd tests/e2e && npm test` |

## Running everything

```bash
php spark serve                              # terminal 1 (or Apache/XAMPP on :8080)
php spark sitecraft:selftest                 # terminal 2
bash tests/smoke/run_all.sh                  # resets the DEV database, seeds demo data, runs all HTTP suites
cd tests/e2e && npm install && npx playwright install chromium && npm test
```

> `run_all.sh` runs `migrate:refresh`, which **deletes all data** in the configured database. Never point it at production.

Requirements: PHP CLI, `mysql`/`mysqldump` clients, `curl`, `python3`, and for the browser tests Node 18+.

The smoke tests reach stores at `<name>.sitecraft.test:8080` by sending the `Host` header to `localhost`, so no hosts-file changes are needed. Mail is written to `writable/mail/` (no SMTP configured) and payments use the built-in Razorpay simulator (`razorpay.simulator = true`).

## What each suite covers

**Self-test** (`app/Commands/SelfTest.php`): tenant scoping and isolation, registration and auth rules, password policy and lockout, subscription lifecycle and plan limits, page rendering and sanitising, publishing, domain verification logic, catalog, stock and concurrency rules, pricing/GST, orders, payment signatures, plan billing (quotes, proration, amount mismatch, idempotency), store payments (reservation, capture, expiry, late payment, refunds), coupons, shipping zones, customer accounts, redirects, blog, SEO audit, media usage protection, analytics privacy and counting.

**Smoke tests** (`tests/smoke/phaseN.sh`):
1. sign-up, verification, sign-in, lockout, password reset, roles, isolation basics
2. admin panel, websites, subscriptions, plan limits, team invites, support, settings
3. templates, editor API, publishing, revisions, page SEO, uploads
4. live stores on subdomains and custom domains, menus, forms, caching, sitemap/robots
5. catalog, cart, checkout (COD), orders, invoices, emails
6. plan payments and store payments through the simulator (forged/tampered callbacks, replays, webhooks, refunds), coupons, shipping, customer accounts
7. media library, blog, SEO settings and redirects, SEO audit, analytics, platform reports
8. security headers and CSP, no inline scripts, health endpoint, error pages, doctor and backups

`marketing.sh`: public pages, prices matching the plans table (hidden plans not shown), template gallery filters and live previews (drafts 404), robots/sitemap, structured data, no JavaScript or cookies, sign-up intent carried into the dashboard, sign-up buttons hidden when registrations are closed.

**Isolation sweep** (`tests/smoke/isolation_sweep.py`): as merchant A, every dashboard/builder GET and POST route with merchant B's IDs → GETs must be 403/404 and a hash of all of B's rows must be unchanged; every admin route → 403; every private page → login redirect when signed out; POST without CSRF → refused.

**Browser tests** (`tests/e2e`):
- `editor.e2e.js` — inline editing, shared header, styles, devices, undo/redo, themes, pages, images, custom HTML, save/reload/publish, two tabs on one site, and that the server renders exactly what the editor shows.
- `ux.e2e.js` — 59 marketing, dashboard, admin, sign-in and store pages at 375, 768 and 1366 px: nothing wider than the screen, no CSP violations or JavaScript errors, and no serious/critical accessibility problems (axe-core, WCAG 2.1 AA) at desktop size.

## Manual release checklist

Before tagging a release, on a staging server set up like production (HTTPS, real SMTP, Razorpay **test** keys, `razorpay.simulator = false`):

- [ ] `php spark sitecraft:doctor` — no problems
- [ ] Register a merchant with a real inbox; verification email arrives; sign in
- [ ] Create a website from a template, edit text and an image, publish; open the store on its subdomain over HTTPS
- [ ] Connect a custom domain (real DNS); it becomes Connected and gets a certificate
- [ ] Add a product with a variant and stock; place a COD order; merchant and customer emails arrive
- [ ] Connect Razorpay test keys in the store; pay an order with a test card/UPI; the order turns paid; refund part of it
- [ ] Buy a plan with Razorpay test mode; receipt arrives; plan changes; webhook shows in *Admin → Payments*
- [ ] Publish a blog post; it appears on `/blog`, in the RSS feed and sitemap
- [ ] Check a store page and the dashboard on a phone
- [ ] Run `php spark backup:run`, restore the dump into a scratch database
