Add browser test for logout #56

Closed
opened 2026-08-18 23:53:21 +02:00 by myrmidex · 1 comment
Owner

Gap

POST /logout has no browser test and no feature test — it is the only auth route with neither.

Scope

Cover, in tests/Browser/Auth/LogoutTest.php:

  • Logging out from an authenticated session redirects to the login page
  • Protected routes (/dashboard, /dishes, /schedule, /users) redirect to login afterwards
  • The back button does not restore an authenticated view

The session/CSRF behaviour here is worth exercising in a real browser — there is a /refresh-csrf route, which suggests token handling has needed attention.

Blocked by #54

Write in Pest browser syntax after the Dusk → Pest migration.

Acceptance

  • Logout redirects correctly
  • Protected routes inaccessible after logout
  • Back button does not expose an authenticated view
  • Green in CI
## Gap `POST /logout` has no browser test and no feature test — it is the only auth route with neither. ## Scope Cover, in `tests/Browser/Auth/LogoutTest.php`: - Logging out from an authenticated session redirects to the login page - Protected routes (`/dashboard`, `/dishes`, `/schedule`, `/users`) redirect to login afterwards - The back button does not restore an authenticated view The session/CSRF behaviour here is worth exercising in a real browser — there is a `/refresh-csrf` route, which suggests token handling has needed attention. ## Blocked by #54 Write in Pest browser syntax after the Dusk → Pest migration. ## Acceptance - [ ] Logout redirects correctly - [ ] Protected routes inaccessible after logout - [ ] Back button does not expose an authenticated view - [ ] Green in CI
myrmidex added this to the v0.9.0 milestone 2026-08-18 23:53:21 +02:00
myrmidex added the
testing
label 2026-08-18 23:53:21 +02:00
myrmidex added a new dependency 2026-08-18 23:54:07 +02:00
myrmidex self-assigned this 2026-08-20 20:25:54 +02:00
Author
Owner

Done

All four acceptance criteria met.

  • Logout redirects correctly
  • Protected routes inaccessible after logout
  • Back button does not expose an authenticated view
  • Green in CI — run #24, both jobs success

Commits

Commit Change
95c5a72 tests/Browser/Auth/LogoutTest.php + shared logout() helper in tests/Pest.php
c1d8008 Session-invalidation feature test; fixed the pest-browser helper in shell.nix
b543f5f Feature tests for /refresh-csrf

Coverage added

tests/Browser/Auth/LogoutTest.php — 3 tests, 24 assertions:

  • logout lands on the login page
  • /dashboard, /dishes, /schedule, /users all redirect to login afterwards (dataset)
  • back button does not restore an authenticated view

tests/Feature/AuthenticationTest.php:

  • test_logout_invalidates_the_session — asserts the session ID changes and session data is flushed
  • two /refresh-csrf tests — the route returned the live CSRF token to both guests and authenticated users, and had no coverage at all before this

Full suite is 160 tests (was 157); browser suite 34 passing.

Notes for future work

Two selector traps in the nav (resources/views/components/layouts/app.blade.php), both of which cause Playwright to hang silently rather than fail:

  1. Blade renders Alpine's shorthand as the literal @click attribute — a selector written as button[x-on\:click="..."] matches nothing.
  2. The nav renders two "Logout" submit buttons (desktop dropdown + sm:hidden mobile overlay). Bare-text press('Logout') goes through the plugin's GuessLocatorgetByText() under unstrict, which silently picks the first match — the hidden one — then waits forever for it to become actionable.

The shared logout() helper in tests/Pest.php scopes to the desktop form with an explicit CSS selector to avoid both. Selectors containing CSS special characters run in Playwright strict mode, so an ambiguous one errors loudly instead of hanging — prefer those over bare text.

Not covered: the full CSRF recovery flow (419 → Livewire fail hook → refetch → token swapped into the meta tag). That depends on client-side JS and needs a browser test; the feature tests only pin the route's response contract. Worth a follow-up ticket if that path is considered risky.

shell.nix: pest-browser previously hardcoded the suite path, so passing a path doubled it and Pest died with "already uses the test case". It now accepts either form. Note this requires leaving and re-entering nix-shell to take effect.

## Done All four acceptance criteria met. - [x] Logout redirects correctly - [x] Protected routes inaccessible after logout - [x] Back button does not expose an authenticated view - [x] Green in CI — run #24, both jobs success ### Commits | Commit | Change | |---|---| | `95c5a72` | `tests/Browser/Auth/LogoutTest.php` + shared `logout()` helper in `tests/Pest.php` | | `c1d8008` | Session-invalidation feature test; fixed the `pest-browser` helper in `shell.nix` | | `b543f5f` | Feature tests for `/refresh-csrf` | ### Coverage added `tests/Browser/Auth/LogoutTest.php` — 3 tests, 24 assertions: - logout lands on the login page - `/dashboard`, `/dishes`, `/schedule`, `/users` all redirect to login afterwards (dataset) - back button does not restore an authenticated view `tests/Feature/AuthenticationTest.php`: - `test_logout_invalidates_the_session` — asserts the session ID changes and session data is flushed - two `/refresh-csrf` tests — the route returned the live CSRF token to both guests and authenticated users, and had no coverage at all before this Full suite is 160 tests (was 157); browser suite 34 passing. ### Notes for future work **Two selector traps in the nav** (`resources/views/components/layouts/app.blade.php`), both of which cause Playwright to hang silently rather than fail: 1. Blade renders Alpine's shorthand as the literal `@click` attribute — a selector written as `button[x-on\:click="..."]` matches nothing. 2. The nav renders **two** "Logout" submit buttons (desktop dropdown + `sm:hidden` mobile overlay). Bare-text `press('Logout')` goes through the plugin's `GuessLocator` → `getByText()` under `unstrict`, which silently picks the first match — the hidden one — then waits forever for it to become actionable. The shared `logout()` helper in `tests/Pest.php` scopes to the desktop form with an explicit CSS selector to avoid both. Selectors containing CSS special characters run in Playwright **strict** mode, so an ambiguous one errors loudly instead of hanging — prefer those over bare text. **Not covered:** the full CSRF recovery flow (419 → Livewire `fail` hook → refetch → token swapped into the meta tag). That depends on client-side JS and needs a browser test; the feature tests only pin the route's response contract. Worth a follow-up ticket if that path is considered risky. **`shell.nix`:** `pest-browser` previously hardcoded the suite path, so passing a path doubled it and Pest died with "already uses the test case". It now accepts either form. Note this requires leaving and re-entering `nix-shell` to take effect.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference: lvl0/dishplanner#56
No description provided.