Skip to content

Browser lifecycle

playwright-page wires the browser lifecycle into a describe block. It launches one browser for the group, creates a fresh context and page for each example, and closes them afterward so examples stay isolated.

Setup

Call playwright-page at the top of a describe, passing the fixture to load:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
use BDD::Behave;
use BDD::Behave::Playwright;

describe 'the greeting page', {
  playwright-page(fixture => 'specs/fixtures/hello.html');

  it 'shows the greeting', {
    expect(page.locator('#greeting').text-content).to.eq('Hello, world');
  }
}

The page term

use BDD::Behave::Playwright brings a page term into scope that returns the current page:

1
2
3
4
it 'fills a field', {
  page.locator('#name').fill('Ada');
  expect(page.locator('#name').input-value).to.eq('Ada');
}

The same page is also reachable through the example's topic parameter as .page, for blocks written -> $_ { ... }:

1
2
3
it 'fills a field', -> $_ {
  .page.locator('#name').fill('Ada');
}

Each example gets its own context and page, so state set in one example does not leak into the next.

Scope

  • One browser is launched per describe group, in a before-all hook.
  • Each example gets a fresh context and page, created in before-each and published as the page term.
  • The context is closed in after-each; the browser is closed in after-all.

Watching the browser

The browser runs headless by default. Set SHOW_CHROME to launch it headed, so the window is visible while the examples drive it:

1
SHOW_CHROME=1 behave specs/some-browser-spec.raku

headless-from-env reads the variable and is what playwright-page passes to launch. An unset variable, or the value 0, stays headless; any other value runs headed. Headed runs suit watching a suite locally. Leave it unset in CI.

Fixtures

fixture-url turns a filesystem path into an absolute file:// URL:

1
fixture-url('specs/fixtures/hello.html');  # file:///abs/path/specs/fixtures/hello.html

playwright-page(fixture => ...) calls it for you. Pass an absolute or working-directory-relative path to a local HTML file. Browser tests run against local file:// fixtures, never the network.

A base URL and visit

To drive a running application instead of a file fixture, give playwright-page a base-url. visit then navigates the current page to a path beneath it:

1
2
3
4
5
6
7
8
describe 'the dashboard', {
  playwright-page(base-url => 'http://127.0.0.1:8080');

  it 'greets the user', -> $_ {
    visit('/dashboard');
    expect(.page.locator('#welcome')).to.have-text('Welcome');
  }
}

visit('/path') joins the path onto the base URL. An absolute URL (visit('http://...')) is used unchanged. goto($url) navigates to a URL directly, without the base.

The base URL may be a callable, which is resolved at navigation time. That suits a server whose address is known only once it has started, such as a test server bound to an ephemeral port:

1
playwright-page(base-url => { test-server-url() });

Context options

context passes options through to the browser context that each example runs in, so a describe can emulate a device, such as a mobile viewport, a color scheme, or a locale:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
describe 'the mobile menu', {
  playwright-page(
    base-url => 'http://127.0.0.1:8080',
    context  => { viewport => { width => 390, height => 844 } });

  it 'shows the hamburger toggle', -> $_ {
    visit('/');
    expect(.page.locator('.menu-toggle')).to.be-visible;
  }
}

The keys are the options that WWW::Playwright's new-context accepts, such as viewport, is-mobile, has-touch, color-scheme, and locale.