Skip to main content

Run your first Playwright test on BrowserStack

Learn how to run your first Playwright tests across 100+ browser-OS combinations.

Introduction

Playwright allows you to perform end-to-end testing across all browsers. It is equipped with multiple features, such as resiliency, auto-wait, capturing test trace, and so on, that are supported with BrowserStack.

In this guide, you will learn about:

Prerequisites

  • BrowserStack Username and Access key, which you can find in your account settings. If you have not created an account yet, you can sign up for a Free Trial or purchase a plan.
  • Before you can start running your Playwright tests with C#, set up a visual studio project as follows. If you already have a working C# setup to run Playwright tests, skip these steps:
    1. Open visual studio and create a new empty project as follows: Create a New Project
    2. After the project loads, click File -> New File and create an empty C# file as follows: Create a New File

Run your first test

To run your first Playwright test on BrowserStack, complete the following steps:

Step 1: Clone the playwright-browserstack sample repo on GitHub using the following command in your terminal:

git clone https://github.com/browserstack/playwright-browserstack
cd playwright-browserstack/playwright-test/
git clone https://github.com/browserstack/playwright-browserstack
cd playwright-browserstack
git clone https://github.com/browserstack/playwright-browserstack
playwright-browserstack/playwright-java/
git clone https://github.com/browserstack/playwright-browserstack
cd playwright-browserstack/playwright-python/
git clone https://github.com/browserstack/playwright-browserstack
cd playwright-browserstack/playwright-dotnet/

Step 2: Install dependencies using the following command in your terminal:

npm install
npm install
mvn clean install
pip install --upgrade pip 
pip install playwright
playwright install
 dotnet build

Step 3: Set your BrowserStack credentials in the script as follows:

Navigate to the fixtures.js file in the playwright-browserstack/playwright-test/ directory and enter YOUR_USERNAME and YOUR_ACCESS_KEY

const caps = {
    'browserstack.username': process.env.BROWSERSTACK_USERNAME || 'YOUR_USERNAME',
    'browserstack.accessKey': process.env.BROWSERSTACK_ACCESS_KEY || 'YOUR_ACCESS_KEY',
  };

Navigate to the single_test.js file in the playwright-browserstack/ directory and set YOUR_USERNAME and YOUR_ACCESS_KEY

const caps = {
    'browserstack.username': process.env.BROWSERSTACK_USERNAME || 'YOUR_USERNAME',
    'browserstack.accessKey': process.env.BROWSERSTACK_ACCESS_KEY || 'YOUR_ACCESS_KEY',
  };

Navigate to the PlaywrightTest.java file in the playwright-java/src/test/java/com/browserstack/ directory and set your BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY

JsonObject capabilitiesObject = new JsonObject();
            capabilitiesObject.addProperty("browserstack.username", "BROWSERSTACK_USERNAME");
            capabilitiesObject.addProperty("browserstack.accessKey", "BROWSERSTACK_ACCESS_KEY");

Navigate to the playwright-test.py file in the playwright-browserstack/playwright-python/ directory and set your BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY

desired_cap = {
  'browserstack.username': 'BROWSERSTACK_USERNAME',
  'browserstack.accessKey': 'BROWSERSTACK_ACCESS_KEY'
}

Navigate to the PlaywrightTest.cs file in the playwright-browserstack/playwright-dotnet/PlaywrightTest.cs directory and set your BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY

Dictionary<string, string> browserstackOptions = new Dictionary<string, string>();
browserstackOptions.Add("browserstack.username", "BROWSERSTACK_USERNAME");
browserstackOptions.Add("browserstack.accessKey", "BROWSERSTACK_ACCESS_KEY");

Alternatively, you can set the environment variables in your system as follows:

# Set these values in your ~/.zprofile (zsh) or ~/.profile (bash)
  export BROWSERSTACK_USERNAME="YOUR_USERNAME"
  export BROWSERSTACK_ACCESS_KEY="YOUR_ACCESS_KEY"
# setx.exe does not set the environment variable in the current command prompt, but it will be available in subsequent command prompts
  setx BROWSERSTACK_USERNAME="YOUR_USERNAME"
  setx BROWSERSTACK_ACCESS_KEY="YOUR_ACCESS_KEY"

# Verify whether the variables have been set
echo BROWSERSTACK_USERNAME
echo BROWSERSTACK_ACCESS_KEY

Step 4: Run your first test using the following command in your terminal:

npm test
node single_test.js
mvn -Dexec.mainClass="com.browserstack.PlaywrightSingleTest" -Dexec.classpathScope=test test-compile exec:java

python single-playwright-test.py
dotnet run single

Step 5: View your tests on BrowserStack on the BrowserStack Automate dashboard. Check out viewing test results to learn more about the dashboard.

Understand the details of your test

When you run your test command, the test script:

  • Starts the latest version of the Chrome browser
  • Opens the Google search home page
  • Performs a search for the term “BrowserStack”
  • Marks the test as passed or failed based on the assertions

When you run the test command, tests present in the fixure.js file are executed

