Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions .github/workflows/sdk-sample-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Runs the BrowserStack SDK sample against a given commit and reports a status check.
# Trigger: Actions tab -> "Cucumber-JS + Playwright SDK sample test" -> Run workflow -> paste the PR's full commit SHA.
# Requires repo secrets: BROWSERSTACK_USERNAME, BROWSERSTACK_ACCESS_KEY.
name: Cucumber-JS + Playwright SDK sample test

on:
workflow_dispatch:
inputs:
commit_sha:
description: 'The full commit id to build'
required: true

permissions:
contents: read # checkout
checks: write # github-script creates the status check

jobs:
sdk-sample:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
max-parallel: 3
matrix:
os: [ubuntu-latest]
node: ['18', '20', '22']
name: cucumber-js-playwright Node ${{ matrix.node }} sample
env:
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.commit_sha }}
- name: Mark status check in_progress
uses: actions/github-script@v7
env:
job_name: cucumber-js-playwright Node ${{ matrix.node }} sample
commit_sha: ${{ github.event.inputs.commit_sha }}
with:
github-token: ${{ github.token }}
script: |
await github.rest.checks.create({
owner: context.repo.owner, repo: context.repo.repo,
name: process.env.job_name, head_sha: process.env.commit_sha, status: 'in_progress'
}).catch(e => console.log('check create failed:', e.status));
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- name: Install
run: |
npm install
- name: Run sample test
run: |
npm run sample-test
- name: Run sample-local test
run: |
npm run sample-local-test
- name: Mark status check completed
if: always()
uses: actions/github-script@v7
env:
conclusion: ${{ job.status }}
job_name: cucumber-js-playwright Node ${{ matrix.node }} sample
commit_sha: ${{ github.event.inputs.commit_sha }}
with:
github-token: ${{ github.token }}
script: |
await github.rest.checks.create({
owner: context.repo.owner, repo: context.repo.repo,
name: process.env.job_name, head_sha: process.env.commit_sha,
status: 'completed', conclusion: process.env.conclusion
}).catch(e => console.log('check create failed:', e.status));
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
node_modules
package-lock.json
.env
local.log
browserstack.err
log/
screenshots
**/.DS_Store
.vscode/
.venv
venv
__pycache__
bin/
obj/
target/
*.log
.pytest_cache
57 changes: 55 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,55 @@
# cucumber-js-playwright-browserstack
Creating a sample repo for different Playwright languages and runners
# Cucumber-JS (Playwright) with BrowserStack

