Capabilities
Using Playwright with BrowserStack requires passing the custom capabilities in an object, and passing this object to the Playwright URL endpoint on BrowserStack. This section includes a sample script file along with a detailed reference of all the supported capabilities.
// fixtures.js
const base = require('@playwright/test');
const cp = require('child_process');
const clientPlaywrightVersion = cp
.execSync('npx playwright --version')
.toString()
.trim()
.split(' ')[1];
const BrowserStackLocal = require('browserstack-local');
// BrowserStack Specific Capabilities.
const caps = {
os: 'osx',
os_version: 'catalina',
browser: 'chrome',
browser_version: 'latest',
'browserstack.username': process.env.BROWSERSTACK_USERNAME || 'YOUR_USERNAME',
'browserstack.accessKey': process.env.BROWSERSTACK_ACCESS_KEY || 'YOUR_ACCESS_KEY',
'browserstack.geoLocation': 'FR',
project: 'My First Project',
build: 'playwright-build-1',
name: 'My first playwright test',
buildTag: 'reg',
resolution: '1280x1024',
'browserstack.local': 'true',
'browserstack.localIdentifier': 'local_connection_name',
'browserstack.playwrightVersion': '1.latest',
'client.playwrightVersion': '1.latest',
'browserstack.debug': 'true', // enabling visual logs
'browserstack.console': 'info' // Enabling Console logs for the test
'browserstack.networkLogs': 'true' // Enabling network logs for the test
'browserstack.interactiveDebugging': 'true',
}
exports.bsLocal = new BrowserStackLocal.Local();
// replace YOUR_ACCESS_KEY with your key. You can also set an environment variable - "BROWSERSTACK_ACCESS_KEY".
exports.BS_LOCAL_ARGS = {
key: process.env.BROWSERSTACK_ACCESS_KEY || 'YOUR_ACCESS_KEY',
};
// Patching the capabilities dynamically according to the project name.
const patchCaps = (name, title) => {
let combination = name.split(/@browserstack/)[0];
let [browerCaps, osCaps] = combination.split(/:/);
let [browser, browser_version] = browerCaps.split(/@/);
let osCapsSplit = osCaps.split(/ /);
let os = osCapsSplit.shift();
let os_version = osCapsSplit.join(' ');
caps.browser = browser ? browser : 'chrome';
caps.browser_version = browser_version ? browser_version : 'latest';
caps.os = os ? os : 'osx';
caps.os_version = os_version ? os_version : 'catalina';
caps.name = title;
};
const isHash = (entity) => Boolean(entity && typeof(entity) === "object" && !Array.isArray(entity));
const nestedKeyValue = (hash, keys) => keys.reduce((hash, key) => (isHash(hash) ? hash[key] : undefined), hash);
const isUndefined = val => (val === undefined || val === null || val === '');
const evaluateSessionStatus = (status) => {
if (!isUndefined(status)) {
status = status.toLowerCase();
}
if (status === "passed") {
return "passed";
} else if (status === "failed" || status === "timedout") {
return "failed";
} else {
return "";
}
}
exports.test = base.test.extend({
page: async ({ page, playwright }, use, testInfo) => {
// Use BrowserStack Launched Browser according to capabilities for cross-browser testing.
if (testInfo.project.name.match(/browserstack/)) {
patchCaps(testInfo.project.name, `${testInfo.file} - ${testInfo.title}`);
const vBrowser = await playwright.chromium.connect({
wsEndpoint:
`wss://cdp.browserstack.com/playwright?caps=` +
`${encodeURIComponent(JSON.stringify(caps))}`,
});
const vContext = await vBrowser.newContext(testInfo.project.use);
const vPage = await vContext.newPage();
await use(vPage);
const testResult = {
action: 'setSessionStatus',
arguments: {
status: evaluateSessionStatus(testInfo.status),
reason: nestedKeyValue(testInfo, ['error', 'message'])
},
};
await vPage.evaluate(() => {},
`browserstack_executor: ${JSON.stringify(testResult)}`);
await vPage.close();
await vBrowser.close();
} else {
use(page);
}
},
});
// single_test.js
const expect = require('chai').expect
const { chromium } = require('playwright');
const cp = require('child_process');
const clientPlaywrightVersion = cp.execSync('npx playwright --version').toString().trim().split(' ')[1];
(async () => {
const caps = {
'os': 'os x',
'os_version': 'big sur',
'browser': 'chrome', // You can choose `chrome`, `edge` or `firefox` in this capability
'browser_version': 'latest', // We support v83 and above. You can choose `latest`, `latest-beta`, `latest-1`, `latest-2` and so on, in this capability
'browserstack.username': process.env.BROWSERSTACK_USERNAME || 'YOUR_USERNAME',
'browserstack.accessKey': process.env.BROWSERSTACK_ACCESS_KEY || 'YOUR_ACCESS_KEY',
'browserstack.geoLocation': "FR",
'project': 'My First Project',
'build': 'playwright-build-1',
'name': 'My First Test', // The name of your test and build. See browserstack.com/docs/automate/playwright/organize tests for more details
'buildTag': 'reg',
'resolution': '1280x1024',
'browserstack.local': 'true',
'browserstack.localIdentifier': 'local_connection_name',
'browserstack.playwrightVersion': '1.latest',
'client.playwrightVersion': '1.latest'
'browserstack.debug': 'true', // enabling visual logs
'browserstack.console': 'info' // Enabling Console logs for the test
'browserstack.networkLogs': 'true' // Enabling network logs for the test
'browserstack.interactiveDebugging': 'true',
};
const browser = await chromium.connect({
wsEndpoint: `wss://cdp.browserstack.com/playwright?caps=${encodeURIComponent(JSON.stringify(caps))}`,
});
const page = await browser.newPage();
await page.goto('https://www.google.com/ncr');
const element = await page.$('[aria-label="Search"]');
await element.click();
await element.type('BrowserStack');
await element.press('Enter');
const title = await page.title('');
console.log(title);
try {
expect(title).to.equal("BrowserStack - Google Search", 'Expected page title is incorrect!');
// following line of code is responsible for marking the status of the test on BrowserStack as 'passed'. You can use this code in your after hook after each test
await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'passed',reason: 'Title matched'}})}`);
} catch {
await page.evaluate(_ => {}, `browserstack_executor: ${JSON.stringify({action: 'setSessionStatus',arguments: {status: 'failed',reason: 'Title did not match'}})}`);
}
await browser.close();
})();
// PlaywrightTest.java
package com.browserstack;
import com.google.gson.JsonObject;
import com.microsoft.playwright.*;
import java.net.URLEncoder;
public class PlaywrightTest {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
JsonObject capabilitiesObject = new JsonObject();
capabilitiesObject.addProperty("os", "osx");
capabilitiesObject.addProperty("os_version", "catalina");
capabilitiesObject.addProperty("browser", "chrome"); // allowed browsers are `chrome`, `edge`, `playwright-chromium`, `playwright-firefox` and `playwright-webkit`
capabilitiesObject.addProperty("browser_version", "latest");
capabilitiesObject.addProperty("browserstack.username", "BROWSERSTACK_USERNAME");
capabilitiesObject.addProperty("browserstack.accessKey", "BROWSERSTACK_ACCESS_KEY");
capabilitiesObject.addProperty("browserstack.geoLocation", "FR");
capabilitiesObject.addProperty("project", "My First Project");
capabilitiesObject.addProperty("build", "playwright-java-1");
capabilitiesObject.addProperty("name", "Playwright first single test");
capabilitiesObject.addProperty("buildTag", "reg");
capabilitiesObject.addProperty("resolution", "1280x1024");
capabilitiesObject.addProperty("browserstack.local", "true");
capabilitiesObject.addProperty("browserstack.localIdentifier", "local_connection_name");
capabilitiesObject.addProperty("browserstack.playwrightVersion", "1.latest");
capabilitiesObject.addProperty("client.playwrightVersion", "1.latest");
capabilitiesObject.addProperty("browserstack.debug", "true");
capabilitiesObject.addProperty("browserstack.console", "info");
browserstackOptions.Add("browserstack.interactiveDebugging", "true");
capabilitiesObject.addProperty("browserstack.networkLogs", "true");
BrowserType chromium = playwright.chromium();
String caps = URLEncoder.encode(capabilitiesObject.toString(), "utf-8");
String ws_endpoint = "wss://cdp.browserstack.com/playwright?caps=" + caps;
Browser browser = chromium.connect(ws_endpoint);
Page page = browser.newPage();
try {
page.navigate("https://www.google.co.in/");
Locator locator = page.locator("[aria-label='Search']");
locator.click();
page.fill("[aria-label='Search']", "BrowserStack");
page.locator("[aria-label='Google Search'] >> nth=0").click();
String title = page.title();
if (title.equals("BrowserStack - Google Search")) {
// following line of code is responsible for marking the status of the test on BrowserStack as 'passed'. You can use this code in your after hook after each test
markTestStatus("passed", "Title matched", page);
} else {
markTestStatus("failed", "Title did not match", page);
}
} catch (Exception err) {
markTestStatus("failed", err.getMessage(), page);
}
browser.close();
} catch (Exception err) {
System.out.println(err);
}
}
public static void markTestStatus(String status, String reason, Page page) {
Object result;
result = page.evaluate("_ => {}", "browserstack_executor: { \"action\": \"setSessionStatus\", \"arguments\": { \"status\": \"" + status + "\", \"reason\": \"" + reason + "\"}}");
}
}
# playwright-test.py
import json
import urllib
import subprocess
from playwright.sync_api import sync_playwright
desired_cap = {
'os': 'osx',
'os_version': 'catalina',
'browser': 'chrome', # allowed browsers are `chrome`, `edge`, `playwright-chromium`, `playwright-firefox` and `playwright-webkit`
'browser_version': 'latest', # this capability is valid only for branded `chrome` and `edge` browsers and you can specify any browser version like `latest`, `latest-beta`, `latest-1` and so on.
'browserstack.username': 'BROWSERSTACK_USERNAME',
'browserstack.accessKey': 'BROWSERSTACK_ACCESS_KEY',
'browserstack.geoLocation': 'FR',
'project': 'My First Project',
'build': 'playwright-python-1',
'name': 'My First Test',
'buildTag': 'reg',
'resolution': '1280x1024',
'browserstack.local': 'true',
'browserstack.localIdentifier': 'local_connection_name',
'browserstack.playwrightVersion': '1.latest',
'client.playwrightVersion': '1.latest'
'browserstack.debug': 'true', # enabling visual logs
'browserstack.console': 'info', # Enabling Console logs for the test
'browserstack.networkLogs': 'true', # Enabling network logs for the test
'browserstack.interactiveDebugging': 'true',
}
def run_session(playwright):
clientPlaywrightVersion = str(subprocess.getoutput('playwright --version')).strip().split(" ")[1]
desired_cap['client.playwrightVersion'] = clientPlaywrightVersion
cdpUrl = 'wss://cdp.browserstack.com/playwright?caps=' + urllib.parse.quote(json.dumps(desired_cap))
browser = playwright.chromium.connect(cdpUrl)
page = browser.new_page()
try:
page.goto("https://www.google.co.in/")
page.fill("[aria-label='Search']", 'Browserstack')
locator = page.locator("[aria-label='Google Search'] >> nth=0")
locator.click()
title = page.title()
if title == "Browserstack - Google Search":
# following line of code is responsible for marking the status of the test on BrowserStack as 'passed'. You can use this code in your after hook after each test
mark_test_status("passed", "Title matched", page)
else:
mark_test_status("failed", "Title did not match", page)
except Exception as err:
mark_test_status("failed", str(err), page)
browser.close()
def mark_test_status(status, reason, page):
page.evaluate("_ => {}", "browserstack_executor: {\"action\": \"setSessionStatus\", \"arguments\": {\"status\":\""+ status + "\", \"reason\": \"" + reason + "\"}}");
with sync_playwright() as playwright:
run_session(playwright)
// PlaywrightTest.cs
using Microsoft.Playwright;
using System.Threading.Tasks;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
class PlaywrightTest
{
public static async Task main(string[] args)
{
using var playwright = await Playwright.CreateAsync();
Dictionary<string, string> browserstackOptions = new Dictionary<string, string>();
browserstackOptions.Add("os", "osx");
browserstackOptions.Add("os_version", "catalina");
browserstackOptions.Add("browser", "chrome"); // allowed browsers are `chrome`, `edge`, `playwright-chromium`, `playwright-firefox` and `playwright-webkit`
browserstackOptions.Add("browser_version", "latest");
browserstackOptions.Add("browserstack.username", "BROWSERSTACK_USERNAME");
browserstackOptions.Add("browserstack.accessKey", "BROWSERSTACK_ACCESS_KEY");
browserstackOptions.Add("geoLocation", "FR");
browserstackOptions.Add("project", "Playwright first sample test");
browserstackOptions.Add("name", "Playwright first sample test");
browserstackOptions.Add("build", "playwright-dotnet-1");
browserstackOptions.Add("buildTag", "reg");
browserstackOptions.Add("resolution", "1280x1024");
browserstackOptions.Add("browserstack.local", "true");
browserstackOptions.Add("browserstack.localIdentifier", "local_connection_name");
browserstackOptions.Add("browserstack.playwrightVersion", "1.latest");
browserstackOptions.Add("client.playwrightVersion", "1.latest");
browserstackOptions.Add("browserstack.debug", "true");
browserstackOptions.Add("browserstack.interactiveDebugging", "true");
browserstackOptions.Add("browserstack.console", "info");
browserstackOptions.Add("browserstack.networkLogs", "true");
string capsJson = JsonConvert.SerializeObject(browserstackOptions);
string cdpUrl = "wss://cdp.browserstack.com/playwright?caps=" + Uri.EscapeDataString(capsJson);
await using var browser = await playwright.Chromium.ConnectAsync(cdpUrl);
var page = await browser.NewPageAsync();
try {
await page.GotoAsync("https://www.google.co.in/");
await page.Locator("[aria-label='Search']").ClickAsync();
await page.FillAsync("[aria-label='Search']", "BrowserStack");
await page.Locator("[aria-label='Google Search'] >> nth=0").ClickAsync();
var title = await page.TitleAsync();
if (title == "BrowserStack - Google Search")
{
// following line of code is responsible for marking the status of the test on BrowserStack as 'passed'. You can use this code in your after hook after each test
await MarkTestStatus("passed", "Title matched", page);
}
else {
await MarkTestStatus("failed", "Title did not match", page);
}
}
catch (Exception err) {
await MarkTestStatus("failed", err.Message, page);
}
await browser.CloseAsync();
}
public static async Task MarkTestStatus(string status, string reason, IPage page) {
await page.EvaluateAsync("_ => {}", "browserstack_executor: {\"action\": \"setSessionStatus\", \"arguments\": {\"status\":\"" + status + "\", \"reason\": \"" + reason + "\"}}");
}
}
The following table lists the supported Playwright capabilities and how they must be defined in your tests:
Capability | Description |
---|---|
os |
Set the operating system on which you want to run your test Eg. Windows or OS X Ref: Specify which OS is to be used to run the test |
os_version |
Set the specific version of the OS Eg. Windows: 10 , 11 or OS X: Mojave , Catalina , Big Sur , Monterey , Ventura and Sequoia Ref: Specify which OS version is to be used to run the test |
browser |
Set the browser you want to use for your test. For branded browsers, use: chrome or edge .The browser_version capability is applicable only when using a branded browser. For Playwright’s bundled browsers, use: playwright-chromium , playwright-firefox or playwright-webkit .Ref: Specify the browser to be used |
browser_version |
Set the browser version for your test Chrome: 83 and above Edge: 83 and above It is recommended that you use latest , latest-1 , latest-2 , latest-beta and so on, to test on the latest n versions of the required browser. Ref: Specify the browser version to be used |
browserstack.username |
Your BrowserStack username which you can find in your account settings. |
browserstack.accessKey |
Your BrowserStack access key which you can find in your account settings. |
browserstack.geolocation |
Simulate the location of browsers "geolocation": "<country_code>"
|
project |
Any string that you want to group your builds into. Eg. New dashboard Ref: Specify a name for your project |
build |
A string that you want to identify your build with. Eg. build 1 Ref: Specify a name for your build or CI run |
name |
A string that you want to identify your session with. Eg. My Test Ref: Specify a name for your build or CI run |
buildTag |
A string that you want to tag your build with. Eg. sanity Ref: Specify a tag for your test build |
resolution |
Set the resolution of your desktop OS before beginning your test Default resolution is 1920x1080 Ref: Specify desktop screen resolution |
browserstack.local |
Test your locally hosted website on BrowserStack. Defaults to false . Set value as true to enable. |
browserstack.localIdentifier |
Specify the unique Local Testing connection name. Eg. local_connection_name
|
browserstack.playwrightVersion |
Specify the Playwright version for your tests. Use 1.latest to run tests on the latest version. Ref: Set the supported Playwright version in your tests |
client.playwrightVersion |
Specify the Playwright version for your tests on the client system. Use 1.latest to run tests on the latest version. Set a Playwright version on the client machine |
browserstack.maskCommands |
Redacts sensitive information from the Automate logs. Ref: Prevent sensitive test data from appearing in the Automate logs. |
browserstack.debug |
Automatically capture screenshots for every Playwright command executed during your test. It helps debug the exact step and how the page was rendered when the failure occurred. Defaults to False . Set True to enable. |
browserstack.video |
Provides a video recording of the actions performed during the test. Available by default. Set false to disable.Ref: Records every test as it is executed on BrowserStack |
browserstack.console |
Captures the browser’s console output at various steps of the test. Available by default. Set value as disable to disable the console logs. Ref: Capture the browser’s console output at various steps of the test |
browserstack.networkLogs |
Provides a comprehensive log of all network activity during your Playwright tests. Default: false . Set true to enable. |
browserstack.networkLogsOptions |
Captures the request and response payload of your test session Default: false . Set true to enable. |
browserstack.interactiveDebugging |
Allows you to debug interactively while a session is in progress Default: true . Set false to enable. |
We're sorry to hear that. Please share your feedback so we can do better
Contact our Support team for immediate help while we work on improving our docs.
We're continuously improving our docs. We'd love to know what you liked
- RESOURCES
We're sorry to hear that. Please share your feedback so we can do better
Contact our Support team for immediate help while we work on improving our docs.
We're continuously improving our docs. We'd love to know what you liked
Thank you for your valuable feedback!