// 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 = {
  browser: 'chrome',
  os: 'osx',
  os_version: 'catalina',
  name: 'My first playwright test',
  build: 'playwright-build-1',
  'browserstack.username': process.env.BROWSERSTACK_USERNAME || 'YOUR_USERNAME',
  'browserstack.accessKey':
    process.env.BROWSERSTACK_ACCESS_KEY || 'YOUR_ACCESS_KEY',
  'browserstack.local': process.env.BROWSERSTACK_LOCAL || false,
  'client.playwrightVersion': clientPlaywrightVersion,
};

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);

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 vPage = await vBrowser.newPage(testInfo.project.use);
      await use(vPage);
      const testResult = {
        action: 'setSessionStatus',
        arguments: {
          status: testInfo.status,
          reason: nestedKeyValue(testInfo, ['error', 'message'])
        },
      };
      await vPage.evaluate(() => {},
      `browserstack_executor: ${JSON.stringify(testResult)}`);
      await vPage.close();
      await vBrowser.close();
    } else {
      use(page);
    }
  },
});
// playwright.config.js
// @ts-check

const { devices } = require('@playwright/test');

/** @type {import('@playwright/test').PlaywrightTestConfig} */
const config = {
  testDir: 'tests',
  testMatch: '**/*.spec.js',
  timeout: 60000,
  use:{
    viewport: null
  },
  projects: [
    // -- BrowserStack Projects --
    // name should be of the format browser@browser_version:os os_version@browserstack
    {
      name: 'chrome@latest:Windows 10@browserstack',
      use: {
        browserName: 'chromium',
        channel: 'chrome'
      },
    },
    {
      name: 'chrome@latest-beta:OSX Big Sur@browserstack',
      use: {
        browserName: 'chromium',
        channel: 'chrome',
      },
    },
    {
      name: 'edge@90:Windows 10@browserstack',
      use: {
        browserName: 'chromium'
      },
    },
    {
      name: 'playwright-firefox@latest:OSX Catalina@browserstack',
      use: {
        browserName: 'firefox',
        ignoreHTTPSErrors: true
      },
    },
    {
      name: 'playwright-webkit@latest:OSX Big Sur@browserstack',
      use: {
        browserName: 'webkit',
        // Config to use playwright emulated devices.
        // ...devices['iPhone 12 Pro Max'],
      },
    },
    // -- Local Projects --

    // Test against playwright browsers
    // {
    //   name: "chrome",
    //   use: {
    //     browserName: "chromium",
    //     // Test against Chrome channel.
    //     channel: "chrome",
    //   },
    // },
    // {
    //   name: "safari",
    //   use: {
    //     browserName: "webkit",
    //     viewport: { width: 1200, height: 750 },
    //   },
    // },
    // {
    //   name: "firefox",
    //   use: {
    //     browserName: "firefox",
    //     viewport: { width: 800, height: 600 },
    //   },
    // },
    //  Test against mobile viewports.
    // {
    //   name: "chrome@pixel5",
    //   use: {
    //     ...devices["Pixel 5"]
    //   }
    // },
  ],
};
module.exports = config;

When you run the test command, tests present in the single_test.js file are executed

// 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 = {
  	'browser': 'chrome',  // allowed browsers are `chrome`, `edge`, `playwright-chromium`, `playwright-firefox` and `playwright-webkit`
    'os': 'osx',
    'os_version': 'catalina',
    'name': 'My first playwright test',
    'build': 'playwright-build-1',
    'browserstack.username': process.env.BROWSERSTACK_USERNAME || 'YOUR_USERNAME',
    'browserstack.accessKey': process.env.BROWSERSTACK_ACCESS_KEY || 'YOUR_ACCESS_KEY',
    'client.playwrightVersion': clientPlaywrightVersion  // Playwright version being used on your local project needs to be passed in this capability for BrowserStack to be able to map request and responses correctly
  };
  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();
})();

When you run the test command, tests present in the PlaywrightTest.java file are executed

// 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("browser", "chrome");    // allowed browsers are `chrome`, `edge`, `playwright-chromium`, `playwright-firefox` and `playwright-webkit`
            capabilitiesObject.addProperty("browser_version", "latest");
            capabilitiesObject.addProperty("os", "osx");
            capabilitiesObject.addProperty("os_version", "catalina");
            capabilitiesObject.addProperty("name", "Playwright first single test");
            capabilitiesObject.addProperty("build", "playwright-java-1");
            capabilitiesObject.addProperty("browserstack.username", "BROWSERSTACK_USERNAME");
            capabilitiesObject.addProperty("browserstack.accessKey", "BROWSERSTACK_ACCESS_KEY");
            
            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 + "\"}}");
    }
}

When you run the test command, tests present in the playwright-test.py file are executed

# playwright-test.py

import json
import urllib
import subprocess
from playwright.sync_api import sync_playwright

desired_cap = {
  '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.
  'os': 'osx',
  'os_version': 'catalina',
  'name': 'Branded Google Chrome on Catalina',
  'build': 'playwright-python-1',
  'browserstack.username': 'BROWSERSTACK_USERNAME',
  'browserstack.accessKey': 'BROWSERSTACK_ACCESS_KEY'
}

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)

When you run the test command, tests present in the PlaywrightTest.cs file are executed

// 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("name", "Playwright first sample test");
        browserstackOptions.Add("build", "playwright-dotnet-1");
        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("browserstack.username", "BROWSERSTACK_USERNAME");
        browserstackOptions.Add("browserstack.accessKey", "BROWSERSTACK_ACCESS_KEY");
        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 + "\"}}");
    }
}
Note: Playwright tests run on BrowserStack using a client-server architecture. So, test assertions run on the client side, and hence, BrowserStack won’t know whether your tests have passed or failed. Learn more how to mark tests as passed or failed on BrowserStack.

Next Steps

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

Is this page helping you?

Yes
No

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!

Talk to an Expert
Talk to an Expert