Skip to content

Commit 2cee181

Browse files
authored
Merge pull request #6 from browserstack/add-jest-sample
Add Jest sample for Selenium load testing
2 parents a3658e3 + 1cdab4a commit 2cee181

7 files changed

Lines changed: 280 additions & 0 deletions

File tree

‎.gitignore‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@
22
**/log
33
**/browserstack-cli
44
**/.DS_Store
5+
**/node_modules/
6+
**/package-lock.json
7+
**/yarn.lock
8+
**/pnpm-lock.yaml

‎jest/README.md‎

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# browserstack-selenium-load-testing-sample
2+
3+
![BrowserStack Logo](https://d98b8t1nnulk5.cloudfront.net/production/images/layout/logo-header.png?1469004780)
4+
5+
## Getting Started
6+
7+
### Run Sample Build
8+
9+
1. **Clone the repository**
10+
11+
```sh
12+
git clone https://github.com/browserstack/browserstack-selenium-load-testing-sample.git
13+
cd browserstack-selenium-load-testing-sample
14+
cd jest
15+
```
16+
17+
2. **Install Node dependencies**
18+
19+
```sh
20+
npm install
21+
```
22+
23+
3. **Install BrowserStack CLI**
24+
25+
Download the appropriate BrowserStack CLI binary based on your operating system:
26+
27+
- **macOS x86**
28+
[browserstack-cli-macOS-x86](https://load-api.browserstack.com/api/v1/binary?os=macos&arch=x64)
29+
30+
- **macOS ARM**
31+
[browserstack-cli-macOS-arm](https://load-api.browserstack.com/api/v1/binary?os=macos&arch=arm64)
32+
33+
- **Windows x86**
34+
[browserstack-cli-windows](https://load-api.browserstack.com/api/v1/binary?os=win&arch=x64)
35+
36+
- **Linux x86**
37+
[browserstack-cli-linux-x86](https://load-api.browserstack.com/api/v1/binary?os=linux&arch=arm64)
38+
39+
- **Linux ARM**
40+
[browserstack-cli-linux-arm](https://load-api.browserstack.com/api/v1/binary?os=linux&arch=x64)
41+
42+
> Place the downloaded `browserstack-cli` binary in the root of your project.
43+
44+
4. **Run tests using BrowserStack CLI**
45+
46+
```sh
47+
./browserstack-cli load run
48+
```
49+
50+
5. **View Test Results**
51+
52+
Visit the [BrowserStack Load-Testing Dashboard](https://load.browserstack.com/projects) to monitor and analyze your test runs.
53+
54+
---

‎jest/browserstack-load.yml‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# =============================
2+
# Set BrowserStack Credentials
3+
# =============================
4+
# Add your BrowserStack userName and accessKey here or set BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY as env variables.
5+
userName: BROWSERSTACK_USERNAME
6+
accessKey: BROWSERSTACK_ACCESS_KEY
7+
8+
# ======================
9+
# BrowserStack Reporting
10+
# ======================
11+
# The following parameters are used to set up reporting on BrowserStack Load Testing:
12+
# Set 'projectName' to the name of your project. Example: 'Product ABC'. Tests under the same projectName will be grouped together.
13+
projectName: Default Project
14+
15+
# Set 'testName' to the name of your test. Example: 'First Load Test'. Test runs with the same testName will be grouped together.
16+
testName: Default Test
17+
18+
# ======================
19+
# Set Load Configuration
20+
# ======================
21+
# The following parameters are used to set load configuration for your test:
22+
# Set 'testType' to the type of load test that you want to execute. Example:'Playwright', 'Selenium'. This is a required parameter.
23+
testType: Selenium
24+
25+
# Set 'vus' to the maximum number of virtual users to simulate during the test.
26+
vus: 1
27+
28+
# Set 'duration' to the total duration of the entire test, in minutes and seconds. The test will run infinite iterations until the duration is met. Example: '2m', '3m 40s'. This is not a required parameter.
29+
duration: 1m
30+
31+
# Set multiple regions from which you would want to generate the load (percent should total 100 across all loadzones).
32+
regions:
33+
- loadzone: us-east-1
34+
percent: 100
35+
36+
# Set language to the programming language used in your project. Example: 'java', 'nodejs'.
37+
language: nodejs
38+
39+
# Set framework to the test framework used in your Selenium project.
40+
framework: jest
41+
42+
# Add list of file paths under 'dependencies' to help set up the test environment by installing required packages. Example: path to 'pom.xml' for Java projects using Maven, path to 'package.json' for Node.js projects.
43+
# Add list of file paths under 'testConfigs' to define which configuration files should be used to run tests. Example: path to 'playwright.config.ts' for Playwright (Node.js), path to 'testng.xml' for Selenium (TestNG).
44+
files:
45+
dependencies:
46+
- ./package.json
47+
testConfigs:
48+
- ./jest.config.js

‎jest/jest.config.js‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Jest runs with --runInBand on BrowserStack so the single Selenium session
2+
// per pod is never contended. testEnvironment must be "node" — Jest drives a
3+
// remote WebDriver, not the in-process DOM.
4+
module.exports = {
5+
testEnvironment: "node",
6+
testMatch: ["**/tests/**/*.test.js", "**/?(*.)+(spec|test).js"],
7+
testTimeout: 120000,
8+
};

‎jest/package.json‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "browserstack-jest-load-testing-sample",
3+
"version": "1.0.0",
4+
"private": true,
5+
"description": "Sample Jest + selenium-webdriver project for BrowserStack Load Testing",
6+
"scripts": {
7+
"test": "jest --runInBand --passWithNoTests=false"
8+
},
9+
"dependencies": {
10+
"jest": "^29.7.0",
11+
"selenium-webdriver": "^4.21.0"
12+
}
13+
}

‎jest/tests/add-to-cart.test.js‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
const { Builder, By, until } = require("selenium-webdriver");
2+
3+
// On BrowserStack Load Testing, the Selenium pod exposes a hub at
4+
// http://localhost:4444/wd/hub. A plain `forBrowser("chrome").build()`
5+
// would try to spawn a local browser the pod does not have.
6+
const HUB_URL = "http://localhost:4444/wd/hub";
7+
8+
describe("BStackDemo test add to cart", () => {
9+
let driver;
10+
11+
beforeAll(async () => {
12+
driver = await new Builder()
13+
.usingServer(HUB_URL)
14+
.forBrowser("chrome")
15+
.build();
16+
});
17+
18+
afterAll(async () => {
19+
if (driver) await driver.quit();
20+
});
21+
22+
test("should add product to cart successfully", async () => {
23+
// visit the site
24+
await driver.get("https://bstackdemo.com/");
25+
26+
// get name of product we want to add to cart
27+
const productNameElem = await driver.wait(
28+
until.elementLocated(By.xpath("//*[@id='3']/p")),
29+
10000,
30+
);
31+
await driver.wait(until.elementIsVisible(productNameElem), 10000);
32+
const productToAdd = (await productNameElem.getText()).trim();
33+
34+
// click on add to cart
35+
const addToCartBtn = await driver.findElement(
36+
By.css("#\\33 > .shelf-item__buy-btn"),
37+
);
38+
await addToCartBtn.click();
39+
40+
// get name of item in cart
41+
const productInCartElem = await driver.wait(
42+
until.elementLocated(
43+
By.css(
44+
".float-cart.float-cart--open .float-cart__shelf-container .shelf-item__details p.title",
45+
),
46+
),
47+
10000,
48+
);
49+
await driver.wait(until.elementIsVisible(productInCartElem), 10000);
50+
const productInCart = (await productInCartElem.getText()).trim();
51+
52+
// check if product in cart is same as one added
53+
expect(productInCart).toBe(productToAdd);
54+
});
55+
});

‎jest/tests/checkout.test.js‎

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
const { Builder, By, until } = require("selenium-webdriver");
2+
3+
// On BrowserStack Load Testing, the Selenium pod exposes a hub at
4+
// http://localhost:4444/wd/hub. A plain `forBrowser("chrome").build()`
5+
// would try to spawn a local browser the pod does not have.
6+
const HUB_URL = "http://localhost:4444/wd/hub";
7+
const WAIT_MS = 10000;
8+
9+
const waitForClickable = async (driver, locator) => {
10+
const el = await driver.wait(until.elementLocated(locator), WAIT_MS);
11+
await driver.wait(until.elementIsVisible(el), WAIT_MS);
12+
await driver.wait(until.elementIsEnabled(el), WAIT_MS);
13+
return el;
14+
};
15+
16+
const click = async (driver, locator) => {
17+
const el = await waitForClickable(driver, locator);
18+
await el.click();
19+
};
20+
21+
const type = async (driver, locator, text) => {
22+
const el = await waitForClickable(driver, locator);
23+
await el.sendKeys(text);
24+
};
25+
26+
describe("BStackDemo test checkout flow", () => {
27+
let driver;
28+
29+
beforeAll(async () => {
30+
driver = await new Builder()
31+
.usingServer(HUB_URL)
32+
.forBrowser("chrome")
33+
.build();
34+
// Implicit wait so findElement polls instead of failing the moment a
35+
// React modal/transition hasn't painted yet.
36+
await driver.manage().setTimeouts({ implicit: WAIT_MS });
37+
});
38+
39+
afterAll(async () => {
40+
if (driver) await driver.quit();
41+
});
42+
43+
test("should complete checkout flow successfully", async () => {
44+
// visit the site
45+
await driver.get("https://bstackdemo.com/");
46+
47+
// sign in
48+
await click(driver, By.id("signin"));
49+
await click(driver, By.css("#username svg"));
50+
await click(driver, By.id("react-select-2-option-0-0"));
51+
await click(driver, By.css("#password svg"));
52+
await click(driver, By.id("react-select-3-option-0-0"));
53+
await click(driver, By.id("login-btn"));
54+
55+
// click first item
56+
await click(driver, By.css("#\\31 > .shelf-item__buy-btn"));
57+
58+
// cart overlay opens
59+
await driver.wait(
60+
until.elementLocated(By.css(".float-cart.float-cart--open")),
61+
WAIT_MS,
62+
);
63+
64+
// close cart (best-effort)
65+
try {
66+
await click(driver, By.css(".float-cart__close-btn"));
67+
} catch (e) {
68+
console.log("[WARN] Could not close cart overlay:", e.message);
69+
}
70+
71+
// click second item
72+
await click(driver, By.css("#\\32 > .shelf-item__buy-btn"));
73+
74+
// proceed to checkout
75+
await click(driver, By.css(".buy-btn"));
76+
77+
// add address details
78+
await type(driver, By.id("firstNameInput"), "first");
79+
await type(driver, By.id("lastNameInput"), "last");
80+
await type(driver, By.id("addressLine1Input"), "address");
81+
await type(driver, By.id("provinceInput"), "province");
82+
await type(driver, By.id("postCodeInput"), "pincode");
83+
84+
// checkout
85+
await click(driver, By.id("checkout-shipping-continue"));
86+
87+
// continue shopping confirmation
88+
await click(
89+
driver,
90+
By.xpath("//*[@id='checkout-app']/div/div/div/div/a/button"),
91+
);
92+
93+
// navigate to orders
94+
await click(driver, By.xpath("//*[text()='Orders']"));
95+
96+
expect(true).toBe(true);
97+
});
98+
});

0 commit comments

Comments
 (0)