UNPKG

jest-environment-browserstack

Version:
159 lines (158 loc) 6.79 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const jest_environment_node_1 = __importDefault(require("jest-environment-node")); const browserstack_local_1 = require("browserstack-local"); const crypto_1 = require("crypto"); /** * Browserstack environment */ class BrowserstackEnvironment extends jest_environment_node_1.default { constructor(config) { super(config); // get the configurations from the config in the main package.json this.btCapabilities = config.globals.browserstack; const { capabilities: { 'bstack:options': opts }, driver, seleniumHubUrl = 'https://hub-cloud.browserstack.com/wd/hub', } = this.btCapabilities; // if no Browserstack credentials were found in the package.json // look into the environment for BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY if (!opts.accessKey || !opts.userName) { const { BROWSERSTACK_USERNAME: userName = '', BROWSERSTACK_ACCESS_KEY: accessKey = '' } = process.env; if (!userName || !accessKey) { throw new Error('valid credentials for Browserstack are required'); } opts.accessKey = accessKey; opts.userName = userName; } this.key = opts.accessKey; if (opts.local) { // if local identifier wasn't generate a random 28 chars string if (!opts.localIdentifier) { this.localIdentifier = Buffer.from(crypto_1.randomBytes(28)).toString('hex'); opts.localIdentifier = this.localIdentifier; } else { this.localIdentifier = opts.localIdentifier; } opts.localIdentifier = this.localIdentifier; this.btTunnelOpts = this.btCapabilities.localTesting; } this.selHubUrl = seleniumHubUrl; if (!driver) { throw new Error('a driver is needed for interacting with Browserstack'); } this.pluginDriver = driver; this.drivers = new Array(); } /** * override the original setup environment for the Browserstack one */ setup() { const _super = Object.create(null, { setup: { get: () => super.setup } }); return __awaiter(this, void 0, void 0, function* () { yield _super.setup.call(this); if (this.btTunnelOpts) { yield this.createBTTunnel(); } // the plugin for the driver is loaded dynamically const mod = yield Promise.resolve().then(() => __importStar(require(this.pluginDriver))); // look for the exported member having a createWdDriver method const clazz = Object.values(mod).find((fct) => Reflect.has(fct.prototype, 'createWdDriver')); if (!clazz) { throw new Error('the plugin is not extending @jest-browserstack-environment/plugin'); } // eslint-disable-next-line @typescript-eslint/ban-ts-ignore // @ts-ignore this.plugin = new clazz(); const driver = yield this.plugin.createWdDriver(this.btCapabilities.capabilities, this.selHubUrl); this.global.__driver__ = ((caps) => __awaiter(this, void 0, void 0, function* () { if (caps) { caps['bstack:options'].accessKey = this.key; caps['bstack:options'].userName = this.btCapabilities.capabilities['bstack:options'].userName; } return (yield driver.build(caps || this.btCapabilities.capabilities)); })).bind(this); this.drivers.push(this.global.__driver__); }); } /** * environment teardown - kill all driver instance and close the tunnel */ teardown() { const _super = Object.create(null, { teardown: { get: () => super.teardown } }); return __awaiter(this, void 0, void 0, function* () { yield _super.teardown.call(this); yield Promise.all(this.drivers.map((driver) => __awaiter(this, void 0, void 0, function* () { try { yield driver.quit(); } catch (_) { return Promise.resolve(); } }))); yield this.closeBTTunnel(); }); } // eslint-disable-next-line @typescript-eslint/no-explicit-any runScript(script) { return super.runScript(script); } /** * Create the Browserstack tunnel * @returns {Promise} resolve if the tunnel was correctly created */ createBTTunnel() { if (this.localIdentifier) { this.btTunnelOpts.localIdentifier = this.localIdentifier; } this.btTunnelOpts.key = this.key; this.global.__local__ = new browserstack_local_1.Local(); return new Promise((resolve, reject) => { this.global.__local__.start(this.btTunnelOpts, (err) => { if (err) { return reject(err); } return resolve(); }); }); } /** * Browserstack tunnel teardown * @returns {Promise} resolve if everything went well */ closeBTTunnel() { if (!this.global.__local__) { return Promise.resolve(); } return new Promise((resolve, reject) => { this.global.__local__.stop((err) => { if (err) { return reject(err); } resolve(); }); }); } } exports.default = BrowserstackEnvironment;