Run your Cucumber-JS + Playwright tests on the BrowserStack cloud using the [BrowserStack Node SDK](https://www.browserstack.com/docs/automate/selenium/sdk-overview). This sample tests on BrowserStack Automate.

## Prerequisites

- A [BrowserStack](https://www.browserstack.com/) account (username + access key).
- [Node.js](https://nodejs.org/) (>= 14) and npm installed.
- Your BrowserStack credentials, available from your [account settings](https://www.browserstack.com/accounts/settings).

## Setup

1. Clone this repository:

```bash
git clone https://github.com/browserstack/cucumber-js-playwright-browserstack.git
cd cucumber-js-playwright-browserstack
```

2. Install the dependencies:

```bash
npm install
```

3. Set your BrowserStack credentials as environment variables:

```bash
export BROWSERSTACK_USERNAME="YOUR_USERNAME"
export BROWSERSTACK_ACCESS_KEY="YOUR_ACCESS_KEY"
```

Alternatively, edit `browserstack.yml` and replace `YOUR_USERNAME` and `YOUR_ACCESS_KEY` with your credentials.

## Run Sample Test

Runs the sample test against the public BrowserStack demo website:

```bash
npx browserstack-node-sdk cucumber-js features/single.feature
```

## Run Local Test

Runs the local test through the BrowserStack Local tunnel (`browserstackLocal: true` in `browserstack.yml`):

```bash
npx browserstack-node-sdk cucumber-js features/local.feature
```

## Notes

- View your test runs and debug results on the [BrowserStack Automate dashboard](https://automate.browserstack.com/).
- Platforms, parallelism, and product capabilities (such as `testObservability`) are configured in `browserstack.yml`.
- The BrowserStack Node SDK patches the Playwright library at runtime and routes browser sessions to BrowserStack — no changes to your test code are required.
26 changes: 26 additions & 0 deletions browserstack.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
userName: YOUR_USERNAME
accessKey: YOUR_ACCESS_KEY
projectName: BrowserStack Samples
buildName: browserstack build
buildIdentifier: '#${BUILD_NUMBER}'
framework: cucumber-js
platforms:
- os: OS X
osVersion: Big Sur
browserName: Chrome
browserVersion: latest
- os: Windows
osVersion: 10
browserName: Edge
browserVersion: latest
- deviceName: Samsung Galaxy S22 Ultra
browserName: chrome
osVersion: 12.0
parallelsPerPlatform: 1
browserstackAutomation: true
browserstackLocal: true
source: cucumber-js-playwright-browserstack:sample-sdk:v1.0
testObservability: true
debug: false
networkLogs: false
consoleLogs: errors
5 changes: 5 additions & 0 deletions features/local.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Feature: BrowserStack Local Testing

Scenario: BStack Local Test - Can check tunnel working
When I open dashboard
Then I should see "BrowserStack Local"
6 changes: 6 additions & 0 deletions features/single.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Feature: Browserstack test

Scenario: BStack Sample Test - Can add a product to the cart
Given I visit bstackdemo website
When I add a product to the cart
Then I should see the same product in the cart section
33 changes: 33 additions & 0 deletions features/step_definitions/bstack-steps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use strict';

const assert = require('assert');
const { Given, When, Then } = require('@cucumber/cucumber');

let productText = '';

Given(/^I visit bstackdemo website/, async function () {
await this.page.goto('https://bstackdemo.com/');
});

When(/^I add a product to the cart/, async function () {
await this.page.waitForSelector('//*[@id="1"]/p');
productText = await this.page.locator('//*[@id="1"]/p').innerText();
await this.page.locator('//*[@id="1"]/div[4]').click();
});

Then(/^I should see the same product in the cart section/, async function () {
await this.page.waitForSelector('.float-cart__content');

await this.page.waitForSelector(
'//*[@id="__next"]/div/div/div[2]/div[2]/div[2]/div/div[3]/p[1]'
);
const productCartText = await this.page
.locator('//*[@id="__next"]/div/div/div[2]/div[2]/div[2]/div/div[3]/p[1]')
.innerText();

assert.strictEqual(
productCartText,
productText,
'Expected product to be ' + productText
);
});
17 changes: 17 additions & 0 deletions features/step_definitions/local-steps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict';

const assert = require('assert');
const { When, Then } = require('@cucumber/cucumber');

When(/^I open dashboard$/, async function () {
await this.page.goto('http://bs-local.com:45454');
});

Then(/^I should see "([^"]*)"$/, async function (sourceMatch) {
const title = await this.page.title();
assert.strictEqual(
title,
sourceMatch,
'Expected page title to be ' + sourceMatch
);
});
5 changes: 5 additions & 0 deletions features/support/env.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict';

const { setDefaultTimeout } = require('@cucumber/cucumber');

setDefaultTimeout(60 * 1000);
26 changes: 26 additions & 0 deletions features/support/hooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict';

const { chromium } = require('@playwright/test');
const { Before, After } = require('@cucumber/cucumber');

// When run through `browserstack-node-sdk cucumber-js`, the BrowserStack Node
// SDK patches the Playwright library at import time and routes the browser
// session to BrowserStack using the capabilities declared in browserstack.yml.
// No CDP wsEndpoint or credentials are needed in the test code.
Before(async function () {
this.browser = await chromium.launch();
this.context = await this.browser.newContext();
this.page = await this.context.newPage();
});

After(async function () {
if (this.page) {
await this.page.close();
}
if (this.context) {
await this.context.close();
}
if (this.browser) {
await this.browser.close();
}
});
23 changes: 23 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "cucumber-js-playwright-browserstack",
"version": "0.1.0",
"description": "Playwright examples for Cucumber-JS and BrowserStack Automate using the BrowserStack Node SDK",
"repository": {
"type": "git",
"url": "git+https://github.com/browserstack/cucumber-js-playwright-browserstack.git"
},
"scripts": {
"test": "browserstack-node-sdk cucumber-js",
"sample-test": "browserstack-node-sdk cucumber-js features/single.feature",
"sample-local-test": "browserstack-node-sdk cucumber-js features/local.feature"
},
"devDependencies": {
"@cucumber/cucumber": "^10.0.1",
"@playwright/test": "1.55.0",
"browserstack-node-sdk": "1.49.3"
},
"dependencies": {
"browserstack-local": "^1.5.5",
"selenium-webdriver": "4.28.1"
}
}