Add comprehensive test coverage for core site features (content, navigation, language, FAQ, news, petition, newsletter) using Pest browser tests and unit tests for custom plugins. Includes test infrastructure (Containerfile.test, compose.test.yaml), test documentation, and test files covering petition form logic, CSV handling, translation, date formatting, rate limiting, and map data building. |
||
|---|---|---|
| .. | ||
| Browser | ||
| Unit | ||
| .gitignore | ||
| composer.json | ||
| Pest.php | ||
| README.md | ||
Test Suite
Browser tests using Pest + pest-plugin-browser (Playwright/Chromium).
Run tests
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
class Context {}
class Hook { const TEMPLATE_VARS = 'template_vars'; }
class Hooks { public static function add(string $hook, callable $fn): void {} }
require_once CUSTOM_DIR . '/plugins/page/my-plugin.php';
it('does something', function () {
expect(myFunction('input'))->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.
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 — 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:
appservice = the site;testservice = runner; mounts./testsas volume so edits apply without rebuild - Pest.php:
BASE_URLdefaults tohttp://appifAPP_URLnot set
Rebuild image
Only needed after changing Containerfile.test or composer.json:
podman compose -f compose.test.yaml build test
Agent workflow
When modifying or adding code in custom/ or content/:
- Run the existing test suite first to establish a baseline.
- Make your changes.
- Run tests again. All previously passing tests must still pass.
- If your change adds new behavior, add a test for it in
tests/Browser/. - 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.