UNPKG

testplane

Version:

Tests framework based on mocha and wdio

264 lines 11.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.NewBrowser = void 0; const url_1 = require("url"); const urijs_1 = __importDefault(require("urijs")); const lodash_1 = require("lodash"); const webdriverio_1 = require("@testplane/webdriverio"); const browser_1 = require("./browser"); const signal_handler_1 = __importDefault(require("../signal-handler")); const logger_1 = require("../utils/logger"); const browser_2 = require("../utils/browser"); const runtime_config_1 = require("../config/runtime-config"); const config_1 = require("../constants/config"); const defaults_1 = require("../config/defaults"); const types_1 = require("./types"); const DEFAULT_PORT = 4444; const headlessBrowserOptions = { [types_1.BrowserName.CHROME]: { capabilityName: "goog:chromeOptions", getArgs: (headlessMode) => { const headlessValue = (0, lodash_1.isBoolean)(headlessMode) ? "headless" : `headless=${headlessMode}`; return [headlessValue, "disable-gpu"]; }, }, [types_1.BrowserName.CHROMEHEADLESSSHELL]: { capabilityName: "goog:chromeOptions", getArgs: (headlessMode) => { const headlessValue = (0, lodash_1.isBoolean)(headlessMode) ? "headless" : `headless=${headlessMode}`; return [headlessValue, "disable-gpu"]; }, }, [types_1.BrowserName.FIREFOX]: { capabilityName: "moz:firefoxOptions", getArgs: () => ["-headless"], }, [types_1.BrowserName.EDGE]: { capabilityName: "ms:edgeOptions", getArgs: () => ["--headless"], }, }; class NewBrowser extends browser_1.Browser { constructor(config, opts) { super(config, opts); signal_handler_1.default.on("exit", () => this.quit()); } async init() { this._session = await this._createSession(); this._addCommands(); this.restoreHttpTimeout(); await this._setPageLoadTimeout(); return this; } reset() { return Promise.resolve(); } async quit() { try { this.setHttpTimeout(this._config.sessionQuitTimeout); await this._session.deleteSession(); this._wdProcess?.free(); } catch (e) { (0, logger_1.warn)(`WARNING: Can not close session: ${e.message}`); this._wdProcess?.kill(); } finally { this._wdProcess = null; } } async kill() { try { await this._session.deleteSession(); this._wdProcess?.kill(); } catch (e) { (0, logger_1.warn)(`WARNING: Can not kill WebDriver process: ${e.message}`); } } async _createSession() { const sessionOpts = await this._getSessionOpts(); return (0, webdriverio_1.remote)(sessionOpts); } async _setPageLoadTimeout() { if (!this._config.pageLoadTimeout) { return; } try { await this._session.setTimeout({ pageLoad: this._config.pageLoadTimeout }); } catch (e) { // edge with w3c does not support setting page load timeout if (this._session.isW3C && this._session.capabilities.browserName === "MicrosoftEdge") { (0, logger_1.warn)(`WARNING: Can not set page load timeout: ${e.message}`); } else { throw e; } } } _isLocalGridUrl() { return this._config.gridUrl === config_1.LOCAL_GRID_URL || (0, runtime_config_1.getInstance)().local; } async _getSessionOpts() { const config = this._config; let gridUrl; if (this._isLocalGridUrl() && config.automationProtocol === config_1.WEBDRIVER_PROTOCOL) { gridUrl = await this._getLocalWebdriverGridUrl(); } else { // if automationProtocol is not "webdriver", fallback to default grid url from "local" // because in "devtools" protocol we dont need gridUrl, but it still has to be valid URL gridUrl = config.gridUrl === config_1.LOCAL_GRID_URL ? defaults_1.gridUrl : config.gridUrl; } const gridUri = new urijs_1.default(gridUrl); const capabilities = await this._extendCapabilities(config); const { devtools } = (0, runtime_config_1.getInstance)(); const options = { protocol: gridUri.protocol(), hostname: this._getGridHost(gridUri), port: gridUri.port() ? parseInt(gridUri.port(), 10) : DEFAULT_PORT, path: gridUri.path(), queryParams: this._getQueryParams(gridUri.query()), capabilities, automationProtocol: devtools ? config_1.DEVTOOLS_PROTOCOL : config.automationProtocol, connectionRetryTimeout: config.sessionRequestTimeout || config.httpTimeout, connectionRetryCount: 3, baseUrl: config.baseUrl, waitforTimeout: config.waitTimeout, waitforInterval: config.waitInterval, ...this._getSessionOptsFromConfig(), }; return options; } _extendCapabilities(config) { const capabilitiesExtendedByVersion = this.version ? this._extendCapabilitiesByVersion() : config.desiredCapabilities; const capabilitiesExtendedByProtocol = this._addWebDriverClassicCapability(capabilitiesExtendedByVersion); const capabilitiesWithAddedHeadless = this._addHeadlessCapability(config.headless, capabilitiesExtendedByProtocol); return this._isLocalGridUrl() ? this._applyLocalBrowserCapabilities(config, capabilitiesWithAddedHeadless) : Promise.resolve(capabilitiesWithAddedHeadless); } _addHeadlessCapability(headless, capabilities) { if (!headless) { return capabilities; } const browserNameW3C = (0, browser_2.getNormalizedBrowserName)(capabilities.browserName); if (!browserNameW3C) { return capabilities; } const capabilitySettings = headlessBrowserOptions[browserNameW3C]; if (!capabilitySettings) { (0, logger_1.warn)(`WARNING: Headless setting is not supported for ${capabilities.browserName} browserName`); return capabilities; } const browserCapabilities = (capabilities[capabilitySettings.capabilityName] ?? {}); // eslint-disable-next-line @typescript-eslint/no-explicit-any capabilities[capabilitySettings.capabilityName] = { ...browserCapabilities, args: [...(browserCapabilities.args ?? []), ...capabilitySettings.getArgs(headless)], }; return capabilities; } _addWebDriverClassicCapability(capabilities) { if (capabilities?.webSocketUrl || "wdio:enforceWebDriverClassic" in capabilities) { return capabilities; } return (0, lodash_1.assign)({}, capabilities, { "wdio:enforceWebDriverClassic": true }); } _extendCapabilitiesByVersion() { const { desiredCapabilities, sessionEnvFlags } = this._config; const versionKeyName = desiredCapabilities.browserVersion || sessionEnvFlags.isW3C ? "browserVersion" : "version"; return (0, lodash_1.assign)({}, desiredCapabilities, { [versionKeyName]: this.version }); } async _getLocalWebdriverGridUrl() { if (!this._wdPool) { throw new Error("webdriver pool is not defined"); } if (this._wdProcess) { return this._wdProcess.gridUrl; } this._wdProcess = await this._wdPool.getWebdriver(this._config.desiredCapabilities?.browserName, this._config.desiredCapabilities?.browserVersion, { debug: this._config.system.debug }); return this._wdProcess.gridUrl; } async _applyLocalBrowserCapabilities(config, capabilities) { const { installBrowser } = await Promise.resolve().then(() => __importStar(require("../browser-installer"))); const browserNameW3C = (0, browser_2.getNormalizedBrowserName)(config.desiredCapabilities?.browserName); if (!browserNameW3C) { throw new Error([ `Running auto local "${config.desiredCapabilities?.browserName}" is unsupported`, `Supported browsers: "chrome", "firefox", "safari", "edge"`, ].join("\n")); } const executablePath = await installBrowser(browserNameW3C, config.desiredCapabilities?.browserVersion, { shouldInstallWebDriver: false, shouldInstallUbuntuPackages: true, }); if (executablePath) { const capabilitySettings = headlessBrowserOptions[browserNameW3C]; if (!capabilitySettings) { return capabilities; } capabilities[capabilitySettings.capabilityName] ||= {}; capabilities[capabilitySettings.capabilityName].binary ||= executablePath; } const filteredCapabilities = Object.keys(capabilities) .filter(capabilityName => { const isW3CCapability = config_1.W3C_CAPABILITIES.includes(capabilityName); const isVendorSpecificCapability = config_1.VENDOR_CAPABILITIES[browserNameW3C].includes(capabilityName); return isW3CCapability || isVendorSpecificCapability; }) .reduce((acc, capabilityName) => { return (0, lodash_1.set)(acc, [capabilityName], capabilities[capabilityName]); }, {}); return filteredCapabilities; } _getGridHost(url) { return new urijs_1.default({ username: url.username(), password: url.password(), hostname: url.hostname(), }) .toString() .slice(2); // URIjs leaves `//` prefix, removing it } _getQueryParams(query) { if ((0, lodash_1.isEmpty)(query)) { return {}; } const urlParams = new url_1.URLSearchParams(query); return Object.fromEntries(urlParams); } } exports.NewBrowser = NewBrowser; //# sourceMappingURL=new-browser.js.map