Files
workavia-mail-front/docs/adr/0080-patrol-web-integration-test-setup.md
T

5.2 KiB

80. Patrol Web Integration Test — Setup & Execution

Date: 2026-04-15

Status

Accepted

  • ADR-0053 — Patrol for mobile integration testing (foundation)
  • ADR-0081 — Cross-platform test architecture
  • ADR-0082 — Migration guide & implementation example
  • ADR-0083 — PR-by-PR migration plan

Context

ADR-0053 established Patrol for mobile (Android/iOS) integration testing. As Twake Mail is also deployed as a web app, the same level of E2E coverage is needed on the browser. Patrol 4.x added Chrome support via --device=chrome, making it feasible to extend the existing setup without introducing a second testing framework.

Decision

Use Patrol with Chrome as the target device for web integration testing, sharing the same backend Docker infrastructure used for mobile tests.

Prerequisites

  • Flutter 3.38.9
  • Patrol CLI 4.3.1: dart pub global activate patrol_cli 4.3.1
  • patrol package 4.5.0 (and patrol_finders 3.x, patrol_log 0.8.x) — requires upgrading from the 3.x currently in pubspec.yaml
  • Docker Desktop (running)
  • openssl installed (used to generate JWT keys for the backend)

Unlike mobile tests, web tests do not require ngrok or jq. The app runs at localhost and Chrome connects to it directly — no traffic forwarding needed.

Environment Variables

All tests receive configuration via --dart-define. Store values in an env file and source it in the run scripts — this keeps credentials out of command-line history and git history (add the file to .gitignore):

# integration_test/test_config.env
BASIC_AUTH_URL=http://localhost/
USERNAME=test_user
PASSWORD=test_password
BASIC_AUTH_EMAIL=test@example.com
ADDITIONAL_MAIL_RECIPIENT=recipient@example.com

The run scripts source this file and forward each value:

source integration_test/test_config.env
patrol test \
  --dart-define=BASIC_AUTH_URL=$BASIC_AUTH_URL \
  --dart-define=USERNAME=$USERNAME \
  --dart-define=PASSWORD=$PASSWORD \
  --dart-define=BASIC_AUTH_EMAIL=$BASIC_AUTH_EMAIL \
  --dart-define=ADDITIONAL_MAIL_RECIPIENT=$ADDITIONAL_MAIL_RECIPIENT \
  ...
Variable Description
BASIC_AUTH_URL App server URL (e.g. http://localhost/)
USERNAME Test account username
PASSWORD Test account password
BASIC_AUTH_EMAIL Test account email address
ADDITIONAL_MAIL_RECIPIENT Secondary email for multi-recipient tests

--dart-define-from-file only accepts JSON, not .env format, so sourcing in the script is the correct approach.

Running Locally (with visible browser)

./scripts/patrol-web-local-integration-test-with-docker.sh

This starts the Docker backend, then runs patrol with Chrome visible. Useful during development.

To run a single test file, edit the script and replace patrol test -v with:

patrol test -v -t integration_test/tests/composer/send_email_test.dart

After migrating to the architecture defined in ADR-0081, test files no longer have a web_ prefix — one file covers all platforms.

Running in CI (headless)

./scripts/patrol-web-integration-test-with-docker.sh

Adds --web-headless=true — no display required. The GitHub Actions workflow (.github/workflows/patrol-web-integration-test.yaml) runs this script on pull requests.

CI Orchestration — Running the Full Project

Mobile and web test suites run as separate parallel jobs in CI. Each job targets its own platform:

PR opened / push
│
├── job: patrol-mobile-integration-test   (ubuntu-latest + Android emulator)
│     patrol test --device=android
│
└── job: patrol-web-integration-test      (ubuntu-latest + Chrome via Patrol)
      ./scripts/patrol-web-integration-test-with-docker.sh
      # patrol test --device=chrome --web-headless=true

The two jobs are independent — they share no state and can run concurrently. A PR is gated on both jobs passing.

Platform filtering is handled automatically by runPatrolTest() (see ADR-0082). Tests that do not apply to the current platform skip themselves — no --exclude-tags flag needed in either job.

Viewing Results

  • Terminal: Patrol prints pass/fail per test with full stack traces on failure.
  • GitHub Actions: Results appear in the workflow run summary under the "Test" step. Each platform job has its own step, making it easy to identify which platform a failure comes from.

Consequences

  • Web and mobile tests share the same test files; platform-only tests skip themselves in runPatrolTest() — no manual tagging required.
  • The same Docker JMAP backend serves both platforms — no additional infrastructure needed.
  • Data isolation limitations from ADR-0053 still apply: backend state is shared across all tests in a single run.
  • Patrol automatically installs and manages Chromium — no manual Chrome installation is needed on local machines or CI runners.