cbPlaywright
End-to-End Tests with Playwright and TestBox





https://slides.com/elpete/itb2023-cbplaywright

What this talk is
- An overview of cbPlaywright
- An overview of Playwright Java
- How to use the companion CommandBox library
- A few end-to-end testing selector strategies
- Live coding cbPlaywright tests


What this talk isn't
- About unit, integration, or any other kind of testing besides end-to-end (or browser) tests
- Comparison to other end-to-end testing tools
- Deep dive into end-to-end testing best practices




What is cbPlaywright?


- Includes the necessary jars and drivers to run Playwright Java
- Provides integration with TestBox and ColdBox tests
- Helper methods for making interacting with Playwright Java easier
What is cbPlaywright?


So...what is Playwright?



CFML


If Playwright Java exists...why would I use cbPlaywright?


Includes the necessary jars to run Playwright Java



Companion CommandBox module for downloading the correct platform drivers



Helper functions to turn this....
var screenshotOptions = createObject( "java", "com.microsoft.playwright.Page$ScreenshotOptions" ).init();
var screenshotPath = createObject( "java", "java.nio.file.Paths" ).get(
javacast( "String", expandPath( "/tests/results/screenshotOne.png" ) ), javacast( "String[]", [] )
);
screenshotOptions.setPath( screenshotPath );
page.screenshot( screenshotOptions );
...into this
screenshotPage( page, "/tests/results/screenshotOne.png" );


Installation


box install cbPlaywright


Unfortunately, there is more this time....


There's this thing called a driver....
- Running the driver from the Playwright Java jars was finicky
- The driver-bundle jar is very large (about 200 MB unzipped)
- The driver-bundle included versions for all the platforms
- You ended up downloading a full driver-bundle for every cbPlaywright installation.
- Interacting with the driver CLI was a pain


CommandBox cbPlaywright


CommandBox cbPlaywright
- Installs as a dependency of cbPlaywright
- Manages installing the correct driver for your platform
- Automatically downloads a driver on install
- Provides a passthrough to the Playwright CLI
# Install the Playwright driver
cbplaywright driver install
# Install Chromium as a test browser
playwright install chromium


Configuration

// tests/Application.cfc
component {
this.javaSettings = {
loadPaths: directoryList(
rootPath & "modules/cbPlaywright/lib",
true,
"array",
"*jar"
),
loadColdFusionClassPath: true,
reloadOnChange: false
};
}

Add the Jar Paths

// tests/Application.cfc
component {
this.mappings[ "/cbPlaywright" ] = rootPath & "/modules/cbPlaywright";
}

Create a Mapping

// .env
CBPLAYWRIGHT_DRIVER_DIR=/path/to/driver/directory

Set the Driver Path
(OPTIONAL)


Usage


Creating a Test

component extends="cbPlaywright.models.PlaywrightTestCase" {
function run() {
// ...
}
}

Extend the Playwright Test Case
component extends="cbPlaywright.models.ColdBoxPlaywrightTestCase" {
function run() {
// ...
}
}

component extends="cbPlaywright.models.PlaywrightTestCase" {
function run() {
describe( "Playwright Tests", () => {
it( "can visit the Google homepage", () => {
var browser = launchBrowser( variables.playwright.chromium() );
var page = browser.newPage();
navigate( page, "https://google.com" );
waitForLoadState( page );
expect( page.title() ).toBe( "Google" );
} );
} );
}
}

Visit a Page

component extends="cbPlaywright.models.PlaywrightTestCase" {
function run() {
describe( "Playwright Tests", () => {
it( "can perform a search on Google", () => {
var browser = launchBrowser( variables.playwright.chromium() );
var page = browser.newPage();
navigate( page, "https://google.com" );
waitForLoadState( page );
var searchBox = locateElement( page, '[aria-label="Search"]' );
fill( searchBox, "playwright" );
press( searchBox, "Enter" );
expect( page.url() ).toInclude( "https://www.google.com/search?q=playwright" );
} );
} );
}
}

Fill Out a Form


What makes a good Selector?


- Role
- Label Text
- Placeholder Text
- Text
- Display Value
What makes a good Selector?
1. Queries Accessible to Everyone
2. Semantic Queries
3. Test IDs
- Alt Text
- Title

component extends="cbPlaywright.models.PlaywrightTestCase" {
function run() {
describe( "Playwright Tests", () => {
it( "can visit the Google homepage", () => {
var browser = launchBrowser( variables.playwright.chromium() );
var page = browser.newPage();
navigate( page, "https://google.com" );
waitForLoadState( page );
expect( page.title() ).toBe( "Google" );
screenshotPage( page, "/tests/results/homepage.png" );
} );
} );
}
}

Take a Screenshot

component extends="cbPlaywright.models.PlaywrightTestCase" {
function run() {
describe( "Playwright Tests", () => {
it( "fill out the search form and click a link", () => {
var browser = launchBrowser( variables.playwright.chromium() );
newRecordedContextForBrowser( browser, "/tests/results/videos", ( context ) => {
var page = context.newPage();
navigate( page, "https://google.com" );
waitForLoadState( page );
var searchBox = locateElement( page, '[aria-label="Search"]' );
fill( searchBox, "playwright" );
press( searchBox, "Enter" );
expect( page.url() ).toInclude( "https://www.google.com/search?q=playwright" );
click(
locateElement(
page,
"text=Playwright: Fast and reliable end-to-end testing for modern ..."
)
);
waitForUrl( page, "https://playwright.dev/" );
} );
} );
} );
}
}
Record a Video

component extends="cbPlaywright.models.PlaywrightTestCase" {
function run() {
describe( "Playwright Tests", () => {
it( "fill out the search form and click a link", () => {
var browser = launchBrowser( variables.playwright.chromium() );
var context = browser.newContext();
traceContext( context, "/tests/results/trace.zip", function() {
var page = context.newPage();
navigate( page, "https://google.com" );
waitForLoadState( page );
var searchBox = locateElement( page, '[aria-label="Search"]' );
fill( searchBox, "playwright" );
press( searchBox, "Enter" );
expect( page.url() ).toInclude( "https://www.google.com/search?q=playwright" );
click(
locateElement(
page,
"text=Playwright: Fast and reliable end-to-end testing for modern ..."
)
);
waitForUrl( page, "https://playwright.dev/" );
} );
} );
} );
}
}
Save a Trace


Save a Trace



Demo


Bonus

name: PRs and Branches
on:
- push
jobs:
tests:
runs-on: ubuntu-latest
name: Tests
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Setup Java JDK
uses: actions/setup-java@v1.4.3
with:
java-version: 11
- name: Set Up CommandBox
uses: elpete/setup-commandbox@v1.0.0
- name: Install dependencies
run: box install
- name: Start server
run: box server start
- name: Install Playwright dependencies
run: |
box playwright-cli install-deps
box playwright-cli install chromium
- name: Run TestBox Tests
run: box testbox run

GitHub Actions

CFCamp 2023 — cbPlaywright
By Eric Peterson
CFCamp 2023 — cbPlaywright
- 367