innhold/tests
Ruben b8e6d2537d Add browser and unit test suite with Pest + Playwright
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.
2026-03-17 16:43:39 +01:00
..
Browser Add browser and unit test suite with Pest + Playwright 2026-03-17 16:43:39 +01:00
Unit Add browser and unit test suite with Pest + Playwright 2026-03-17 16:43:39 +01:00
.gitignore Add browser and unit test suite with Pest + Playwright 2026-03-17 16:43:39 +01:00
composer.json Add browser and unit test suite with Pest + Playwright 2026-03-17 16:43:39 +01:00
Pest.php Add browser and unit test suite with Pest + Playwright 2026-03-17 16:43:39 +01:00
README.md Add browser and unit test suite with Pest + Playwright 2026-03-17 16:43:39 +01:00

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: 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:

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.