# Test Suite Browser tests using [Pest](https://pestphp.com/) + [pest-plugin-browser](https://github.com/pestphp/pest-plugin-browser) (Playwright/Chromium). ## Run tests ```bash podman compose -f compose.test.yaml run --rm test ``` The `app` service (the site) starts automatically via `depends_on`. Tests run against `http://app.dns.podman` inside the Podman network. ## Structure ``` tests/ composer.json # pestphp/pest ^4, pestphp/pest-plugin-browser ^4 Pest.php # defines BASE_URL and CUSTOM_DIR constants; groups unit tests Browser/ # browser tests (require running app + Playwright) HomepageTest.php NavigationTest.php LanguageTest.php PetitionTest.php Screenshots/ # auto-saved on failure (gitignored) Unit/ # unit tests (pure PHP, no browser needed) PetitionFormTest.php ``` ## Writing unit tests Place tests in `tests/Unit/`. The constant `CUSTOM_DIR` points to `custom/` on the host. Since `custom/` plugins are written as framework plugins (they call `Hooks::add()` and reference `Context`), stub those classes before requiring the file: ```php toBe('expected'); }); ``` Only test functions from `custom/` — `app/` has its own test suite. ## Writing browser tests All browser tests use `$this` for the Playwright page object via pest-plugin-browser. ```php it('describes behavior', function () { $this->visit(BASE_URL . '/path') ->assertSee('text') // visible text ->assertSourceHas('html snippet') // raw HTML/source ->assertPresent('css selector') // element exists in DOM ->click('css selector') ->press('input[type="submit"]') // click button/submit ->assertSee('expected result'); }); ``` Place new test files in `tests/Browser/`. No registration needed — Pest autodiscovers `*Test.php` files. **Reference:** [pestphp.com/docs/browser-testing](https://pestphp.com/docs/browser-testing) — full list of interactions (`type()`, `select()`, `check()`, `drag()`, …) and assertions (`assertUrlIs()`, `assertAttribute()`, `assertNoJavaScriptErrors()`, …). ## Infrastructure - **Containerfile.test**: `php:8.4-cli-bookworm` + Node 22 + Composer + Playwright Chromium at `/opt/playwright` - **compose.test.yaml**: `app` service = the site; `test` service = runner; mounts `./tests` as volume so edits apply without rebuild - **Pest.php**: `BASE_URL` defaults to `http://app` if `APP_URL` not set ## Rebuild image Only needed after changing `Containerfile.test` or `composer.json`: ```bash podman compose -f compose.test.yaml build test ``` ## Agent workflow When modifying or adding code in `custom/` or `content/`: 1. Run the existing test suite first to establish a baseline. 2. Make your changes. 3. Run tests again. All previously passing tests must still pass. 4. If your change adds new behavior, add a test for it in `tests/Browser/`. 5. Do not mark work done until the test suite passes (excluding pre-existing known failures listed below). Failed tests save screenshots to `tests/Browser/Screenshots/` — read them to diagnose rendering issues. ## Known failures None.