Skip to content

Architecture ​

Test Lifecycle ​

The test lifecycle is bookended by global setup and teardown. Global setup starts the shared halOP container once, then each Playwright worker starts its own WildFly container via a worker-scoped fixture. Page objects are created per test, and everything tears down in reverse order when tests complete.

Spec files run in parallel across multiple workers (4 locally, 2 in CI). Tests within a spec file are sequential. Each test file gets its own isolated WildFly container per browser project via a worker-scoped Playwright fixture backed by testcontainers. Tests run in Chromium, Firefox, and WebKit.

For a detailed walkthrough of the four fixture layers, see Fixtures.

Parallelism and Container Instances ​

The simple rule is: each spec file gets its own WildFly container. Two spec files never share a container, and tests within the same spec file always share one.

This works because Playwright assigns each spec file to a worker (an OS process), and the WildFly container is created by a worker-scoped fixture — a Playwright mechanism that ties the container's lifetime to the worker. Since each worker runs exactly one spec file, the mapping is always 1:1:1:

one worker = one spec file = one WildFly container

The fixture is the code that starts and stops the container (defined in wildfly.fixture.ts). The container is the actual Docker/Podman instance running WildFly. There's always exactly one container per fixture instance, so in practice the terms refer to the same thing — but "container" is what matters to test authors.

Playwright runs three browser projects (Chromium, Firefox, WebKit). Each project runs every spec file independently, so the same spec gets a separate container in each browser:

ConceptRelationship
Spec fileGets its own dedicated WildFly container — full isolation between specs
WorkerRuns one spec file; owns one WildFly container for its lifetime
Browser projectEach spec runs independently per browser, so the same spec gets a separate container in Chromium, Firefox, and WebKit
ParallelismUp to workers spec files run simultaneously per browser project (4 local, 2 CI)
Tests within a specRun sequentially (fullyParallel: false), sharing that spec's WildFly container

Total WildFly containers at peak = min(workers, spec_count) per browser project. With 10 spec files and 4 workers running Chromium, at most 4 containers run concurrently for Chromium; finished workers pick up the next spec file.

The container lifecycle: started before the first test in a worker, shared by all tests in that spec file, stopped after the last test finishes.

WildFly Container Fixture ​

WildFly containers are managed by a worker-scoped Playwright fixture defined in src/fixtures/wildfly.fixture.ts. Spec files that need WildFly and page objects import test from pages.fixture.ts and declare their spec path:

typescript
import { test, expect } from "../../fixtures/pages.fixture.js";

test.use({ specPath: "smoke/dashboard" });

The fixture starts a container before any test in the worker runs and stops it after the last test finishes. Container names follow the pattern dave_<path>_<project> (e.g., dave_smoke_dashboard_chromium). Ports are dynamically allocated.

Spec files that don't need WildFly (e.g., app-loads.spec.ts) import test and expect from wildfly.fixture.ts.

Page Object Model ​

Custom Playwright fixtures in src/fixtures/pages.fixture.ts provide page objects to each test. Page objects are pure UI concerns (locators and actions) — they don't know about WildFly URLs or infrastructure. The fixture layer handles navigation via openHalOp(page, managementUrl) before handing each page object to the test, so tests receive ready-to-use pages. Check pages.fixture.ts for the current list of available fixtures.

Tests import test and expect from ../fixtures/pages.fixture instead of @playwright/test. For guidance on creating new page objects, see Page Objects.

Element Identification ​

Tests use OUIA attributes for element selection, following PatternFly's testing conventions. The OUIA component IDs are generated locally from halOP's OuiaIds.java source file into src/selectors/ids.ts. Run pnpm sync:ouia to regenerate after upstream changes — no npm release required.

See Sync for details on keeping OUIA IDs up to date.

Project Structure ​

text
dave/
  global-setup.ts                    # Start halOP before tests
  global-teardown.ts                 # Stop halOP after tests
  playwright.config.ts               # Playwright configuration
  scripts/                           # Sync scripts (OUIA IDs, container image)
  src/
    fixtures/
      wildfly.fixture.ts             # WildFly container lifecycle (worker-scoped)
      pages.fixture.ts               # OUIA enablement, navigation, page object registry
    pages/                           # Page objects (one per UI section)
    selectors/
      ids.ts                         # Generated OUIA ID constants (do not edit)
    tags.ts                          # Tag constants for test grouping
    tests/                           # Test specs organized by feature (smoke/, configuration/, ...)
    utils/
      wildfly-container.ts           # WildFly container lifecycle
      ouia.ts                        # OUIA attribute selector helper
      container-runtime.ts           # Auto-detect Podman or Docker
      configure-testcontainers.ts    # Testcontainers config

UI test suite for halOP — the WildFly management console