diff --git a/README.md b/README.md
index e53af9c..6225d81 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,6 @@
# jest-environment-browserstack
-[![Actions Status](https://github.com/taktakpeops/jest-environment-browserstack/workflows/Node%20CI/badge.svg)](https://github.com/taktakpeops/jest-environment-browserstack/actions) [![npm version](http://img.shields.io/npm/v/jest-environment-browserstack.svg?style=flat)](https://npmjs.org/package/jest-environment-browserstack "View this project on npm")
-
+[![Actions Status](https://github.com/taktakpeops/jest-environment-browserstack/workflows/Node%20CI/badge.svg)](https://github.com/taktakpeops/jest-environment-browserstack/actions) [![npm version](http://img.shields.io/npm/v/jest-environment-browserstack.svg?style=flat)](https://npmjs.org/package/jest-environment-browserstack 'View this project on npm')
Use Jest as test-runner for running your visual-tests and more using Browserstack.
@@ -90,13 +89,30 @@ my-visual-test.spec.js:
/**
* @jest-environment browserstack
*/
-import { until, By } from 'selenium-webdriver';
+import { By } from 'selenium-webdriver';
describe('my visual test', () => {
- it('test something', () => {
- global.__driver__.get('https://mysuperurl.ltd');
- // do something
- // do test
+ let driver;
+
+ beforeAll(async () => {
+ // you can override the default configuration
+ driver = await global.__driver__({
+ 'bstack:options': {
+ sessionName: 'my test',
+ },
+ });
+ driver.get('https://mysuperurl.ltd');
+ });
+
+ afterAll(async () => {
+ // can be omitted
+ await driver.quit();
+ });
+
+ it('test something', async () => {
+ const myElement = await driver.findElement(By.css('.super.class'));
+ const text = await myElement.getText();
+ expect(text).toBe('super text');
});
});
```
@@ -121,7 +137,7 @@ The `test` script will run a basic e2e tests, a visual tests making a snapshot o
# Known limitations
-For now, only one browser can be defined.
+For now, cannot override Browserstack parameters at runtime.
# Bug and more
diff --git a/examples/with-bt-local/package.json b/examples/with-bt-local/package.json
index ed40369..0b8cc6a 100644
--- a/examples/with-bt-local/package.json
+++ b/examples/with-bt-local/package.json
@@ -67,6 +67,9 @@
"start": "PORT=8080 node scripts/start.js",
"build": "node scripts/build.js",
"test:jest": "jest --ci",
+ "test:visual": "jest --testNamePattern=VisualTest --update-snapshot",
+ "test:e2e": "jest --testNamePattern=UiTest",
+ "test:unit": "jest --testNamePattern=UnitTest",
"test": "npm-run-all -p -r start test:jest"
},
"eslintConfig": {
diff --git a/examples/with-bt-local/src/App.e2e.test.js b/examples/with-bt-local/src/App.e2e.test.js
index bec88ab..c19c461 100644
--- a/examples/with-bt-local/src/App.e2e.test.js
+++ b/examples/with-bt-local/src/App.e2e.test.js
@@ -4,12 +4,24 @@
const { By } = require('selenium-webdriver');
-describe('ui testing', () => {
- const driver = global.__driver__;
+describe('ui testing UiTest', () => {
+ let driver;
+
+ beforeAll(async () => {
+ driver = await global.__driver__({
+ 'bstack:options': {
+ sessionName: 'ui testing',
+ },
+ });
- it('load the app', async () => {
await driver.get('http://localhost:8080');
+ }, 10000);
+ afterAll(async () => {
+ await driver.quit();
+ });
+
+ it('load the app', async () => {
const title = await driver.getTitle();
expect(title).toBe('React App');
diff --git a/examples/with-bt-local/src/App.test.js b/examples/with-bt-local/src/App.test.js
index a754b20..1b9fb83 100644
--- a/examples/with-bt-local/src/App.test.js
+++ b/examples/with-bt-local/src/App.test.js
@@ -2,7 +2,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
-it('renders without crashing', () => {
+it('renders without crashing UnitTest', () => {
const div = document.createElement('div');
ReactDOM.render(, div);
ReactDOM.unmountComponentAtNode(div);
diff --git a/examples/with-bt-local/src/__visual_testing__/App.test.js b/examples/with-bt-local/src/__visual_testing__/App.test.js
index 51e05de..9dd39ad 100644
--- a/examples/with-bt-local/src/__visual_testing__/App.test.js
+++ b/examples/with-bt-local/src/__visual_testing__/App.test.js
@@ -5,12 +5,24 @@ const { toMatchImageSnapshot } = require('jest-image-snapshot');
expect.extend({ toMatchImageSnapshot });
-describe('ui testing', () => {
- const driver = global.__driver__;
+describe('visual testing VisualTest', () => {
+ let driver;
+
+ beforeAll(async () => {
+ driver = await global.__driver__({
+ 'bstack:options': {
+ sessionName: 'visual testing',
+ },
+ });
- it('load the app', async () => {
await driver.get('http://localhost:8080');
+ }, 10000);
+
+ afterAll(async () => {
+ await driver.quit();
+ });
+ it('check the app', async () => {
const title = await driver.getTitle();
expect(title).toBe('React App');
diff --git a/examples/with-bt-local/src/__visual_testing__/__image_snapshots__/app-test-js-visual-testing-visual-test-take-and-screenshot-and-compare-1-snap.png b/examples/with-bt-local/src/__visual_testing__/__image_snapshots__/app-test-js-visual-testing-visual-test-take-and-screenshot-and-compare-1-snap.png
new file mode 100644
index 0000000..3a18ae9
Binary files /dev/null and b/examples/with-bt-local/src/__visual_testing__/__image_snapshots__/app-test-js-visual-testing-visual-test-take-and-screenshot-and-compare-1-snap.png differ
diff --git a/examples/with-bt-local/yarn.lock b/examples/with-bt-local/yarn.lock
index 8cbdc87..3f55424 100644
--- a/examples/with-bt-local/yarn.lock
+++ b/examples/with-bt-local/yarn.lock
@@ -1173,6 +1173,18 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636"
integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==
+"@types/lodash.merge@~4.6.6":
+ version "4.6.6"
+ resolved "https://registry.yarnpkg.com/@types/lodash.merge/-/lodash.merge-4.6.6.tgz#b84b403c1d31bc42d51772d1cd5557fa008cd3d6"
+ integrity sha512-IB90krzMf7YpfgP3u/EvZEdXVvm4e3gJbUvh5ieuI+o+XqiNEt6fCzqNRaiLlPVScLI59RxIGZMQ3+Ko/DJ8vQ==
+ dependencies:
+ "@types/lodash" "*"
+
+"@types/lodash@*":
+ version "4.14.141"
+ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.141.tgz#d81f4d0c562abe28713406b571ffb27692a82ae6"
+ integrity sha512-v5NYIi9qEbFEUpCyikmnOYe4YlP8BMUdTcNCAquAKzu+FA7rZ1onj9x80mbnDdOW/K5bFf3Tv5kJplP33+gAbQ==
+
"@types/q@^1.5.1":
version "1.5.2"
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
@@ -5256,9 +5268,11 @@ jest-each@^24.9.0:
version "1.0.0"
dependencies:
"@jest/types" "~24.9.0"
+ "@types/lodash.merge" "~4.6.6"
"@types/selenium-webdriver" "~4.0.3"
browserstack-local "~1.4.2"
jest-environment-node "~24.9.0"
+ lodash.merge "~4.6.2"
selenium-webdriver "~4.0.0-alpha.5"
jest-environment-jsdom-fourteen@0.1.0:
@@ -5923,6 +5937,11 @@ lodash.memoize@^4.1.2:
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
+lodash.merge@~4.6.2:
+ version "4.6.2"
+ resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
+ integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
+
lodash.sortby@^4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
diff --git a/package-lock.json b/package-lock.json
index 6aec602..aaf7bb0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -437,6 +437,19 @@
"integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==",
"dev": true
},
+ "@types/lodash": {
+ "version": "4.14.141",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.141.tgz",
+ "integrity": "sha512-v5NYIi9qEbFEUpCyikmnOYe4YlP8BMUdTcNCAquAKzu+FA7rZ1onj9x80mbnDdOW/K5bFf3Tv5kJplP33+gAbQ=="
+ },
+ "@types/lodash.merge": {
+ "version": "4.6.6",
+ "resolved": "https://registry.npmjs.org/@types/lodash.merge/-/lodash.merge-4.6.6.tgz",
+ "integrity": "sha512-IB90krzMf7YpfgP3u/EvZEdXVvm4e3gJbUvh5ieuI+o+XqiNEt6fCzqNRaiLlPVScLI59RxIGZMQ3+Ko/DJ8vQ==",
+ "requires": {
+ "@types/lodash": "*"
+ }
+ },
"@types/node": {
"version": "12.7.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.7.tgz",
@@ -3552,6 +3565,11 @@
"integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
"dev": true
},
+ "lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
+ },
"lodash.sortby": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
diff --git a/package.json b/package.json
index 1107170..3f64714 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "jest-environment-browserstack",
- "version": "1.0.0",
+ "version": "1.1.0",
"description": "an environment for using Browserstack with Jest",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@@ -31,9 +31,11 @@
"license": "MIT",
"dependencies": {
"@jest/types": "~24.9.0",
+ "@types/lodash.merge": "~4.6.6",
"@types/selenium-webdriver": "~4.0.3",
"browserstack-local": "~1.4.2",
"jest-environment-node": "~24.9.0",
+ "lodash.merge": "~4.6.2",
"selenium-webdriver": "~4.0.0-alpha.5"
},
"devDependencies": {
diff --git a/src/__tests__/github.spec.ts b/src/__tests__/github.spec.ts
new file mode 100644
index 0000000..2ef1a12
--- /dev/null
+++ b/src/__tests__/github.spec.ts
@@ -0,0 +1,32 @@
+import { WebDriver, By } from 'selenium-webdriver';
+
+describe('Github', () => {
+ let driver: WebDriver;
+
+ beforeAll(async () => {
+ // eslint-disable-next-line
+ // @ts-ignore
+ driver = await global.__driver__({
+ 'bstack:options': {
+ sessionName: 'github',
+ },
+ });
+ await driver.get('https://github.com/taktakpeops/jest-environment-browserstack');
+ }, 10000);
+
+ afterAll(async () => {
+ await driver.quit();
+ });
+
+ it('has an author', async () => {
+ const authorSpan = await driver.findElement(By.css('.author'));
+ const author = await authorSpan.getText();
+ expect(author).toBe('taktakpeops');
+ });
+
+ it('has a repository name', async () => {
+ const repoSpan = await driver.findElement(By.css('h1.public strong'));
+ const repo = await repoSpan.getText();
+ expect(repo).toBe('jest-environment-browserstack');
+ });
+});
diff --git a/src/__tests__/index.spec.ts b/src/__tests__/index.spec.ts
deleted file mode 100644
index 2b820ac..0000000
--- a/src/__tests__/index.spec.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { WebDriver } from 'selenium-webdriver';
-
-describe('BrowserstackEnvironment', () => {
- // eslint-disable-next-line
- // @ts-ignore
- const driver = global.__driver__ as WebDriver;
-
- it('connects to NPM', async () => {
- await driver.get('https://www.npmjs.com/package/jest-environment-browserstack');
-
- const title = await driver.getTitle();
- expect(title).toBe('jest-environment-browserstack - npm');
- });
-});
diff --git a/src/__tests__/npm.spec.ts b/src/__tests__/npm.spec.ts
new file mode 100644
index 0000000..8f8d997
--- /dev/null
+++ b/src/__tests__/npm.spec.ts
@@ -0,0 +1,31 @@
+import { WebDriver, By } from 'selenium-webdriver';
+
+describe('NPM', () => {
+ let driver: WebDriver;
+
+ beforeAll(async () => {
+ // eslint-disable-next-line
+ // @ts-ignore
+ driver = await global.__driver__({
+ 'bstack:options': {
+ sessionName: 'npm',
+ },
+ });
+ await driver.get('https://www.npmjs.com/package/jest-environment-browserstack');
+ }, 10000);
+
+ afterAll(async () => {
+ await driver.quit();
+ });
+
+ it('get title from NPM', async () => {
+ const title = await driver.getTitle();
+ expect(title).toBe('jest-environment-browserstack - npm');
+ });
+
+ it('get name of the module', async () => {
+ const titleBlock = await driver.findElement(By.css('.w-100.ph0-l.ph3.ph4-m span[title="jest-environment-browserstack"]'));
+ const title = await titleBlock.getText();
+ expect(title).toBe('jest-environment-browserstack');
+ });
+});
diff --git a/src/index.ts b/src/index.ts
index 95d38cf..45cda15 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -4,6 +4,7 @@ import { Options, Local } from 'browserstack-local';
import { Builder, WebDriver } from 'selenium-webdriver';
import { randomBytes } from 'crypto';
import { Script } from 'vm';
+import merge from 'lodash.merge';
import { BrowserstackCapabilities } from './types';
@@ -18,6 +19,8 @@ export default class BrowserstackEnvironment extends NodeEnvironment {
private btTunnelOpts: Options;
+ private readonly drivers: WebDriver[];
+
constructor(config: Config.ProjectConfig) {
super(config);
@@ -54,6 +57,7 @@ export default class BrowserstackEnvironment extends NodeEnvironment {
}
this.selHubUrl = seleniumHubUrl;
+ this.drivers = new Array();
}
async setup(): Promise {
@@ -63,13 +67,21 @@ export default class BrowserstackEnvironment extends NodeEnvironment {
await this.createBTTunnel();
}
- this.global.__driver__ = await this.createWDDriver();
+ this.global.__driver__ = this.createWDDriver.bind(this);
}
async teardown(): Promise {
await super.teardown();
- await this.global.__driver__.quit();
+ await Promise.all(
+ this.drivers.map(async driver => {
+ try {
+ await driver.quit();
+ } catch (_) {
+ return Promise.resolve();
+ }
+ }),
+ );
await this.closeBTTunnel();
}
@@ -77,10 +89,13 @@ export default class BrowserstackEnvironment extends NodeEnvironment {
return super.runScript(script);
}
- private async createWDDriver(): Promise {
- const driverFactory = new Builder().usingServer(this.selHubUrl).withCapabilities(this.btCapabilities);
+ private async createWDDriver(capabilities?: BrowserstackCapabilities): Promise {
+ const driverFactory = new Builder().usingServer(this.selHubUrl).withCapabilities(merge(this.btCapabilities, capabilities));
+ const driver = await driverFactory.build();
+
+ this.drivers.push(driver);
- return await driverFactory.build();
+ return driver;
}
private createBTTunnel(): Promise {