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