Repository navigation
Testing
php artisan test46 PHPUnit feature tests (331 assertions) run against a real MySQL/MariaDB database (bookmymovie_test). They cover the booking flow, seat holds, the unique live-seat key, idempotent checkout, cancellations and refunds, snacks with gift cards and points, payments and signed URLs, bans, commerce rules, group bookings, waitlists, admin roles, SEO limits, error-page noindex, the Usher assistant and the Vite build manifest.
The Docker stack (Apache + PHP 8.3, MySQL 8.4, Redis, queue worker, scheduler) was run with APP_ENV=production and 15 simulated people, each in its own container with its own IP address:
| Group | What they did |
|---|---|
| 4 browsers | Home, films, film pages, seat maps, cinemas, offers, FAQ, search and Usher for 90 seconds |
| 8 buyers | All pressed "hold" on the same seat in the same instant, then held their own seats, checked out with a double-tapped Confirm, opened their bookings and some cancelled |
| 3 staff | Owner, manager and box office opened every admin page in a loop |
Results of the final run:
- About 1,900 requests with no 5xx responses and no logged exceptions. Median response 100 to 160 ms, 95th percentile under 0.55 s.
- One of the eight buyers got the contested seat; the other seven were told straight away that it had just been taken.
- Every double-tapped Confirm produced exactly one booking, and both taps landed on it.
- Each staff role saw exactly its own pages and got 403 for the rest.
61 checks, all passing: every admin page for each role; creating, editing, pausing and deleting coupons; snack stock; pausing film sales; member, IP and device bans and unbans; review moderation; issuing gift cards; verifying, rejecting forged and admitting tickets at the door; refunds (and refusing a second refund); broadcasts; refusing unknown actions; and the audit log.
Nonce-based CSP with a fresh nonce per response and no unsafe-inline; X-Frame-Options, nosniff, Referrer-Policy, Permissions-Policy; HSTS on HTTPS; no X-Powered-By or server version; HttpOnly SameSite session cookie. CSRF-less and forged-token POSTs are rejected without side effects. No XSS reflection, no SQL injection through search, route parameters or admin search. Guessed booking numbers return 404, and staff roles are enforced. .env, .git, logs and vendor are not served, and no stack traces leak. Logins need the image code, admin login is rate limited, a 150-request burst from one IP is throttled by the abuse shield, and oversized bodies are refused. All stored passwords are Argon2id.
- A database CHECK constraint rejected every booking that used snacks, a gift card or loyalty points, and the customer saw "one of your seats was just booked".
- Opening a booking with snacks failed because the snacks pivot inherited the bookings table's
booked_attimestamp name. - Cancelling without a reason, or issuing a gift card without a recipient, raised an error instead of using the default.
- The second tap of a double-tapped Confirm showed "your hold expired" instead of the booking it had just made.
- Banning a member could also block the admin's own browser if it appeared in the member's device list.
BookMyMovie · MIT licence · by Syed Ahmer Shah · Project page
Run it
How it works
Operate it
Read more