Skip to content
Open
Show file tree
Hide file tree
Changes from 7 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
111 changes: 111 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock
package-lock.json

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# Next.js build output
.next

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# IDE files
.idea/

**/target/
**/.DS_Store
76 changes: 74 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,74 @@
# cucumber-js-playwright-browserstack
Creating a sample repo for different Playwright languages and runners
# Running Playwright Tests with Cucumber.js on BrowserStack

Cucumber.js is a JavaScript-based open-source framework for web automation testing. It runs on Node.js and latest web browsers. Cucumber.js allows you to write and execute tests in Gherkin - a non-technical and human-readable language.

By default, Cucumber JS will automatically search for Step Definitions in the same folder as the feature files.

This repository provides an example setup for running Playwright tests with Cucumber.js on the BrowserStack cloud platform.

## Prerequisites

Before getting started, make sure you have the following prerequisites installed:

- [Node.js](https://nodejs.org) - The JavaScript runtime environment
- [npm](https://www.npmjs.com/) - The Node.js package manager
- [Playwright](https://playwright.dev/) - A Node.js library for browser automation

## Setup

1. Clone this repository to your local machine:

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

2. Install the dependencies by navigating to the project directory and running:


```bash
npm install
```

3. Set up your BrowserStack Environment variables

```plaintext
BROWSERSTACK_USERNAME=<your-browserstack-username>
BROWSERSTACK_ACCESS_KEY=<your-browserstack-access-key>
```

Replace `<your-browserstack-username>` and `<your-browserstack-access-key>` with your BrowserStack username and access key, which you can obtain from the BrowserStack dashboard.

## Execution
To run the tests in parallel with different browser configurations, use the following command:

```bash
npm run test:parallel
```
This command will execute the Cucumber.js tests in parallel on Chrome and Firefox browsers based on the configurations specified in the features/steps/viewBrowserstack.js file.

## Other Available Commands
```bash
npm run sample-local-test: Run a sample test using BrowserStack Local testing.
npm run sample-test: Run a sample test without BrowserStack Local testing.
npm run test:chrome: Run the tests only on Chrome.
npm run test:firefox: Run the tests only on Firefox.
```

## Reporting

By default, Cucumber.js generates HTML reports in the `reports` directory after the test execution. You can open the HTML report in your browser to view the test results and detailed information.

## Conclusion

This repository provides a basic setup for running Playwright tests with Cucumber.js on the BrowserStack cloud platform. Feel free to modify and expand it based on your project requirements.

For more information on Playwright and Cucumber.js, refer to their respective documentation:

- [Playwright Documentation](https://playwright.dev/docs/intro)
- [Cucumber.js Documentation](https://github.com/cucumber/cucumber-js)

For additional details on configuring and using BrowserStack with Playwright, consult the BrowserStack documentation:

- [BrowserStack Documentation](https://www.browserstack.com/docs)

Happy testing!
77 changes: 77 additions & 0 deletions browserstack.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# =============================
# Set BrowserStack Credentials
# =============================
# Add your BrowserStack userName and accessKey here or set BROWSERSTACK_USERNAME and
# BROWSERSTACK_ACCESS_KEY as env variables
userName: rakeshdasi_bLnYJW
accessKey: cYRj9XTqzxqdBozK9DFf

# ======================
# BrowserStack Reporting
# ======================
# The following capabilities are used to set up reporting on BrowserStack:
# Set 'projectName' to the name of your project. Example, Marketing Website
projectName: BrowserStack Samples
# Set `buildName` as the name of the job / testsuite being run
buildName: browserstack build
# `buildIdentifier` is a unique id to differentiate every execution that gets appended to
# buildName. Choose your buildIdentifier format from the available expressions:
# ${BUILD_NUMBER} (Default): Generates an incremental counter with every execution
# ${DATE_TIME}: Generates a Timestamp with every execution. Eg. 05-Nov-19:30
# Read more about buildIdentifiers here -> https://www.browserstack.com/docs/automate/selenium/organize-tests
buildIdentifier: '#${BUILD_NUMBER}' # Supports strings along with either/both ${expression}

# =======================================
# Platforms (Browsers / Devices to test)
# =======================================
# Platforms object contains all the browser / device combinations you want to test on.
# Entire list available here -> (https://www.browserstack.com/list-of-browsers-and-platforms/automate)
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 # Try 'samsung' for Samsung browser
osVersion: 12.0

# =======================
# Parallels per Platform
# =======================
# The number of parallel threads to be used for each platform set.
# BrowserStack's SDK runner will select the best strategy based on the configured value
#
# Example 1 - If you have configured 3 platforms and set `parallelsPerPlatform` as 2, a total of 6 (2 * 3) parallel threads will be used on BrowserStack
#
# Example 2 - If you have configured 1 platform and set `parallelsPerPlatform` as 5, a total of 5 (1 * 5) parallel threads will be used on BrowserStack
parallelsPerPlatform: 1

# ==========================================
# BrowserStack Local
# (For localhost, staging/private websites)
# ==========================================
# Set browserStackLocal to true if your website under test is not accessible publicly over the internet
# Learn more about how BrowserStack Local works here -> https://www.browserstack.com/docs/automate/selenium/local-testing-introduction
browserstackLocal: true # <boolean> (Default false)
# browserStackLocalOptions:
# Options to be passed to BrowserStack local in-case of advanced configurations
# localIdentifier: # <string> (Default: null) Needed if you need to run multiple instances of local.
# forceLocal: true # <boolean> (Default: false) Set to true if you need to resolve all your traffic via BrowserStack Local tunnel.
# Entire list of arguments available here -> https://www.browserstack.com/docs/automate/selenium/manage-incoming-connections

# ===================
# Debugging features
# ===================
debug: false # <boolean> # Set to true if you need screenshots for every selenium command ran
networkLogs: false # <boolean> Set to true to enable HAR logs capturing
consoleLogs: errors # <string> Remote browser's console debug levels to be printed (Default: errors)
# Available options are `disable`, `errors`, `warnings`, `info`, `verbose` (Default: errors)
# CUSTOM_TAG_<INT>: # <string> (Default: parent folder name of the test file) Custom tag for your test suite

# Test Observability is an intelligent test reporting & debugging product. It collects data using the SDK. Read more about what data is collected at https://www.browserstack.com/docs/test-observability/references/terms-and-conditions
# Visit observability.browserstack.com to see your test reports and insights. To disable test observability, specify `testObservability: false` in the key below.
testObservability: true
4 changes: 4 additions & 0 deletions features/config/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Object.assign(global, {
BASE_URL: 'https://bstackdemo.com/',
LOCAL_URL: 'https://www.example.com/'
});
4 changes: 4 additions & 0 deletions features/steps/assertions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const chai = require('chai');
global.expect = chai.expect;
global.assert = chai.assert;
global.should = chai.should;
108 changes: 108 additions & 0 deletions features/steps/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
const { setWorldConstructor, World, Before, After, Status, setDefaultTimeout } = require("@cucumber/cucumber");
const { chromium, devices } = require('playwright');
const cp = require('child_process');
const BrowserStackLocal = require('browserstack-local');
const playwrightClientVersion = cp.execSync('npx playwright --version').toString().trim().split(' ')[1];
setDefaultTimeout(120 * 1000);

const enableLocalTesting = false; // Set this flag to true to enable BrowserStack Local testing

const browserConfigs = [

{
browserName: 'chrome',
browserTagName: '@chrome',
browserVersion: 'latest',
os: 'OS X',
osVersion: 'Monterey',
resolution: '1280x1024',
},
{
browserName: 'playwright-firefox',
browserTagName: '@playwright-firefox',
browserVersion: 'latest',
os: 'Windows',
osVersion: '11',
resolution: '1280x1024',
},
{
browserName: 'edge',
browserTagName: '@edge',
browserVersion: 'latest',
os: 'OS X',
osVersion: 'Ventura',
resolution: '1280x1024',
},
];

const browserConnections = [];

Before(async (scenario) => {
const tagName = scenario.pickle.tags[0].name;
const filteredBrowserConfigs = browserConfigs.filter(config => config.browserTagName === tagName);

for (const browserConfig of filteredBrowserConfigs) {
const caps = {
...browserConfig,
'browserstack.username': process.env.BROWSERSTACK_USERNAME || 'YOUR_USERNAME',
'browserstack.accessKey': process.env.BROWSERSTACK_ACCESS_KEY || 'YOUR_ACCESS_KEY',
'project': 'PLAYWRIGHT-CUCUMBER-JS',
'build': 'playwright-cucumber-build-1',
'name': scenario.pickle.name,
'buildTag': 'Regression',
'browserstack.playwrightVersion': '1.latest',
'client.playwrightVersion': '1.latest'
};

console.log('enableLocalTesting', enableLocalTesting);
if (enableLocalTesting && browserConnections.length === 0) {
const bsLocal = new BrowserStackLocal.Local();
const bsLocalArgs = {
key: process.env.BROWSERSTACK_ACCESS_KEY, // Replace with your BrowserStack access key
localIdentifier: 'local_connection_name' // Replace with your desired local connection name
};

await new Promise((resolve, reject) => {
bsLocal.start(bsLocalArgs, (error) => {
if (error) {
console.error('Failed to start BrowserStack Local:', error);
reject(error);
} else {
console.log('BrowserStack Local started successfully');
resolve();
}
});
});
}

// Create page and browser globals to be used in the scenarios
const browser = await chromium.connect({
wsEndpoint: `wss://cdp.browserstack.com/playwright?caps=${encodeURIComponent(JSON.stringify(caps))}`,
});

const context = await browser.newContext();
global.page = await context.newPage();

browserConnections.push(browser);
}
});

After(async () => {
await Promise.all(browserConnections.map(browser => browser.close()));
});

After(async (scenario) => {
if (scenario.result.status === Status.PASSED) {
await page.evaluate(_ => { }, `browserstack_executor: ${JSON.stringify({ action: 'setSessionStatus', arguments: { status: 'passed', reason: 'Test Passed' } })}`);
} else if (scenario.result.status === Status.FAILED) {
await page.evaluate(_ => { }, `browserstack_executor: ${JSON.stringify({ action: 'setSessionStatus', arguments: { status: 'failed', reason: 'Test Failed' } })}`);
}
});

setWorldConstructor(function () {
this.testCaseRetry = 2; // Set the number of retries for each test case
});

module.exports = {
parallel: 2, // Set the number of parallel test workers to the number of browsers
};
Loading