diff --git a/.gitignore b/.gitignore index 349af901d..47937fc12 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ .DS_store .DS_Store -build .idea .vscode diff --git a/build/package.json b/build/package.json new file mode 100644 index 000000000..30f0a13a2 --- /dev/null +++ b/build/package.json @@ -0,0 +1,130 @@ +{ + "name": "hermione", + "version": "8.0.0-beta.3", + "description": "Tests framework based on mocha and wdio", + "main": "build/src/index.js", + "files": [ + "build" + ], + "scripts": { + "build": "tsc && npm run copy-static", + "copy-static": "copyfiles 'src/browser/client-scripts/*' 'typings/*' build", + "check-types": "tsc --project tsconfig.spec.json", + "clean": "rimraf build/ *.tsbuildinfo", + "coverage": "nyc --reporter=text npm run test-unit", + "lint": "eslint --cache . && prettier --check .", + "reformat": "eslint --fix . && prettier --write .", + "prettier-watch": "onchange '**' --exclude-path .prettierignore -- prettier --write {{changed}}", + "test-unit": "_mocha test/", + "test": "npm run test-unit && npm run check-types && npm run lint", + "toc": "doctoc README.md", + "precommit": "npm run lint", + "prepack": "npm run clean && npm run build", + "preversion": "npm run lint && npm test", + "commitmsg": "commitlint -e", + "release": "standard-version", + "watch": "npm run copy-static && tsc --watch" + }, + "repository": { + "type": "git", + "url": "git://github.com/gemini-testing/hermione.git" + }, + "engines": { + "node": ">= 18.0.0" + }, + "keywords": [ + "hermione", + "webdriverio", + "mocha", + "test" + ], + "bin": { + "hermione": "./bin/hermione" + }, + "license": "MIT", + "dependencies": { + "@gemini-testing/commander": "2.15.3", + "@types/chalk": "^2.2.0", + "@types/mocha": "^10.0.1", + "@wdio/globals": "^8.10.7", + "@wdio/types": "^8.10.4", + "@wdio/utils": "^7.26.0", + "aliasify": "^1.9.0", + "bluebird": "^3.5.1", + "browserify": "^13.3.0", + "chalk": "^2.4.2", + "clear-require": "^1.0.1", + "date-fns": "^2.29.3", + "debug": "^2.6.9", + "expect-webdriverio": "^3.5.3", + "fastq": "^1.13.0", + "fs-extra": "^5.0.0", + "gemini-configparser": "^1.3.0", + "glob-extra": "^5.0.2", + "inherit": "^2.2.2", + "lodash": "^4.17.21", + "looks-same": "^9.0.0", + "micromatch": "^4.0.5", + "mocha": "^10.2.0", + "plugins-loader": "^1.2.0", + "png-validator": "1.1.0", + "sharp": "~0.30.7", + "sizzle": "^2.3.6", + "strip-ansi": "^6.0.1", + "temp": "^0.8.3", + "uglifyify": "^3.0.4", + "urijs": "^1.19.11", + "url-join": "^4.0.1", + "webdriverio": "8.21.0", + "worker-farm": "^1.7.0", + "yallist": "^3.1.1" + }, + "devDependencies": { + "@commitlint/cli": "^17.1.2", + "@commitlint/config-conventional": "^17.1.0", + "@sinonjs/fake-timers": "^10.3.0", + "@swc/core": "^1.3.40", + "@types/bluebird": "^3.5.38", + "@types/chai": "^4.3.4", + "@types/chai-as-promised": "^7.1.5", + "@types/lodash": "^4.14.191", + "@types/node": "^18.19.3", + "@types/proxyquire": "^1.3.28", + "@types/sharp": "^0.31.1", + "@types/sinon": "^4.3.3", + "@types/sinonjs__fake-timers": "^8.1.2", + "@typescript-eslint/eslint-plugin": "^6.12.0", + "@typescript-eslint/parser": "^6.12.0", + "app-module-path": "^2.2.0", + "chai": "^4.1.1", + "chai-as-promised": "^7.1.1", + "copyfiles": "^2.4.1", + "doctoc": "^2.2.0", + "escape-string-regexp": "1.0.5", + "eslint": "^8.25.0", + "eslint-config-gemini-testing": "^2.8.0", + "eslint-config-prettier": "^8.7.0", + "husky": "^0.11.4", + "jsdom": "^16.6.0", + "jsdom-global": "^3.0.2", + "nyc": "^15.1.0", + "onchange": "^7.1.0", + "prettier": "^2.8.4", + "proxyquire": "^1.7.3", + "rimraf": "^4.1.2", + "sinon": "^4.4.2", + "sinon-chai": "^2.12.0", + "standard-version": "^9.5.0", + "ts-node": "^10.9.1", + "type-fest": "^3.10.0", + "typescript": "^5.3.2" + }, + "peerDependencies": { + "ts-node": ">=10.5.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + } +} diff --git a/build/src/base-hermione.d.ts b/build/src/base-hermione.d.ts new file mode 100644 index 000000000..dd2edb26e --- /dev/null +++ b/build/src/base-hermione.d.ts @@ -0,0 +1,18 @@ +import { Config } from "./config"; +import { AsyncEmitter, InterceptedEvent, Events, InterceptHandler, Interceptor } from "./events"; +import Errors from "./errors"; +import { ConfigInput } from "./config/types"; +export declare abstract class BaseHermione extends AsyncEmitter { + protected _interceptors: Interceptor[]; + protected _config: Config; + static create(this: new (config?: string | ConfigInput) => T, config?: string | ConfigInput): T; + protected constructor(config?: string | ConfigInput); + protected _init(): Promise; + get config(): Config; + get events(): Events; + get errors(): typeof Errors; + intercept(event: InterceptedEvent, handler: InterceptHandler): this; + abstract isWorker(): boolean; + protected _setLogLevel(): void; + protected _loadPlugins(): void; +} diff --git a/build/src/base-hermione.js b/build/src/base-hermione.js new file mode 100644 index 000000000..86c83bccb --- /dev/null +++ b/build/src/base-hermione.js @@ -0,0 +1,78 @@ +"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.BaseHermione = void 0; +const lodash_1 = __importDefault(require("lodash")); +const plugins_loader_1 = __importDefault(require("plugins-loader")); +const config_1 = require("./config"); +const events_1 = require("./events"); +const errors_1 = __importDefault(require("./errors")); +const typescript_1 = require("./utils/typescript"); +const packageJson = __importStar(require("../package.json")); +const PREFIX = packageJson.name + "-"; +class BaseHermione extends events_1.AsyncEmitter { + static create(config) { + return new this(config); + } + constructor(config) { + super(); + this._interceptors = []; + this._interceptors = []; + (0, typescript_1.tryToRegisterTsNode)(); + this._config = config_1.Config.create(config); + this._setLogLevel(); + this._loadPlugins(); + } + async _init() { + this._init = () => Promise.resolve(); // init only once + await this.emitAndWait(events_1.MasterEvents.INIT); + } + get config() { + return this._config; + } + get events() { + return lodash_1.default.extend({}, events_1.MasterEvents, events_1.WorkerEvents); + } + get errors() { + return errors_1.default; + } + intercept(event, handler) { + this._interceptors.push({ event, handler }); + return this; + } + _setLogLevel() { + if (!process.env.WDIO_LOG_LEVEL) { + process.env.WDIO_LOG_LEVEL = lodash_1.default.get(this.config, "system.debug", false) ? "trace" : "error"; + } + } + _loadPlugins() { + plugins_loader_1.default.load(this, this.config.plugins, PREFIX); + } +} +exports.BaseHermione = BaseHermione; +//# sourceMappingURL=base-hermione.js.map \ No newline at end of file diff --git a/build/src/base-hermione.js.map b/build/src/base-hermione.js.map new file mode 100644 index 000000000..0400d922b --- /dev/null +++ b/build/src/base-hermione.js.map @@ -0,0 +1 @@ +{"version":3,"file":"base-hermione.js","sourceRoot":"","sources":["../../src/base-hermione.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oDAAuB;AACvB,oEAA2C;AAC3C,qCAAkC;AAClC,qCAQkB;AAClB,sDAA8B;AAC9B,mDAAyD;AACzD,6DAA+C;AAG/C,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,GAAG,GAAG,CAAC;AAEtC,MAAsB,YAAa,SAAQ,qBAAY;IAInD,MAAM,CAAC,MAAM,CAET,MAA6B;QAE7B,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED,YAAsB,MAA6B;QAC/C,KAAK,EAAE,CAAC;QAXF,kBAAa,GAAkB,EAAE,CAAC;QAaxC,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QAExB,IAAA,gCAAmB,GAAE,CAAC;QAEtB,IAAI,CAAC,OAAO,GAAG,eAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,IAAI,CAAC,YAAY,EAAE,CAAC;IACxB,CAAC;IAES,KAAK,CAAC,KAAK;QACjB,IAAI,CAAC,KAAK,GAAG,GAAkB,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,iBAAiB;QACtE,MAAM,IAAI,CAAC,WAAW,CAAC,qBAAY,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,IAAI,MAAM;QACN,OAAO,gBAAC,CAAC,MAAM,CAAC,EAAE,EAAE,qBAAY,EAAE,qBAAY,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,MAAM;QACN,OAAO,gBAAM,CAAC;IAClB,CAAC;IAED,SAAS,CAAC,KAAuB,EAAE,OAAyB;QACxD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAE5C,OAAO,IAAI,CAAC;IAChB,CAAC;IAIS,YAAY;QAClB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,gBAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;QAC/F,CAAC;IACL,CAAC;IAES,YAAY;QAClB,wBAAa,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1D,CAAC;CACJ;AAzDD,oCAyDC"} \ No newline at end of file diff --git a/build/src/browser-pool/basic-pool.d.ts b/build/src/browser-pool/basic-pool.d.ts new file mode 100644 index 000000000..1ae58e2af --- /dev/null +++ b/build/src/browser-pool/basic-pool.d.ts @@ -0,0 +1,14 @@ +export = BasicPool; +declare class BasicPool extends Pool { + static create(config: any, emitter: any): import("./basic-pool"); + constructor(config: any, emitter: any); + _config: any; + _emitter: any; + log: any; + _activeSessions: {}; + getBrowser(id: any, opts?: {}): Promise; + freeBrowser(browser: any): Promise; + _emit(event: any, browser: any): any; + _cancelled: boolean | undefined; +} +import Pool = require("./pool"); diff --git a/build/src/browser-pool/basic-pool.js b/build/src/browser-pool/basic-pool.js new file mode 100644 index 000000000..8e9812feb --- /dev/null +++ b/build/src/browser-pool/basic-pool.js @@ -0,0 +1,62 @@ +"use strict"; +const _ = require("lodash"); +const Browser = require("../browser/new-browser"); +const { CancelledError } = require("./cancelled-error"); +const { MasterEvents } = require("../events"); +const Pool = require("./pool"); +const debug = require("debug"); +module.exports = class BasicPool extends Pool { + static create(config, emitter) { + return new BasicPool(config, emitter); + } + constructor(config, emitter) { + super(); + this._config = config; + this._emitter = emitter; + this.log = debug("hermione:pool:basic"); + this._activeSessions = {}; + } + async getBrowser(id, opts = {}) { + const browser = Browser.create(this._config, { ...opts, id }); + try { + await browser.init(); + this.log(`browser ${browser.fullId} started`); + await this._emit(MasterEvents.SESSION_START, browser); + if (this._cancelled) { + throw new CancelledError(); + } + await browser.reset(); + this._activeSessions[browser.sessionId] = browser; + return browser; + } + catch (e) { + if (browser.publicAPI) { + await this.freeBrowser(browser); + } + throw e; + } + } + async freeBrowser(browser) { + delete this._activeSessions[browser.sessionId]; + this.log(`stop browser ${browser.fullId}`); + try { + await this._emit(MasterEvents.SESSION_END, browser); + } + catch (err) { + console.warn((err && err.stack) || err); + } + await browser.quit(); + } + _emit(event, browser) { + return this._emitter.emitAndWait(event, browser.publicAPI, { + browserId: browser.id, + sessionId: browser.sessionId, + }); + } + cancel() { + this._cancelled = true; + _.forEach(this._activeSessions, browser => browser.quit()); + this._activeSessions = {}; + } +}; +//# sourceMappingURL=basic-pool.js.map \ No newline at end of file diff --git a/build/src/browser-pool/basic-pool.js.map b/build/src/browser-pool/basic-pool.js.map new file mode 100644 index 000000000..a49397926 --- /dev/null +++ b/build/src/browser-pool/basic-pool.js.map @@ -0,0 +1 @@ +{"version":3,"file":"basic-pool.js","sourceRoot":"","sources":["../../../src/browser-pool/basic-pool.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/browser-pool/caching-pool.d.ts b/build/src/browser-pool/caching-pool.d.ts new file mode 100644 index 000000000..f7878eefc --- /dev/null +++ b/build/src/browser-pool/caching-pool.d.ts @@ -0,0 +1,29 @@ +export = CachingPool; +declare class CachingPool extends Pool { + /** + * @constructor + * @extends BasicPool + * @param {BasicPool} underlyingPool + */ + constructor(underlyingPool: BasicPool, config: any); + log: any; + underlyingPool: BasicPool; + _caches: {}; + _config: any; + _getCacheFor(id: any, version: any): any; + getBrowser(id: any, opts?: {}): any; + _initPool(browserId: any, version: any): void; + /** + * Free browser + * @param {Browser} browser session instance + * @param {Object} [options] - advanced options + * @param {Boolean} [options.force] - if `true` than browser should + * not be cached + * @returns {Promise} + */ + freeBrowser(browser: Browser, options?: { + force?: boolean | undefined; + } | undefined): Promise; +} +import Pool = require("./pool"); +import Promise = require("bluebird"); diff --git a/build/src/browser-pool/caching-pool.js b/build/src/browser-pool/caching-pool.js new file mode 100644 index 000000000..952344e9d --- /dev/null +++ b/build/src/browser-pool/caching-pool.js @@ -0,0 +1,90 @@ +"use strict"; +const Promise = require("bluebird"); +const Pool = require("./pool"); +const LimitedUseSet = require("./limited-use-set"); +const debug = require("debug"); +const { buildCompositeBrowserId } = require("./utils"); +module.exports = class CachingPool extends Pool { + /** + * @constructor + * @extends BasicPool + * @param {BasicPool} underlyingPool + */ + constructor(underlyingPool, config) { + super(); + this.log = debug("hermione:pool:caching"); + this.underlyingPool = underlyingPool; + this._caches = {}; + this._config = config; + } + _getCacheFor(id, version) { + const compositeId = buildCompositeBrowserId(id, version); + this.log(`request for ${compositeId}`); + if (!this._caches[compositeId]) { + this.log(`init for ${compositeId}`); + this._initPool(id, version); + } + return this._caches[compositeId]; + } + getBrowser(id, opts = {}) { + const { version } = opts; + const cache = this._getCacheFor(id, version); + const browser = cache.pop(); + if (!browser) { + this.log(`no cached browser for ${buildCompositeBrowserId(id, version)}, requesting new`); + return this.underlyingPool.getBrowser(id, opts); + } + this.log(`has cached browser ${browser.fullId}`); + return browser + .reset() + .catch(e => { + const reject = Promise.reject.bind(null, e); + return this.underlyingPool.freeBrowser(browser).then(reject, reject); + }) + .then(() => browser); + } + _initPool(browserId, version) { + const compositeId = buildCompositeBrowserId(browserId, version); + const freeBrowser = this.underlyingPool.freeBrowser.bind(this.underlyingPool); + const { testsPerSession } = this._config.forBrowser(browserId); + this._caches[compositeId] = new LimitedUseSet({ + formatItem: item => item.fullId, + // browser does not get put in a set on first usages, so if + // we want to limit it usage to N times, we must set N-1 limit + // for the set. + useLimit: testsPerSession - 1, + finalize: freeBrowser, + }); + } + /** + * Free browser + * @param {Browser} browser session instance + * @param {Object} [options] - advanced options + * @param {Boolean} [options.force] - if `true` than browser should + * not be cached + * @returns {Promise} + */ + freeBrowser(browser, options = {}) { + const shouldFreeForNextRequest = () => { + const { compositeIdForNextRequest } = options; + if (!compositeIdForNextRequest) { + return false; + } + const { hasFreeSlots } = options; + const hasCacheForNextRequest = this._caches[options.compositeIdForNextRequest]; + return !hasFreeSlots && !hasCacheForNextRequest; + }; + const force = options.force || shouldFreeForNextRequest(); + this.log(`free ${browser.fullId} force=${force}`); + if (force) { + return this.underlyingPool.freeBrowser(browser); + } + const cache = this._getCacheFor(browser.id, browser.version); + return cache.push(browser); + } + cancel() { + this.log("cancel"); + this.underlyingPool.cancel(); + } +}; +//# sourceMappingURL=caching-pool.js.map \ No newline at end of file diff --git a/build/src/browser-pool/caching-pool.js.map b/build/src/browser-pool/caching-pool.js.map new file mode 100644 index 000000000..472abbc76 --- /dev/null +++ b/build/src/browser-pool/caching-pool.js.map @@ -0,0 +1 @@ +{"version":3,"file":"caching-pool.js","sourceRoot":"","sources":["../../../src/browser-pool/caching-pool.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/browser-pool/cancelled-error.d.ts b/build/src/browser-pool/cancelled-error.d.ts new file mode 100644 index 000000000..6ae90ab98 --- /dev/null +++ b/build/src/browser-pool/cancelled-error.d.ts @@ -0,0 +1,5 @@ +export declare class CancelledError extends Error { + name: string; + message: string; + constructor(); +} diff --git a/build/src/browser-pool/cancelled-error.js b/build/src/browser-pool/cancelled-error.js new file mode 100644 index 000000000..93fde220a --- /dev/null +++ b/build/src/browser-pool/cancelled-error.js @@ -0,0 +1,13 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CancelledError = void 0; +class CancelledError extends Error { + constructor() { + super(); + this.name = "CancelledError"; + this.message = "Browser request was cancelled"; + Error.captureStackTrace(this, CancelledError); + } +} +exports.CancelledError = CancelledError; +//# sourceMappingURL=cancelled-error.js.map \ No newline at end of file diff --git a/build/src/browser-pool/cancelled-error.js.map b/build/src/browser-pool/cancelled-error.js.map new file mode 100644 index 000000000..a8e7f1fe3 --- /dev/null +++ b/build/src/browser-pool/cancelled-error.js.map @@ -0,0 +1 @@ +{"version":3,"file":"cancelled-error.js","sourceRoot":"","sources":["../../../src/browser-pool/cancelled-error.ts"],"names":[],"mappings":";;;AAAA,MAAa,cAAe,SAAQ,KAAK;IAIrC;QACI,KAAK,EAAE,CAAC;QAJZ,SAAI,GAAG,gBAAgB,CAAC;QACxB,YAAO,GAAG,+BAA+B,CAAC;QAItC,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAClD,CAAC;CACJ;AARD,wCAQC"} \ No newline at end of file diff --git a/build/src/browser-pool/index.d.ts b/build/src/browser-pool/index.d.ts new file mode 100644 index 000000000..d8d380490 --- /dev/null +++ b/build/src/browser-pool/index.d.ts @@ -0,0 +1,6 @@ +import LimitedPool from "./limited-pool"; +import PerBrowserLimitedPool from "./per-browser-limited-pool"; +import { Config } from "../config"; +import { AsyncEmitter } from "../events"; +export type BrowserPool = LimitedPool | PerBrowserLimitedPool; +export declare const create: (config: Config, emitter: AsyncEmitter) => BrowserPool; diff --git a/build/src/browser-pool/index.js b/build/src/browser-pool/index.js new file mode 100644 index 000000000..898266e01 --- /dev/null +++ b/build/src/browser-pool/index.js @@ -0,0 +1,25 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.create = void 0; +const lodash_1 = __importDefault(require("lodash")); +const basic_pool_1 = __importDefault(require("./basic-pool")); +const limited_pool_1 = __importDefault(require("./limited-pool")); +const per_browser_limited_pool_1 = __importDefault(require("./per-browser-limited-pool")); +const caching_pool_1 = __importDefault(require("./caching-pool")); +const create = function (config, emitter) { + let pool = basic_pool_1.default.create(config, emitter); + pool = new caching_pool_1.default(pool, config); + pool = new per_browser_limited_pool_1.default(pool, config); + if (lodash_1.default.isFinite(config.system.parallelLimit)) { + pool = new limited_pool_1.default(pool, { + limit: config.system.parallelLimit, + isSpecificBrowserLimiter: false, + }); + } + return pool; +}; +exports.create = create; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/browser-pool/index.js.map b/build/src/browser-pool/index.js.map new file mode 100644 index 000000000..82ae92c87 --- /dev/null +++ b/build/src/browser-pool/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/browser-pool/index.ts"],"names":[],"mappings":";;;;;;AAAA,oDAAuB;AACvB,8DAAqC;AACrC,kEAAyC;AACzC,0FAA+D;AAC/D,kEAAyC;AAMlC,MAAM,MAAM,GAAG,UAAU,MAAc,EAAE,OAAqB;IACjE,IAAI,IAAI,GAAkE,oBAAS,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE5G,IAAI,GAAG,IAAI,sBAAW,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrC,IAAI,GAAG,IAAI,kCAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAE/C,IAAI,gBAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;QAC1C,IAAI,GAAG,IAAI,sBAAW,CAAC,IAAI,EAAE;YACzB,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa;YAClC,wBAAwB,EAAE,KAAK;SAClC,CAAC,CAAC;IACP,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC;AAdW,QAAA,MAAM,UAcjB"} \ No newline at end of file diff --git a/build/src/browser-pool/limited-pool.d.ts b/build/src/browser-pool/limited-pool.d.ts new file mode 100644 index 000000000..4b6f0c520 --- /dev/null +++ b/build/src/browser-pool/limited-pool.d.ts @@ -0,0 +1,30 @@ +export = LimitedPool; +declare class LimitedPool extends Pool { + static create(underlyingPool: any, opts: any): import("./limited-pool"); + /** + * @extends BasicPool + * @param {Number} limit + * @param {BasicPool} underlyingPool + */ + constructor(underlyingPool: BasicPool, opts: any); + log: any; + underlyingPool: BasicPool; + _limit: any; + _launched: number; + _requests: number; + _requestQueue: any; + _highPriorityRequestQueue: any; + _isSpecificBrowserLimiter: any; + getBrowser(id: any, opts?: {}): Promise; + freeBrowser(browser: any, opts?: {}): any; + _getBrowser(id: any, opts?: {}): Promise; + /** + * @param {String} id + * @returns {Promise} + */ + _newBrowser(id: string, opts: any): Promise; + _lookAtNextRequest(): any; + _launchNextBrowser(): void; +} +import Pool = require("./pool"); +import Promise = require("bluebird"); diff --git a/build/src/browser-pool/limited-pool.js b/build/src/browser-pool/limited-pool.js new file mode 100644 index 000000000..a55bcb994 --- /dev/null +++ b/build/src/browser-pool/limited-pool.js @@ -0,0 +1,100 @@ +"use strict"; +const _ = require("lodash"); +const Promise = require("bluebird"); +const yallist = require("yallist"); +const Pool = require("./pool"); +const { CancelledError } = require("./cancelled-error"); +const debug = require("debug"); +const { buildCompositeBrowserId } = require("./utils"); +module.exports = class LimitedPool extends Pool { + static create(underlyingPool, opts) { + return new LimitedPool(underlyingPool, opts); + } + /** + * @extends BasicPool + * @param {Number} limit + * @param {BasicPool} underlyingPool + */ + constructor(underlyingPool, opts) { + super(); + this.log = debug("hermione:pool:limited"); + this.underlyingPool = underlyingPool; + this._limit = opts.limit; + this._launched = 0; + this._requests = 0; + this._requestQueue = yallist.create(); + this._highPriorityRequestQueue = yallist.create(); + this._isSpecificBrowserLimiter = _.isBoolean(opts.isSpecificBrowserLimiter) + ? opts.isSpecificBrowserLimiter + : true; + } + getBrowser(id, opts = {}) { + const optsToPrint = JSON.stringify(opts); + this.log(`get browser ${id} with opts:${optsToPrint} (launched ${this._launched}, limit ${this._limit})`); + ++this._requests; + return this._getBrowser(id, opts).catch(e => { + --this._requests; + return Promise.reject(e); + }); + } + freeBrowser(browser, opts = {}) { + --this._requests; + const nextRequest = this._lookAtNextRequest(); + const compositeIdForNextRequest = nextRequest && buildCompositeBrowserId(nextRequest.id, nextRequest.version); + const hasFreeSlots = this._launched < this._limit; + const shouldFreeUnusedResource = this._isSpecificBrowserLimiter && this._launched > this._requests; + const force = opts.force || shouldFreeUnusedResource; + const optsForFree = { force, compositeIdForNextRequest, hasFreeSlots }; + this.log(`free browser ${browser.fullId} with opts:${JSON.stringify(optsForFree)}`); + return this.underlyingPool.freeBrowser(browser, optsForFree).finally(() => this._launchNextBrowser()); + } + cancel() { + this.log("cancel"); + const reject_ = entry => entry.reject(new CancelledError()); + this._highPriorityRequestQueue.forEach(reject_); + this._requestQueue.forEach(reject_); + this._highPriorityRequestQueue = yallist.create(); + this._requestQueue = yallist.create(); + this.underlyingPool.cancel(); + } + _getBrowser(id, opts = {}) { + if (this._launched < this._limit) { + this.log("can launch one more"); + this._launched++; + return this._newBrowser(id, opts); + } + this.log("queuing the request"); + const queue = opts.highPriority ? this._highPriorityRequestQueue : this._requestQueue; + const { version } = opts; + return new Promise((resolve, reject) => { + queue.push({ id, version, resolve, reject }); + }); + } + /** + * @param {String} id + * @returns {Promise} + */ + _newBrowser(id, opts) { + this.log(`launching new browser ${id} with opts:${JSON.stringify(opts)}`); + return this.underlyingPool.getBrowser(id, opts).catch(e => { + this._launchNextBrowser(); + return Promise.reject(e); + }); + } + _lookAtNextRequest() { + return this._highPriorityRequestQueue.get(0) || this._requestQueue.get(0); + } + _launchNextBrowser() { + const queued = this._highPriorityRequestQueue.shift() || this._requestQueue.shift(); + if (queued) { + const compositeId = buildCompositeBrowserId(queued.id, queued.version); + this.log(`has queued requests for ${compositeId}`); + this.log(`remaining queue length: ${this._requestQueue.length}`); + this._newBrowser(queued.id, { version: queued.version }).then(queued.resolve, queued.reject); + } + else { + this._launched--; + } + } +}; +//# sourceMappingURL=limited-pool.js.map \ No newline at end of file diff --git a/build/src/browser-pool/limited-pool.js.map b/build/src/browser-pool/limited-pool.js.map new file mode 100644 index 000000000..a9b6b67ee --- /dev/null +++ b/build/src/browser-pool/limited-pool.js.map @@ -0,0 +1 @@ +{"version":3,"file":"limited-pool.js","sourceRoot":"","sources":["../../../src/browser-pool/limited-pool.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/browser-pool/limited-use-set.d.ts b/build/src/browser-pool/limited-use-set.d.ts new file mode 100644 index 000000000..8b148cdf4 --- /dev/null +++ b/build/src/browser-pool/limited-use-set.d.ts @@ -0,0 +1,13 @@ +export = LimitedUseSet; +declare class LimitedUseSet { + constructor(opts: any); + _useCounts: WeakMap; + _useLimit: any; + _finalize: any; + _formatItem: any; + _objects: any[]; + log: any; + push(value: any): any; + _isOverLimit(value: any): boolean; + pop(): any; +} diff --git a/build/src/browser-pool/limited-use-set.js b/build/src/browser-pool/limited-use-set.js new file mode 100644 index 000000000..948b77241 --- /dev/null +++ b/build/src/browser-pool/limited-use-set.js @@ -0,0 +1,54 @@ +"use strict"; +const _ = require("lodash"); +const debug = require("debug"); +/** + * Set implementation which allows to get and put an object + * there only limited amout of times. After limit is reached + * attempt to put an object there causes the object to be finalized. + * + * @constructor + * @param {Number} useLimit number of times object can be popped from set + * before finalizing. + * @param {Function} finalize callback which will be called when value in + * set needs to be finalized. + */ +module.exports = class LimitedUseSet { + constructor(opts) { + this._useCounts = new WeakMap(); + this._useLimit = opts.useLimit; + this._finalize = opts.finalize; + this._formatItem = opts.formatItem || _.identity; + this._objects = []; + this.log = debug("hermione:pool:limited-use-set"); + } + push(value) { + const formatedItem = this._formatItem(value); + this.log(`push ${formatedItem}`); + if (this._isOverLimit(value)) { + this.log(`over limit, finalizing ${formatedItem}`); + return this._finalize(value); + } + this.log(`under limit for ${formatedItem}`); + this._objects.push(value); + return Promise.resolve(); + } + _isOverLimit(value) { + if (this._useLimit === 0) { + return true; + } + return this._useCounts.has(value) && this._useCounts.get(value) >= this._useLimit; + } + pop() { + if (this._objects.length === 0) { + return null; + } + const result = this._objects.pop(); + const useCount = this._useCounts.get(result) || 0; + const formatedItem = this._formatItem(result); + this.log(`popping ${formatedItem}`); + this.log(`previous use count ${formatedItem}:${useCount}`); + this._useCounts.set(result, useCount + 1); + return result; + } +}; +//# sourceMappingURL=limited-use-set.js.map \ No newline at end of file diff --git a/build/src/browser-pool/limited-use-set.js.map b/build/src/browser-pool/limited-use-set.js.map new file mode 100644 index 000000000..21e5c5700 --- /dev/null +++ b/build/src/browser-pool/limited-use-set.js.map @@ -0,0 +1 @@ +{"version":3,"file":"limited-use-set.js","sourceRoot":"","sources":["../../../src/browser-pool/limited-use-set.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAE/B;;;;;;;;;;GAUG;AACH,MAAM,CAAC,OAAO,GAAG,MAAM,aAAa;IAChC,YAAY,IAAI;QACZ,IAAI,CAAC,UAAU,GAAG,IAAI,OAAO,EAAE,CAAC;QAChC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,QAAQ,CAAC;QACjD,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QAEnB,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,CAAC,KAAK;QACN,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAE7C,IAAI,CAAC,GAAG,CAAC,QAAQ,YAAY,EAAE,CAAC,CAAC;QAEjC,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,GAAG,CAAC,0BAA0B,YAAY,EAAE,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,mBAAmB,YAAY,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE1B,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;IAED,YAAY,CAAC,KAAK;QACd,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC;IACtF,CAAC;IAED,GAAG;QACC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAClD,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAE9C,IAAI,CAAC,GAAG,CAAC,WAAW,YAAY,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,sBAAsB,YAAY,IAAI,QAAQ,EAAE,CAAC,CAAC;QAE3D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC;QAE1C,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/browser-pool/per-browser-limited-pool.d.ts b/build/src/browser-pool/per-browser-limited-pool.d.ts new file mode 100644 index 000000000..54a32a798 --- /dev/null +++ b/build/src/browser-pool/per-browser-limited-pool.d.ts @@ -0,0 +1,10 @@ +export = PerBrowserLimitedPool; +declare class PerBrowserLimitedPool extends Pool { + constructor(underlyingPool: any, config: any); + log: any; + _browserPools: _.Dictionary; + getBrowser(id: any, opts: any): any; + freeBrowser(browser: any, opts: any): any; +} +import Pool = require("./pool"); +import _ = require("lodash"); diff --git a/build/src/browser-pool/per-browser-limited-pool.js b/build/src/browser-pool/per-browser-limited-pool.js new file mode 100644 index 000000000..ffe354c71 --- /dev/null +++ b/build/src/browser-pool/per-browser-limited-pool.js @@ -0,0 +1,28 @@ +"use strict"; +const _ = require("lodash"); +const Pool = require("./pool"); +const LimitedPool = require("./limited-pool"); +const debug = require("debug"); +module.exports = class PerBrowserLimitedPool extends Pool { + constructor(underlyingPool, config) { + super(); + this.log = debug("hermione:pool:per-browser-limited"); + const ids = config.getBrowserIds(); + this._browserPools = _.zipObject(ids, ids.map(id => LimitedPool.create(underlyingPool, { + limit: config.forBrowser(id).sessionsPerBrowser, + }))); + } + getBrowser(id, opts) { + this.log(`request ${id} with opts: ${JSON.stringify(opts)}`); + return this._browserPools[id].getBrowser(id, opts); + } + freeBrowser(browser, opts) { + this.log(`free ${browser.fullId}`); + return this._browserPools[browser.id].freeBrowser(browser, opts); + } + cancel() { + this.log("cancel"); + _.forEach(this._browserPools, pool => pool.cancel()); + } +}; +//# sourceMappingURL=per-browser-limited-pool.js.map \ No newline at end of file diff --git a/build/src/browser-pool/per-browser-limited-pool.js.map b/build/src/browser-pool/per-browser-limited-pool.js.map new file mode 100644 index 000000000..58669edcd --- /dev/null +++ b/build/src/browser-pool/per-browser-limited-pool.js.map @@ -0,0 +1 @@ +{"version":3,"file":"per-browser-limited-pool.js","sourceRoot":"","sources":["../../../src/browser-pool/per-browser-limited-pool.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC/B,MAAM,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAE/B,MAAM,CAAC,OAAO,GAAG,MAAM,qBAAsB,SAAQ,IAAI;IACrD,YAAY,cAAc,EAAE,MAAM;QAC9B,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC,mCAAmC,CAAC,CAAC;QAEtD,MAAM,GAAG,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;QACnC,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,SAAS,CAC5B,GAAG,EACH,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CACT,WAAW,CAAC,MAAM,CAAC,cAAc,EAAE;YAC/B,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,kBAAkB;SAClD,CAAC,CACL,CACJ,CAAC;IACN,CAAC;IAED,UAAU,CAAC,EAAE,EAAE,IAAI;QACf,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,eAAe,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAE7D,OAAO,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,WAAW,CAAC,OAAO,EAAE,IAAI;QACrB,IAAI,CAAC,GAAG,CAAC,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAEnC,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrE,CAAC;IAED,MAAM;QACF,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACnB,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACzD,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/browser-pool/pool.d.ts b/build/src/browser-pool/pool.d.ts new file mode 100644 index 000000000..3b87b133f --- /dev/null +++ b/build/src/browser-pool/pool.d.ts @@ -0,0 +1,13 @@ +export = Pool; +declare class Pool { + /** + * @returns {Promise.} + */ + getBrowser(): Promise; + /** + * @param {Browser} browser + * @returns {Promise} + */ + freeBrowser(): Promise; + cancel(): void; +} diff --git a/build/src/browser-pool/pool.js b/build/src/browser-pool/pool.js new file mode 100644 index 000000000..587625820 --- /dev/null +++ b/build/src/browser-pool/pool.js @@ -0,0 +1,18 @@ +"use strict"; +module.exports = class Pool { + /** + * @returns {Promise.} + */ + // eslint-disable-next-line @typescript-eslint/no-empty-function + getBrowser() { } + /** + * @param {Browser} browser + * @returns {Promise} + */ + freeBrowser() { + return Promise.resolve(); + } + // eslint-disable-next-line @typescript-eslint/no-empty-function + cancel() { } +}; +//# sourceMappingURL=pool.js.map \ No newline at end of file diff --git a/build/src/browser-pool/pool.js.map b/build/src/browser-pool/pool.js.map new file mode 100644 index 000000000..4d7b51fa4 --- /dev/null +++ b/build/src/browser-pool/pool.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pool.js","sourceRoot":"","sources":["../../../src/browser-pool/pool.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,OAAO,GAAG,MAAM,IAAI;IACvB;;OAEG;IACH,gEAAgE;IAChE,UAAU,KAAI,CAAC;IAEf;;;OAGG;IACH,WAAW;QACP,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;IAED,gEAAgE;IAChE,MAAM,KAAI,CAAC;CACd,CAAC"} \ No newline at end of file diff --git a/build/src/browser-pool/utils.d.ts b/build/src/browser-pool/utils.d.ts new file mode 100644 index 000000000..5429c66df --- /dev/null +++ b/build/src/browser-pool/utils.d.ts @@ -0,0 +1 @@ +export function buildCompositeBrowserId(browserId: any, version: any): any; diff --git a/build/src/browser-pool/utils.js b/build/src/browser-pool/utils.js new file mode 100644 index 000000000..ccdfd5f7e --- /dev/null +++ b/build/src/browser-pool/utils.js @@ -0,0 +1,3 @@ +"use strict"; +exports.buildCompositeBrowserId = (browserId, version) => (version ? `${browserId}.${version}` : browserId); +//# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/build/src/browser-pool/utils.js.map b/build/src/browser-pool/utils.js.map new file mode 100644 index 000000000..f1333e14b --- /dev/null +++ b/build/src/browser-pool/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/browser-pool/utils.js"],"names":[],"mappings":";AAAA,OAAO,CAAC,uBAAuB,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/browser/browser.d.ts b/build/src/browser/browser.d.ts new file mode 100644 index 000000000..ea3499ee0 --- /dev/null +++ b/build/src/browser/browser.d.ts @@ -0,0 +1,33 @@ +export = Browser; +declare class Browser { + static create(config: any, opts: any): import("./browser"); + constructor(config: any, opts: any); + id: any; + version: any; + testXReqId: any; + _config: any; + _debug: any; + _session: any; + _callstackHistory: import("./history/callstack") | null; + _state: { + isBroken: boolean; + }; + attach(sessionId: any, sessionCaps: any, sessionOpts: any): Promise; + setHttpTimeout(timeout: any): void; + restoreHttpTimeout(): void; + applyState(state: any): void; + _addCommands(): void; + _addSteps(): void; + _addHistory(): void; + _addExtendOptionsMethod(session: any): void; + _getSessionOptsFromConfig(optNames?: string[]): {}; + get fullId(): any; + get publicAPI(): any; + get sessionId(): any; + get config(): any; + get state(): { + isBroken: boolean; + }; + get capabilities(): any; + get callstackHistory(): import("./history/callstack") | null; +} diff --git a/build/src/browser/browser.js b/build/src/browser/browser.js new file mode 100644 index 000000000..6a4b0238c --- /dev/null +++ b/build/src/browser/browser.js @@ -0,0 +1,111 @@ +"use strict"; +const crypto = require("crypto"); +const _ = require("lodash"); +const { SAVE_HISTORY_MODE } = require("../constants/config"); +const { X_REQUEST_ID_DELIMITER } = require("../constants/browser"); +const history = require("./history"); +const addRunStepCommand = require("./commands/runStep"); +const CUSTOM_SESSION_OPTS = [ + "outputDir", + "agent", + "headers", + "transformRequest", + "transformResponse", + "strictSSL", + // cloud service opts + "user", + "key", + "region", +]; +module.exports = class Browser { + static create(config, opts) { + return new this(config, opts); + } + constructor(config, opts) { + this.id = opts.id; + this.version = opts.version; + this.testXReqId = opts.testXReqId; + this._config = config.forBrowser(this.id); + this._debug = config.system.debug; + this._session = null; + this._callstackHistory = null; + this._state = { + isBroken: false, + }; + } + async attach(sessionId, sessionCaps, sessionOpts) { + this._session = await this._attachSession(sessionId, sessionCaps, sessionOpts); + this._addSteps(); + this._addHistory(); + this._addCommands(); + } + setHttpTimeout(timeout) { + if (timeout === null) { + timeout = this._config.httpTimeout; + } + this._session.extendOptions({ connectionRetryTimeout: timeout }); + } + restoreHttpTimeout() { + this.setHttpTimeout(this._config.httpTimeout); + } + applyState(state) { + _.extend(this._state, state); + } + _addCommands() { + this._addExtendOptionsMethod(this._session); + } + _addSteps() { + addRunStepCommand(this); + } + _addHistory() { + if (this._config.saveHistoryMode !== SAVE_HISTORY_MODE.NONE) { + this._callstackHistory = history.initCommandHistory(this._session); + } + } + _addExtendOptionsMethod(session) { + session.addCommand("extendOptions", opts => { + _.extend(session.options, opts); + }); + } + _getSessionOptsFromConfig(optNames = CUSTOM_SESSION_OPTS) { + return optNames.reduce((options, optName) => { + if (optName === "transformRequest") { + options[optName] = req => { + if (!_.isNull(this._config[optName])) { + req = this._config[optName](req); + } + if (!req.headers["X-Request-ID"]) { + req.headers["X-Request-ID"] = `${this.testXReqId}${X_REQUEST_ID_DELIMITER}${crypto.randomUUID()}`; + } + return req; + }; + } + else if (!_.isNull(this._config[optName])) { + options[optName] = this._config[optName]; + } + return options; + }, {}); + } + get fullId() { + return this.version ? `${this.id}.${this.version}` : this.id; + } + get publicAPI() { + return this._session; // exposing webdriver API as is + } + get sessionId() { + return this.publicAPI.sessionId; + } + get config() { + return this._config; + } + get state() { + return this._state; + } + get capabilities() { + return this.publicAPI.capabilities; + } + get callstackHistory() { + return this._callstackHistory; + } +}; +//# sourceMappingURL=browser.js.map \ No newline at end of file diff --git a/build/src/browser/browser.js.map b/build/src/browser/browser.js.map new file mode 100644 index 000000000..c508a94d3 --- /dev/null +++ b/build/src/browser/browser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../../src/browser/browser.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/browser/calibrator.d.ts b/build/src/browser/calibrator.d.ts new file mode 100644 index 000000000..70a5edb91 --- /dev/null +++ b/build/src/browser/calibrator.d.ts @@ -0,0 +1,16 @@ +export = Calibrator; +declare class Calibrator { + _cache: {}; + /** + * @param {Browser} browser + * @returns {Promise.} + */ + calibrate(browser: Browser): Promise; + _analyzeImage(image: any, params: any): globalThis.Promise<{ + viewportStart: { + x: number; + y: any; + }; + } | null>; +} +import Promise = require("bluebird"); diff --git a/build/src/browser/calibrator.js b/build/src/browser/calibrator.js new file mode 100644 index 000000000..ab8ae631f --- /dev/null +++ b/build/src/browser/calibrator.js @@ -0,0 +1,105 @@ +"use strict"; +const fs = require("fs"); +const path = require("path"); +const Promise = require("bluebird"); +const _ = require("lodash"); +const looksSame = require("looks-same"); +const { CoreError } = require("./core-error"); +const clientScriptCalibrate = fs.readFileSync(path.join(__dirname, "client-scripts", "calibrate.js"), "utf8"); +const DIRECTION = { FORWARD: "forward", REVERSE: "reverse" }; +module.exports = class Calibrator { + constructor() { + this._cache = {}; + } + /** + * @param {Browser} browser + * @returns {Promise.} + */ + calibrate(browser) { + if (this._cache[browser.id]) { + return Promise.resolve(this._cache[browser.id]); + } + return Promise.resolve(browser.open("about:blank")) + .then(() => browser.evalScript(clientScriptCalibrate)) + .then(features => [features, browser.captureViewportImage()]) + .spread(async (features, image) => { + const { innerWidth, pixelRatio } = features; + const hasPixelRatio = Boolean(pixelRatio && pixelRatio > 1.0); + const imageFeatures = await this._analyzeImage(image, { calculateColorLength: hasPixelRatio }); + if (!imageFeatures) { + return Promise.reject(new CoreError("Could not calibrate. This could be due to calibration page has failed to open properly")); + } + features = _.extend(features, { + top: imageFeatures.viewportStart.y, + left: imageFeatures.viewportStart.x, + usePixelRatio: hasPixelRatio && imageFeatures.colorLength > innerWidth, + }); + this._cache[browser.id] = features; + return features; + }); + } + async _analyzeImage(image, params) { + const imageHeight = (await image.getSize()).height; + for (var y = 0; y < imageHeight; y++) { + var result = await analyzeRow(y, image, params); + if (result) { + return result; + } + } + return null; + } +}; +async function analyzeRow(row, image, params = {}) { + const markerStart = await findMarkerInRow(row, image, DIRECTION.FORWARD); + if (markerStart === -1) { + return null; + } + const result = { viewportStart: { x: markerStart, y: row } }; + if (!params.calculateColorLength) { + return result; + } + const markerEnd = await findMarkerInRow(row, image, DIRECTION.REVERSE); + const colorLength = markerEnd - markerStart + 1; + return _.extend(result, { colorLength }); +} +async function findMarkerInRow(row, image, searchDirection) { + const imageWidth = (await image.getSize()).width; + const searchColor = { R: 148, G: 250, B: 0 }; + if (searchDirection === DIRECTION.REVERSE) { + return searchReverse_(); + } + else { + return searchForward_(); + } + async function searchForward_() { + for (var x = 0; x < imageWidth; x++) { + var isSame = await compare_(x); + if (isSame) { + return x; + } + } + return -1; + } + async function searchReverse_() { + for (var x = imageWidth - 1; x >= 0; x--) { + var isSame = await compare_(x); + if (isSame) { + return x; + } + } + return -1; + } + async function compare_(x) { + var pixel = await image.getRGBA(x, row); + var color = pickRGB(pixel); + return looksSame.colors(color, searchColor); + } +} +function pickRGB(rgba) { + return { + R: rgba.r, + G: rgba.g, + B: rgba.b, + }; +} +//# sourceMappingURL=calibrator.js.map \ No newline at end of file diff --git a/build/src/browser/calibrator.js.map b/build/src/browser/calibrator.js.map new file mode 100644 index 000000000..5caa2c10d --- /dev/null +++ b/build/src/browser/calibrator.js.map @@ -0,0 +1 @@ +{"version":3,"file":"calibrator.js","sourceRoot":"","sources":["../../../src/browser/calibrator.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/browser/camera/index.d.ts b/build/src/browser/camera/index.d.ts new file mode 100644 index 000000000..a2126e9ed --- /dev/null +++ b/build/src/browser/camera/index.d.ts @@ -0,0 +1,13 @@ +export = Camera; +declare class Camera { + static create(screenshotMode: any, takeScreenshot: any): import("."); + constructor(screenshotMode: any, takeScreenshot: any); + _screenshotMode: any; + _takeScreenshot: any; + _calibration: any; + calibrate(calibration: any): void; + captureViewportImage(page: any): Promise; + _calibrateArea(imageArea: any): any; + _cropAreaToViewport(imageArea: any, page: any): any; +} +import Image = require("../../image"); diff --git a/build/src/browser/camera/index.js b/build/src/browser/camera/index.js new file mode 100644 index 000000000..0cd79cefb --- /dev/null +++ b/build/src/browser/camera/index.js @@ -0,0 +1,53 @@ +"use strict"; +const Image = require("../../image"); +const _ = require("lodash"); +const utils = require("./utils"); +module.exports = class Camera { + static create(screenshotMode, takeScreenshot) { + return new this(screenshotMode, takeScreenshot); + } + constructor(screenshotMode, takeScreenshot) { + this._screenshotMode = screenshotMode; + this._takeScreenshot = takeScreenshot; + this._calibration = null; + } + calibrate(calibration) { + this._calibration = calibration; + } + async captureViewportImage(page) { + const base64 = await this._takeScreenshot(); + const image = Image.fromBase64(base64); + const { width, height } = await image.getSize(); + const imageArea = { left: 0, top: 0, width, height }; + const calibratedArea = this._calibrateArea(imageArea); + const viewportCroppedArea = this._cropAreaToViewport(calibratedArea, page); + if (viewportCroppedArea.width !== width || viewportCroppedArea.height !== height) { + await image.crop(viewportCroppedArea); + } + return image; + } + _calibrateArea(imageArea) { + if (!this._calibration) { + return imageArea; + } + const { left, top } = this._calibration; + return { left, top, width: imageArea.width - left, height: imageArea.height - top }; + } + _cropAreaToViewport(imageArea, page) { + if (!page) { + return imageArea; + } + const isFullPage = utils.isFullPage(imageArea, page, this._screenshotMode); + const cropArea = _.clone(page.viewport); + if (!isFullPage) { + _.extend(cropArea, { top: 0, left: 0 }); + } + return { + left: imageArea.left + cropArea.left, + top: imageArea.top + cropArea.top, + width: Math.min(imageArea.width - cropArea.left, cropArea.width), + height: Math.min(imageArea.height - cropArea.top, cropArea.height), + }; + } +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/browser/camera/index.js.map b/build/src/browser/camera/index.js.map new file mode 100644 index 000000000..c1f059303 --- /dev/null +++ b/build/src/browser/camera/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/browser/camera/index.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/browser/camera/utils.d.ts b/build/src/browser/camera/utils.d.ts new file mode 100644 index 000000000..5d8c7b438 --- /dev/null +++ b/build/src/browser/camera/utils.d.ts @@ -0,0 +1 @@ +export function isFullPage(imageArea: any, page: any, screenshotMode: any): boolean | undefined; diff --git a/build/src/browser/camera/utils.js b/build/src/browser/camera/utils.js new file mode 100644 index 000000000..1a9cb9fd1 --- /dev/null +++ b/build/src/browser/camera/utils.js @@ -0,0 +1,25 @@ +"use strict"; +exports.isFullPage = (imageArea, page, screenshotMode) => { + switch (screenshotMode) { + case "fullpage": + return true; + case "viewport": + return false; + case "auto": + return compareDimensions(imageArea, page); + } +}; +/** + * @param {Object} imageArea - area + * @param {number} imageArea.left - left offset + * @param {number} imageArea.top - top offset + * @param {number} imageArea.width - area width + * @param {number} imageArea.height - area height + * @param {Object} page - capture meta information object + * @returns {boolean} + * @private + */ +function compareDimensions(imageArea, page) { + return imageArea.height >= page.documentHeight && imageArea.width >= page.documentWidth; +} +//# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/build/src/browser/camera/utils.js.map b/build/src/browser/camera/utils.js.map new file mode 100644 index 000000000..db38148dc --- /dev/null +++ b/build/src/browser/camera/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/browser/camera/utils.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,CAAC,UAAU,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE;IACrD,QAAQ,cAAc,EAAE,CAAC;QACrB,KAAK,UAAU;YACX,OAAO,IAAI,CAAC;QAChB,KAAK,UAAU;YACX,OAAO,KAAK,CAAC;QACjB,KAAK,MAAM;YACP,OAAO,iBAAiB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAClD,CAAC;AACL,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACH,SAAS,iBAAiB,CAAC,SAAS,EAAE,IAAI;IACtC,OAAO,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,cAAc,IAAI,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,aAAa,CAAC;AAC5F,CAAC"} \ No newline at end of file diff --git a/build/src/browser/client-bridge/client-bridge.d.ts b/build/src/browser/client-bridge/client-bridge.d.ts new file mode 100644 index 000000000..9df549425 --- /dev/null +++ b/build/src/browser/client-bridge/client-bridge.d.ts @@ -0,0 +1,12 @@ +export = ClientBridge; +declare class ClientBridge { + static create(browser: any, script: any): import("./client-bridge"); + constructor(browser: any, script: any); + _browser: any; + _script: any; + call(name: any, args?: any[]): any; + _callCommand(command: any, injectAllowed: any): any; + _clientMethodCommand(name: any, args: any): string; + _guardClientCall(call: any): string; + _inject(): any; +} diff --git a/build/src/browser/client-bridge/client-bridge.js b/build/src/browser/client-bridge/client-bridge.js new file mode 100644 index 000000000..20607aea8 --- /dev/null +++ b/build/src/browser/client-bridge/client-bridge.js @@ -0,0 +1,41 @@ +"use strict"; +const Promise = require("bluebird"); +const { ClientBridgeError } = require("./error"); +module.exports = class ClientBridge { + static create(browser, script) { + return new ClientBridge(browser, script); + } + constructor(browser, script) { + this._browser = browser; + this._script = script; + } + call(name, args = []) { + return this._callCommand(this._clientMethodCommand(name, args), true); + } + _callCommand(command, injectAllowed) { + return this._browser + .evalScript(command) + .then(result => { + if (!result || !result.isClientScriptNotInjected) { + return Promise.resolve(result); + } + if (injectAllowed) { + return this._inject().then(() => this._callCommand(command, false)); + } + return Promise.reject(new ClientBridgeError("Unable to inject client script")); + }) + .catch(e => Promise.reject(new ClientBridgeError(e.message))); + } + _clientMethodCommand(name, args) { + const params = args.map(JSON.stringify).join(", "); + const call = `__geminiCore.${name}(${params})`; + return this._guardClientCall(call); + } + _guardClientCall(call) { + return `typeof __geminiCore !== "undefined" ? ${call} : {isClientScriptNotInjected: true}`; + } + _inject() { + return this._browser.injectScript(this._script); + } +}; +//# sourceMappingURL=client-bridge.js.map \ No newline at end of file diff --git a/build/src/browser/client-bridge/client-bridge.js.map b/build/src/browser/client-bridge/client-bridge.js.map new file mode 100644 index 000000000..82d54a85b --- /dev/null +++ b/build/src/browser/client-bridge/client-bridge.js.map @@ -0,0 +1 @@ +{"version":3,"file":"client-bridge.js","sourceRoot":"","sources":["../../../../src/browser/client-bridge/client-bridge.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACpC,MAAM,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAEjD,MAAM,CAAC,OAAO,GAAG,MAAM,YAAY;IAC/B,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM;QACzB,OAAO,IAAI,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IAED,YAAY,OAAO,EAAE,MAAM;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IAC1B,CAAC;IAED,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE;QAChB,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;IAC1E,CAAC;IAED,YAAY,CAAC,OAAO,EAAE,aAAa;QAC/B,OAAO,IAAI,CAAC,QAAQ;aACf,UAAU,CAAC,OAAO,CAAC;aACnB,IAAI,CAAC,MAAM,CAAC,EAAE;YACX,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,yBAAyB,EAAE,CAAC;gBAC/C,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACnC,CAAC;YAED,IAAI,aAAa,EAAE,CAAC;gBAChB,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;YACxE,CAAC;YAED,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,iBAAiB,CAAC,gCAAgC,CAAC,CAAC,CAAC;QACnF,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,oBAAoB,CAAC,IAAI,EAAE,IAAI;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,gBAAgB,IAAI,IAAI,MAAM,GAAG,CAAC;QAE/C,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IAED,gBAAgB,CAAC,IAAI;QACjB,OAAO,yCAAyC,IAAI,sCAAsC,CAAC;IAC/F,CAAC;IAED,OAAO;QACH,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpD,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/browser/client-bridge/error.d.ts b/build/src/browser/client-bridge/error.d.ts new file mode 100644 index 000000000..bf63b594c --- /dev/null +++ b/build/src/browser/client-bridge/error.d.ts @@ -0,0 +1,3 @@ +export declare class ClientBridgeError extends Error { + constructor(message: string); +} diff --git a/build/src/browser/client-bridge/error.js b/build/src/browser/client-bridge/error.js new file mode 100644 index 000000000..184c181b4 --- /dev/null +++ b/build/src/browser/client-bridge/error.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ClientBridgeError = void 0; +class ClientBridgeError extends Error { + constructor(message) { + super(message); + this.name = this.constructor.name; + } +} +exports.ClientBridgeError = ClientBridgeError; +//# sourceMappingURL=error.js.map \ No newline at end of file diff --git a/build/src/browser/client-bridge/error.js.map b/build/src/browser/client-bridge/error.js.map new file mode 100644 index 000000000..0ac7eeda6 --- /dev/null +++ b/build/src/browser/client-bridge/error.js.map @@ -0,0 +1 @@ +{"version":3,"file":"error.js","sourceRoot":"","sources":["../../../../src/browser/client-bridge/error.ts"],"names":[],"mappings":";;;AAAA,MAAa,iBAAkB,SAAQ,KAAK;IACxC,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IACtC,CAAC;CACJ;AALD,8CAKC"} \ No newline at end of file diff --git a/build/src/browser/client-bridge/index.d.ts b/build/src/browser/client-bridge/index.d.ts new file mode 100644 index 000000000..e50223cc1 --- /dev/null +++ b/build/src/browser/client-bridge/index.d.ts @@ -0,0 +1,4 @@ +export { ClientBridge }; +export function build(browser: any, opts?: {}): Promise; +import ClientBridge = require("./client-bridge"); +import Promise = require("bluebird"); diff --git a/build/src/browser/client-bridge/index.js b/build/src/browser/client-bridge/index.js new file mode 100644 index 000000000..9a0168983 --- /dev/null +++ b/build/src/browser/client-bridge/index.js @@ -0,0 +1,33 @@ +"use strict"; +const path = require("path"); +const Promise = require("bluebird"); +const browserify = require("browserify"); +const ClientBridge = require("./client-bridge"); +exports.ClientBridge = ClientBridge; +exports.build = (browser, opts = {}) => { + const script = browserify({ + entries: "./index", + basedir: path.join(__dirname, "..", "client-scripts"), + }); + script.transform({ + sourcemap: false, + global: true, + compress: { screw_ie8: false }, // eslint-disable-line camelcase + mangle: { screw_ie8: false }, // eslint-disable-line camelcase + output: { screw_ie8: false }, // eslint-disable-line camelcase + }, "uglifyify"); + const lib = opts.calibration && opts.calibration.needsCompatLib ? "./lib.compat.js" : "./lib.native.js"; + const ignoreAreas = opts.supportDeprecated ? "./ignore-areas.deprecated.js" : "./ignore-areas.js"; + script.transform({ + aliases: { + "./lib": { relative: lib }, + "./ignore-areas": { relative: ignoreAreas }, + }, + verbose: false, + }, "aliasify"); + return Promise.fromCallback(cb => script.bundle(cb)).then(buf => { + const scripts = buf.toString(); + return ClientBridge.create(browser, scripts); + }); +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/browser/client-bridge/index.js.map b/build/src/browser/client-bridge/index.js.map new file mode 100644 index 000000000..6033c26ce --- /dev/null +++ b/build/src/browser/client-bridge/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/browser/client-bridge/index.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAC7B,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACpC,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;AACzC,MAAM,YAAY,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEhD,OAAO,CAAC,YAAY,GAAG,YAAY,CAAC;AAEpC,OAAO,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,IAAI,GAAG,EAAE,EAAE,EAAE;IACnC,MAAM,MAAM,GAAG,UAAU,CAAC;QACtB,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,gBAAgB,CAAC;KACxD,CAAC,CAAC;IAEH,MAAM,CAAC,SAAS,CACZ;QACI,SAAS,EAAE,KAAK;QAChB,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,gCAAgC;QAChE,MAAM,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,gCAAgC;QAC9D,MAAM,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,gCAAgC;KACjE,EACD,WAAW,CACd,CAAC;IAEF,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,iBAAiB,CAAC;IACxG,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,mBAAmB,CAAC;IAElG,MAAM,CAAC,SAAS,CACZ;QACI,OAAO,EAAE;YACL,OAAO,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE;YAC1B,gBAAgB,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE;SAC9C;QACD,OAAO,EAAE,KAAK;KACjB,EACD,UAAU,CACb,CAAC;IAEF,OAAO,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QAC5D,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;QAE/B,OAAO,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/browser/client-scripts/calibrate.js b/build/src/browser/client-scripts/calibrate.js new file mode 100644 index 000000000..5646953df --- /dev/null +++ b/build/src/browser/client-scripts/calibrate.js @@ -0,0 +1,70 @@ +(function (window) { + "use strict"; + + // HACK: ie8 does not need to reset the body border, + // while any other browser does. + // This hack is obsolete in standards mode, but + // calibration script is executed on about:blank + // which is in quirks mode. + // Needs to find a proper way to open calibration + // page in standards mode. + function needsResetBorder() { + return !/MSIE 8\.0/.test(navigator.userAgent); + } + + function resetZoom() { + var meta = document.createElement("meta"); + meta.name = "viewport"; + meta.content = "width=device-width,initial-scale=1.0,user-scalable=no"; + document.getElementsByTagName("head")[0].appendChild(meta); + } + + function createPattern() { + var bodyStyle = document.body.style; + bodyStyle.margin = 0; + bodyStyle.padding = 0; + + if (needsResetBorder()) { + bodyStyle.border = 0; + } + + bodyStyle.backgroundColor = "#96fa00"; + } + + function hasCSS3Selectors() { + try { + document.querySelector("body:nth-child(1)"); + } catch (e) { + return false; + } + return true; + } + + function needsCompatLib() { + return !hasCSS3Selectors() || !window.getComputedStyle || !window.matchMedia || !String.prototype.trim; + } + + // In safari `window.innerWidth` always returns default 980px and and even viewport meta tag setting does not change it. + // https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/UsingtheViewport/UsingtheViewport.html + function getInnerWidth() { + var isSafari = /Safari/.test(navigator.userAgent); + + return isSafari + ? document.documentElement.clientWidth || document.body.clientWidth + : window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; + } + + function getBrowserFeatures() { + var features = { + needsCompatLib: needsCompatLib(), + pixelRatio: window.devicePixelRatio, + innerWidth: getInnerWidth() + }; + + return features; + } + + resetZoom(); + createPattern(); + return getBrowserFeatures(); +})(window); diff --git a/build/src/browser/client-scripts/ignore-areas.deprecated.js b/build/src/browser/client-scripts/ignore-areas.deprecated.js new file mode 100644 index 000000000..96ad827d4 --- /dev/null +++ b/build/src/browser/client-scripts/ignore-areas.deprecated.js @@ -0,0 +1,7 @@ +"use strict"; + +var lib = require("./lib"); + +module.exports = function queryIgnoreAreas(selector) { + return typeof selector === "string" ? [lib.queryFirst(selector)] : lib.queryAll(selector.every); +}; diff --git a/build/src/browser/client-scripts/ignore-areas.js b/build/src/browser/client-scripts/ignore-areas.js new file mode 100644 index 000000000..ac2db1755 --- /dev/null +++ b/build/src/browser/client-scripts/ignore-areas.js @@ -0,0 +1,7 @@ +"use strict"; + +var lib = require("./lib"); + +module.exports = function queryIgnoreAreas(selector) { + return lib.queryAll(selector); +}; diff --git a/build/src/browser/client-scripts/index.js b/build/src/browser/client-scripts/index.js new file mode 100644 index 000000000..4106d69d2 --- /dev/null +++ b/build/src/browser/client-scripts/index.js @@ -0,0 +1,403 @@ +/*jshint browserify:true*/ +"use strict"; + +var util = require("./util"), + rect = require("./rect"), + lib = require("./lib"), + queryIgnoreAreas = require("./ignore-areas"), + Rect = rect.Rect; + +if (typeof window === "undefined") { + global.__geminiCore = exports; +} else { + window.__geminiCore = exports; +} + +exports.queryFirst = lib.queryFirst; + +// Terminology +// - clientRect - the result of calling getBoundingClientRect of the element +// - extRect - clientRect + outline + box shadow +// - elementCaptureRect - sum of extRects of the element and its pseudo-elements +// - captureRect - sum of all elementCaptureRect for each captureSelectors + +exports.prepareScreenshot = function prepareScreenshot(areas, opts) { + opts = opts || {}; + try { + return prepareScreenshotUnsafe(areas, opts); + } catch (e) { + return { + error: "JS", + message: e.stack || e.message + }; + } +}; + +exports.disableFrameAnimations = function disableFrameAnimations() { + try { + return disableFrameAnimationsUnsafe(); + } catch (e) { + return { + error: "JS", + message: e.stack || e.message + }; + } +}; + +exports.cleanupFrameAnimations = function cleanupFrameAnimations() { + if (window.__cleanupAnimation) { + window.__cleanupAnimation(); + } +}; + +function prepareScreenshotUnsafe(areas, opts) { + var allowViewportOverflow = opts.allowViewportOverflow; + var captureElementFromTop = opts.captureElementFromTop; + var disableAnimation = opts.disableAnimation; + var scrollElem = window; + + if (opts.selectorToScroll) { + scrollElem = document.querySelector(opts.selectorToScroll); + + if (!scrollElem) { + return { + error: "NOTFOUND", + message: + 'Could not find element with css selector specified in "selectorToScroll" option: ' + + opts.selectorToScroll, + selector: opts.selectorToScroll + }; + } + } + + var viewportWidth = document.documentElement.clientWidth, + viewportHeight = document.documentElement.clientHeight, + documentWidth = document.documentElement.scrollWidth, + documentHeight = document.documentElement.scrollHeight, + viewPort = new Rect({ + left: util.getScrollLeft(scrollElem), + top: util.getScrollTop(scrollElem), + width: viewportWidth, + height: viewportHeight + }), + pixelRatio = configurePixelRatio(opts.usePixelRatio), + rect, + selectors = []; + + areas.forEach(function (area) { + if (Rect.isRect(area)) { + rect = rect ? rect.merge(new Rect(area)) : new Rect(area); + } else { + selectors.push(area); + } + }); + + rect = getCaptureRect(selectors, { + initialRect: rect, + allowViewportOverflow: allowViewportOverflow, + scrollElem: scrollElem, + viewportWidth: viewportWidth, + documentHeight: documentHeight + }); + + if (rect.error) { + return rect; + } + + if (captureElementFromTop && !viewPort.rectInside(rect)) { + util.isSafariMobile() + ? scrollToCaptureAreaInSafari(viewPort, rect, scrollElem) + : scrollElem.scrollTo(rect.left, rect.top); + } else if (allowViewportOverflow && viewPort.rectIntersects(rect)) { + rect.overflowsTopBound(viewPort) && rect.recalculateHeight(viewPort); + rect.overflowsLeftBound(viewPort) && rect.recalculateWidth(viewPort); + } else if (!captureElementFromTop && !viewPort.rectIntersects(rect)) { + return { + error: "OUTSIDE_OF_VIEWPORT", + message: + "Can not capture element, because it is outside of viewport. " + + 'Try to set "captureElementFromTop=true" to scroll to it before capture.' + }; + } + + if (disableAnimation) { + disableFrameAnimationsUnsafe(); + } + + return { + captureArea: rect.scale(pixelRatio).serialize(), + ignoreAreas: findIgnoreAreas(opts.ignoreSelectors, { + scrollElem: scrollElem, + pixelRatio: pixelRatio, + viewportWidth: viewportWidth, + documentHeight: documentHeight + }), + viewport: new Rect({ + left: util.getScrollLeft(scrollElem), + top: util.getScrollTop(scrollElem), + width: viewportWidth, + height: viewportHeight + }) + .scale(pixelRatio) + .serialize(), + documentHeight: Math.ceil(documentHeight * pixelRatio), + documentWidth: Math.ceil(documentWidth * pixelRatio), + canHaveCaret: isEditable(document.activeElement), + pixelRatio: pixelRatio + }; +} + +function disableFrameAnimationsUnsafe() { + var everyElementSelector = "*:not(#hermione-q.hermione-w.hermione-e.hermione-r.hermione-t.hermione-y)"; + var everythingSelector = ["", "::before", "::after"] + .map(function (pseudo) { + return everyElementSelector + pseudo; + }) + .join(", "); + + var styleElements = []; + + util.forEachRoot(function (root) { + var styleElement = document.createElement("style"); + styleElement.innerHTML = + everythingSelector + + [ + "{", + " animation-delay: 0ms !important;", + " animation-duration: 0ms !important;", + " animation-timing-function: step-start !important;", + " transition-timing-function: step-start !important;", + " scroll-behavior: auto !important;", + "}" + ].join("\n"); + + root.appendChild(styleElement); + styleElements.push(styleElement); + }); + + window.__cleanupAnimation = function () { + for (var i = 0; i < styleElements.length; i++) { + // IE11 doesn't have remove() on node + styleElements[i].parentNode.removeChild(styleElements[i]); + } + + delete window.__cleanupAnimation; + }; +} + +exports.resetZoom = function () { + var meta = lib.queryFirst('meta[name="viewport"]'); + if (!meta) { + meta = document.createElement("meta"); + meta.name = "viewport"; + var head = lib.queryFirst("head"); + head && head.appendChild(meta); + } + meta.content = "width=device-width,initial-scale=1.0,user-scalable=no"; +}; + +function getCaptureRect(selectors, opts) { + var element, + elementRect, + rect = opts.initialRect; + for (var i = 0; i < selectors.length; i++) { + element = lib.queryFirst(selectors[i]); + if (!element) { + return { + error: "NOTFOUND", + message: "Could not find element with css selector specified in setCaptureElements: " + selectors[i], + selector: selectors[i] + }; + } + + elementRect = getElementCaptureRect(element, opts); + if (elementRect) { + rect = rect ? rect.merge(elementRect) : elementRect; + } + } + + return rect + ? rect.round() + : { + error: "HIDDEN", + message: "Area with css selector : " + selectors + " is hidden", + selector: selectors + }; +} + +function configurePixelRatio(usePixelRatio) { + if (usePixelRatio === false) { + return 1; + } + + if (window.devicePixelRatio) { + return window.devicePixelRatio; + } + + // for ie6-ie10 (https://developer.mozilla.org/ru/docs/Web/API/Window/devicePixelRatio) + return window.screen.deviceXDPI / window.screen.logicalXDPI || 1; +} + +function findIgnoreAreas(selectors, opts) { + var result = []; + util.each(selectors, function (selector) { + var elements = queryIgnoreAreas(selector); + + util.each(elements, function (elem) { + return addIgnoreArea.call(result, elem, opts); + }); + }); + + return result; +} + +function addIgnoreArea(element, opts) { + var rect = element && getElementCaptureRect(element, opts); + + if (!rect) { + return; + } + + var ignoreArea = rect.round().scale(opts.pixelRatio).serialize(); + + this.push(ignoreArea); +} + +function isHidden(css, clientRect) { + return ( + css.display === "none" || + css.visibility === "hidden" || + css.opacity < 0.0001 || + clientRect.width < 0.0001 || + clientRect.height < 0.0001 + ); +} + +function getElementCaptureRect(element, opts) { + var pseudo = [":before", ":after"], + css = lib.getComputedStyle(element), + clientRect = rect.getAbsoluteClientRect(element, opts); + + if (isHidden(css, clientRect)) { + return null; + } + + var elementRect = getExtRect(css, clientRect, opts.allowViewportOverflow); + + util.each(pseudo, function (pseudoEl) { + css = lib.getComputedStyle(element, pseudoEl); + elementRect = elementRect.merge(getExtRect(css, clientRect, opts.allowViewportOverflow)); + }); + + return elementRect; +} + +function getExtRect(css, clientRect, allowViewportOverflow) { + var shadows = parseBoxShadow(css.boxShadow), + outline = parseInt(css.outlineWidth, 10); + + if (isNaN(outline)) { + outline = 0; + } + + return adjustRect(clientRect, shadows, outline, allowViewportOverflow); +} + +function parseBoxShadow(value) { + value = value || ""; + var regex = /[-+]?\d*\.?\d+px/g, + values = value.split(","), + results = [], + match; + + util.each(values, function (value) { + if ((match = value.match(regex))) { + results.push({ + offsetX: parseFloat(match[0]), + offsetY: parseFloat(match[1]) || 0, + blurRadius: parseFloat(match[2]) || 0, + spreadRadius: parseFloat(match[3]) || 0, + inset: value.indexOf("inset") !== -1 + }); + } + }); + return results; +} + +function adjustRect(rect, shadows, outline, allowViewportOverflow) { + var shadowRect = calculateShadowRect(rect, shadows, allowViewportOverflow), + outlineRect = calculateOutlineRect(rect, outline, allowViewportOverflow); + return shadowRect.merge(outlineRect); +} + +function calculateOutlineRect(rect, outline, allowViewportOverflow) { + var top = rect.top - outline, + left = rect.left - outline; + + return new Rect({ + top: allowViewportOverflow ? top : Math.max(0, top), + left: allowViewportOverflow ? left : Math.max(0, left), + bottom: rect.bottom + outline, + right: rect.right + outline + }); +} + +function calculateShadowRect(rect, shadows, allowViewportOverflow) { + var extent = calculateShadowExtent(shadows), + left = rect.left + extent.left, + top = rect.top + extent.top; + + return new Rect({ + left: allowViewportOverflow ? left : Math.max(0, left), + top: allowViewportOverflow ? top : Math.max(0, top), + width: rect.width - extent.left + extent.right, + height: rect.height - extent.top + extent.bottom + }); +} + +function calculateShadowExtent(shadows) { + var result = { top: 0, left: 0, right: 0, bottom: 0 }; + + util.each(shadows, function (shadow) { + if (shadow.inset) { + //skip inset shadows + return; + } + + var blurAndSpread = shadow.spreadRadius + shadow.blurRadius; + result.left = Math.min(shadow.offsetX - blurAndSpread, result.left); + result.right = Math.max(shadow.offsetX + blurAndSpread, result.right); + result.top = Math.min(shadow.offsetY - blurAndSpread, result.top); + result.bottom = Math.max(shadow.offsetY + blurAndSpread, result.bottom); + }); + return result; +} + +function isEditable(element) { + if (!element) { + return false; + } + return /^(input|textarea)$/i.test(element.tagName) || element.isContentEditable; +} + +function scrollToCaptureAreaInSafari(viewportCurr, captureArea, scrollElem) { + var documentHeight = Math.round(document.documentElement.scrollHeight); + var viewportHeight = Math.round(document.documentElement.clientHeight); + var maxScrollByY = documentHeight - viewportHeight; + + scrollElem.scrollTo(viewportCurr.left, Math.min(captureArea.top, maxScrollByY)); + + // TODO: uncomment after fix bug in safari - https://bugs.webkit.org/show_bug.cgi?id=179735 + /* + var viewportAfterScroll = new Rect({ + left: util.getScrollLeft(scrollElem), + top: util.getScrollTop(scrollElem), + width: viewportCurr.width, + height: viewportCurr.height + }); + + if (!viewportAfterScroll.rectInside(captureArea)) { + scrollElem.scrollTo(captureArea.left, captureArea.top); + } + */ +} diff --git a/build/src/browser/client-scripts/lib.compat.js b/build/src/browser/client-scripts/lib.compat.js new file mode 100644 index 000000000..4e39a4f68 --- /dev/null +++ b/build/src/browser/client-scripts/lib.compat.js @@ -0,0 +1,28 @@ +"use strict"; +/*jshint newcap:false*/ +var Sizzle = require("sizzle"); +var xpath = require("./xpath"); + +exports.queryFirst = function (selector) { + if (xpath.isXpathSelector(selector)) { + return xpath.queryFirst(selector); + } + var elems = Sizzle(exports.trim(selector) + ":first"); + return elems.length > 0 ? elems[0] : null; +}; + +exports.queryAll = function (selector) { + if (xpath.isXpathSelector(selector)) { + return xpath.queryAll(selector); + } + return Sizzle(selector); +}; + +exports.trim = function (str) { + // trim spaces, unicode BOM and NBSP and the beginning and the end of the line + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill + return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ""); +}; + +exports.getComputedStyle = require("./polyfills/getComputedStyle").getComputedStyle; +exports.matchMedia = require("./polyfills/matchMedia").matchMedia; diff --git a/build/src/browser/client-scripts/lib.native.js b/build/src/browser/client-scripts/lib.native.js new file mode 100644 index 000000000..c070d8c07 --- /dev/null +++ b/build/src/browser/client-scripts/lib.native.js @@ -0,0 +1,28 @@ +"use strict"; +var xpath = require("./xpath"); + +exports.queryFirst = function (selector) { + if (xpath.isXpathSelector(selector)) { + return xpath.queryFirst(selector); + } + return document.querySelector(selector); +}; + +exports.queryAll = function (selector) { + if (xpath.isXpathSelector(selector)) { + return xpath.queryAll(selector); + } + return document.querySelectorAll(selector); +}; + +exports.getComputedStyle = function (element, pseudoElement) { + return getComputedStyle(element, pseudoElement); +}; + +exports.matchMedia = function (mediaQuery) { + return matchMedia(mediaQuery); +}; + +exports.trim = function (str) { + return str.trim(); +}; diff --git a/build/src/browser/client-scripts/rect.js b/build/src/browser/client-scripts/rect.js new file mode 100644 index 000000000..9f235fba1 --- /dev/null +++ b/build/src/browser/client-scripts/rect.js @@ -0,0 +1,166 @@ +"use strict"; + +var util = require("./util"); + +function Rect(data) { + this.top = data.top; + this.left = data.left; + + if ("width" in data && "height" in data) { + this.width = data.width; + this.height = data.height; + this.bottom = data.bottom || this.top + this.height; + this.right = data.right || this.left + this.width; + } else if ("bottom" in data && "right" in data) { + this.bottom = data.bottom; + this.right = data.right; + this.width = data.right - Math.max(0, data.left); + this.height = data.bottom - Math.max(0, data.top); + } else { + throw new Error("Not enough data for the rect construction"); + } +} + +Rect.isRect = function (data) { + if (typeof data !== "object" || data === null || Array.isArray(data)) { + return false; + } + + return ( + "left" in data && + "top" in data && + (("width" in data && "height" in data) || ("right" in data && "bottom" in data)) + ); +}; + +Rect.prototype = { + constructor: Rect, + merge: function (otherRect) { + return new Rect({ + left: Math.min(this.left, otherRect.left), + top: Math.min(this.top, otherRect.top), + bottom: Math.max(this.bottom, otherRect.bottom), + right: Math.max(this.right, otherRect.right) + }); + }, + + translate: function (x, y) { + return new Rect({ + left: this.left + x, + top: this.top + y, + width: this.width, + height: this.height + }); + }, + + pointInside: function (x, y) { + return x >= this.left && x <= this.right && y >= this.top && y <= this.bottom; + }, + + rectInside: function (rect) { + return util.every( + rect._keyPoints(), + function (point) { + return this.pointInside(point[0], point[1]); + }, + this + ); + }, + + rectIntersects: function (other) { + var isOtherOutside = + other.right <= this.left || + other.bottom <= this.top || + other.left >= this.right || + other.top >= this.bottom; + + return !isOtherOutside; + }, + + round: function () { + return new Rect({ + top: Math.floor(this.top), + left: Math.floor(this.left), + right: Math.ceil(this.right), + bottom: Math.ceil(this.bottom) + }); + }, + + scale: function (scaleFactor) { + var rect = new Rect({ + top: this.top * scaleFactor, + left: this.left * scaleFactor, + right: this.right * scaleFactor, + bottom: this.bottom * scaleFactor + }); + + return util.isInteger(scaleFactor) ? rect : rect.round(); + }, + + serialize: function () { + return { + left: this.left, + top: this.top, + width: this.width, + height: this.height + }; + }, + + overflowsTopBound: function (rect) { + return this._overflowsBound(rect, "top"); + }, + + overflowsLeftBound: function (rect) { + return this._overflowsBound(rect, "left"); + }, + + /** @type Function */ + recalculateHeight: function (rect) { + this.height = this.height - (rect.top - Math.max(0, this.top)); + }, + + /** @type Function */ + recalculateWidth: function (rect) { + this.width = this.width - (rect.left - Math.max(0, this.left)); + }, + + _overflowsBound: function (rect, prop) { + return Math.max(0, this[prop]) < rect[prop]; + }, + + _anyPointInside: function (points) { + return util.some( + points, + function (point) { + return this.pointInside(point[0], point[1]); + }, + this + ); + }, + + _keyPoints: function () { + return [ + [this.left, this.top], + [this.left, this.bottom], + [this.right, this.top], + [this.right, this.bottom] + ]; + } +}; + +exports.Rect = Rect; +exports.getAbsoluteClientRect = function getAbsoluteClientRect(element, opts) { + var coords = element.getBoundingClientRect(); + var widthRatio = coords.width % opts.viewportWidth; + var heightRatio = coords.height % opts.documentHeight; + + var clientRect = new Rect({ + left: coords.left, + top: coords.top, + // to correctly calculate "width" and "height" in devices with fractional pixelRatio + width: widthRatio > 0 && widthRatio < 1 ? opts.viewportWidth : coords.width, + height: heightRatio > 0 && heightRatio < 1 ? opts.documentHeight : coords.height + }); + + return clientRect.translate(util.getScrollLeft(opts.scrollElem), util.getScrollTop(opts.scrollElem)); +}; diff --git a/build/src/browser/client-scripts/util.js b/build/src/browser/client-scripts/util.js new file mode 100644 index 000000000..e6438101a --- /dev/null +++ b/build/src/browser/client-scripts/util.js @@ -0,0 +1,107 @@ +"use strict"; + +var SCROLL_DIR_NAME = { + top: "scrollTop", + left: "scrollLeft" +}; + +var PAGE_OFFSET_NAME = { + x: "pageXOffset", + y: "pageYOffset" +}; + +exports.each = arrayUtil(Array.prototype.forEach, myForEach); +exports.some = arrayUtil(Array.prototype.some, mySome); +exports.every = arrayUtil(Array.prototype.every, myEvery); + +function arrayUtil(nativeFunc, shimFunc) { + return nativeFunc ? contextify(nativeFunc) : shimFunc; +} + +/** + * Makes function f to accept context as a + * first argument + */ +function contextify(f) { + return function (ctx) { + var rest = Array.prototype.slice.call(arguments, 1); + return f.apply(ctx, rest); + }; +} + +function myForEach(array, cb, context) { + for (var i = 0; i < array.length; i++) { + cb.call(context, array[i], i, array); + } +} + +function mySome(array, cb, context) { + for (var i = 0; i < array.length; i++) { + if (cb.call(context, array[i], i, array)) { + return true; + } + } + return false; +} + +function myEvery(array, cb, context) { + for (var i = 0; i < array.length; i++) { + if (!cb.call(context, array[i], i, array)) { + return false; + } + } + return true; +} + +function getScroll(scrollElem, direction, coord) { + var scrollDir = SCROLL_DIR_NAME[direction]; + var pageOffset = PAGE_OFFSET_NAME[coord]; + + if (scrollElem && scrollElem !== window) { + return scrollElem[scrollDir]; + } + + if (typeof window[pageOffset] !== "undefined") { + return window[pageOffset]; + } + + return document.documentElement[scrollDir]; +} + +exports.getScrollTop = function (scrollElem) { + return getScroll(scrollElem, "top", "y"); +}; + +exports.getScrollLeft = function (scrollElem) { + return getScroll(scrollElem, "left", "x"); +}; + +exports.isSafariMobile = function () { + return ( + navigator && + typeof navigator.vendor === "string" && + navigator.vendor.match(/apple/i) && + /(iPhone|iPad).*AppleWebKit.*Safari/i.test(navigator.userAgent) + ); +}; + +exports.isInteger = function (num) { + return num % 1 === 0; +}; + +exports.forEachRoot = function (cb) { + function traverseRoots(root) { + cb(root); + + // In IE 11, we need to pass the third and fourth arguments + var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, null, false); + + for (var node = treeWalker.currentNode; node !== null; node = treeWalker.nextNode()) { + if (node instanceof Element && node.shadowRoot) { + traverseRoots(node.shadowRoot); + } + } + } + + traverseRoots(document.documentElement); +}; diff --git a/build/src/browser/client-scripts/xpath.js b/build/src/browser/client-scripts/xpath.js new file mode 100644 index 000000000..b88ce31f5 --- /dev/null +++ b/build/src/browser/client-scripts/xpath.js @@ -0,0 +1,31 @@ +"use strict"; + +var XPATH_SELECTORS_START = ["/", "(", "../", "./", "*/"]; + +function isXpathSelector(selector) { + return XPATH_SELECTORS_START.some(function (startString) { + return selector.indexOf(startString) === 0; + }); +} + +function queryFirst(selector) { + return document.evaluate(selector, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; +} + +function queryAll(selector) { + var elements = document.evaluate(selector, document, null, XPathResult.ANY_TYPE, null); + var node, + nodes = []; + node = elements.iterateNext(); + while (node) { + nodes.push(node); + node = elements.iterateNext(); + } + return nodes; +} + +module.exports = { + isXpathSelector: isXpathSelector, + queryFirst: queryFirst, + queryAll: queryAll +}; diff --git a/build/src/browser/commands/assert-view/assert-view-results.d.ts b/build/src/browser/commands/assert-view/assert-view-results.d.ts new file mode 100644 index 000000000..192f51f8d --- /dev/null +++ b/build/src/browser/commands/assert-view/assert-view-results.d.ts @@ -0,0 +1,12 @@ +export = AssertViewResults; +declare class AssertViewResults { + static fromRawObject(results: any): import("./assert-view-results"); + static create(results: any): import("./assert-view-results"); + constructor(results: any); + _results: any; + add(data: any): void; + hasFails(): any; + hasState(stateName: any): any; + toRawObject(): any; + get(): any; +} diff --git a/build/src/browser/commands/assert-view/assert-view-results.js b/build/src/browser/commands/assert-view/assert-view-results.js new file mode 100644 index 000000000..3bf4c0cd3 --- /dev/null +++ b/build/src/browser/commands/assert-view/assert-view-results.js @@ -0,0 +1,34 @@ +"use strict"; +const { ImageDiffError } = require("./errors/image-diff-error"); +const { NoRefImageError } = require("./errors/no-ref-image-error"); +module.exports = class AssertViewResults { + static fromRawObject(results) { + return AssertViewResults.create(results.map(res => { + return ((res.name === ImageDiffError.name && ImageDiffError.fromObject(res)) || + (res.name === NoRefImageError.name && NoRefImageError.fromObject(res)) || + res); + })); + } + static create(results) { + return new AssertViewResults(results); + } + constructor(results) { + this._results = results || []; + } + add(data) { + this._results.push(data); + } + hasFails() { + return this._results.some(res => res instanceof Error); + } + hasState(stateName) { + return this._results.some(res => res.stateName === stateName); + } + toRawObject() { + return this._results.map(res => ({ ...res })); + } + get() { + return this._results; + } +}; +//# sourceMappingURL=assert-view-results.js.map \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/assert-view-results.js.map b/build/src/browser/commands/assert-view/assert-view-results.js.map new file mode 100644 index 000000000..37e43855c --- /dev/null +++ b/build/src/browser/commands/assert-view/assert-view-results.js.map @@ -0,0 +1 @@ +{"version":3,"file":"assert-view-results.js","sourceRoot":"","sources":["../../../../../src/browser/commands/assert-view/assert-view-results.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;AAChE,MAAM,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAAC;AAEnE,MAAM,CAAC,OAAO,GAAG,MAAM,iBAAiB;IACpC,MAAM,CAAC,aAAa,CAAC,OAAO;QACxB,OAAO,iBAAiB,CAAC,MAAM,CAC3B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;YACd,OAAO,CACH,CAAC,GAAG,CAAC,IAAI,KAAK,cAAc,CAAC,IAAI,IAAI,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;gBACpE,CAAC,GAAG,CAAC,IAAI,KAAK,eAAe,CAAC,IAAI,IAAI,eAAe,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;gBACtE,GAAG,CACN,CAAC;QACN,CAAC,CAAC,CACL,CAAC;IACN,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,OAAO;QACjB,OAAO,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,YAAY,OAAO;QACf,IAAI,CAAC,QAAQ,GAAG,OAAO,IAAI,EAAE,CAAC;IAClC,CAAC;IAED,GAAG,CAAC,IAAI;QACJ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,QAAQ;QACJ,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC;IAC3D,CAAC;IAED,QAAQ,CAAC,SAAS;QACd,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;IAClE,CAAC;IAED,WAAW;QACP,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,GAAG;QACC,OAAO,IAAI,CAAC,QAAQ,CAAC;IACzB,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/capture-processors/assert-refs.d.ts b/build/src/browser/commands/assert-view/capture-processors/assert-refs.d.ts new file mode 100644 index 000000000..7a4940ecb --- /dev/null +++ b/build/src/browser/commands/assert-view/capture-processors/assert-refs.d.ts @@ -0,0 +1,3 @@ +export function handleNoRefImage(currImg: any, refImg: any, state: any): Promise; +export function handleImageDiff(currImg: any, refImg: any, state: any, opts: any): Promise; +import Promise = require("bluebird"); diff --git a/build/src/browser/commands/assert-view/capture-processors/assert-refs.js b/build/src/browser/commands/assert-view/capture-processors/assert-refs.js new file mode 100644 index 000000000..298aa36f0 --- /dev/null +++ b/build/src/browser/commands/assert-view/capture-processors/assert-refs.js @@ -0,0 +1,22 @@ +"use strict"; +const Promise = require("bluebird"); +const { ImageDiffError } = require("../errors/image-diff-error"); +const { NoRefImageError } = require("../errors/no-ref-image-error"); +exports.handleNoRefImage = (currImg, refImg, state) => { + return Promise.reject(NoRefImageError.create(state, currImg, refImg)); +}; +exports.handleImageDiff = (currImg, refImg, state, opts) => { + const { tolerance, antialiasingTolerance, canHaveCaret, diffAreas, config, diffBuffer } = opts; + const { buildDiffOpts, system: { diffColor }, } = config; + buildDiffOpts.ignoreCaret = buildDiffOpts.ignoreCaret && canHaveCaret; + const diffOpts = { + current: currImg.path, + reference: refImg.path, + diffColor, + tolerance, + antialiasingTolerance, + ...buildDiffOpts, + }; + return Promise.reject(ImageDiffError.create(state, currImg, refImg, diffOpts, diffAreas, diffBuffer)); +}; +//# sourceMappingURL=assert-refs.js.map \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/capture-processors/assert-refs.js.map b/build/src/browser/commands/assert-view/capture-processors/assert-refs.js.map new file mode 100644 index 000000000..24710a353 --- /dev/null +++ b/build/src/browser/commands/assert-view/capture-processors/assert-refs.js.map @@ -0,0 +1 @@ +{"version":3,"file":"assert-refs.js","sourceRoot":"","sources":["../../../../../../src/browser/commands/assert-view/capture-processors/assert-refs.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACpC,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;AACjE,MAAM,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAAC;AAEpE,OAAO,CAAC,gBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;IAClD,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AAC1E,CAAC,CAAC;AAEF,OAAO,CAAC,eAAe,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IACvD,MAAM,EAAE,SAAS,EAAE,qBAAqB,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IAC/F,MAAM,EACF,aAAa,EACb,MAAM,EAAE,EAAE,SAAS,EAAE,GACxB,GAAG,MAAM,CAAC;IACX,aAAa,CAAC,WAAW,GAAG,aAAa,CAAC,WAAW,IAAI,YAAY,CAAC;IAEtE,MAAM,QAAQ,GAAG;QACb,OAAO,EAAE,OAAO,CAAC,IAAI;QACrB,SAAS,EAAE,MAAM,CAAC,IAAI;QACtB,SAAS;QACT,SAAS;QACT,qBAAqB;QACrB,GAAG,aAAa;KACnB,CAAC;IAEF,OAAO,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;AAC1G,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/capture-processors/index.d.ts b/build/src/browser/commands/assert-view/capture-processors/index.d.ts new file mode 100644 index 000000000..fae575d31 --- /dev/null +++ b/build/src/browser/commands/assert-view/capture-processors/index.d.ts @@ -0,0 +1,2 @@ +export function getCaptureProcessors(): typeof updateRefs; +import updateRefs = require("./update-refs"); diff --git a/build/src/browser/commands/assert-view/capture-processors/index.js b/build/src/browser/commands/assert-view/capture-processors/index.js new file mode 100644 index 000000000..9d48990db --- /dev/null +++ b/build/src/browser/commands/assert-view/capture-processors/index.js @@ -0,0 +1,6 @@ +"use strict"; +const RuntimeConfig = require("../../../../config/runtime-config"); +const assertRefs = require("./assert-refs"); +const updateRefs = require("./update-refs"); +exports.getCaptureProcessors = () => (RuntimeConfig.getInstance().updateRefs ? updateRefs : assertRefs); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/capture-processors/index.js.map b/build/src/browser/commands/assert-view/capture-processors/index.js.map new file mode 100644 index 000000000..c94db45e8 --- /dev/null +++ b/build/src/browser/commands/assert-view/capture-processors/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/browser/commands/assert-view/capture-processors/index.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,aAAa,GAAG,OAAO,CAAC,mCAAmC,CAAC,CAAC;AAEnE,MAAM,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;AAC5C,MAAM,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;AAE5C,OAAO,CAAC,oBAAoB,GAAG,GAAG,EAAE,CAAC,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/capture-processors/update-refs.d.ts b/build/src/browser/commands/assert-view/capture-processors/update-refs.d.ts new file mode 100644 index 000000000..06b9940f7 --- /dev/null +++ b/build/src/browser/commands/assert-view/capture-processors/update-refs.d.ts @@ -0,0 +1,6 @@ +export function handleNoRefImage(currImg: any, refImg: any, state: any, { emitter }: { + emitter: any; +}): Promise; +export function handleImageDiff(currImg: any, refImg: any, state: any, { emitter }: { + emitter: any; +}): Promise; diff --git a/build/src/browser/commands/assert-view/capture-processors/update-refs.js b/build/src/browser/commands/assert-view/capture-processors/update-refs.js new file mode 100644 index 000000000..720d487e5 --- /dev/null +++ b/build/src/browser/commands/assert-view/capture-processors/update-refs.js @@ -0,0 +1,8 @@ +"use strict"; +const fs = require("fs-extra"); +const { WorkerEvents } = require("../../../../events"); +exports.handleNoRefImage = exports.handleImageDiff = async (currImg, refImg, state, { emitter }) => { + await fs.copy(currImg.path, refImg.path); + emitter.emit(WorkerEvents.UPDATE_REFERENCE, { state, refImg }); +}; +//# sourceMappingURL=update-refs.js.map \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/capture-processors/update-refs.js.map b/build/src/browser/commands/assert-view/capture-processors/update-refs.js.map new file mode 100644 index 000000000..52afeeec5 --- /dev/null +++ b/build/src/browser/commands/assert-view/capture-processors/update-refs.js.map @@ -0,0 +1 @@ +{"version":3,"file":"update-refs.js","sourceRoot":"","sources":["../../../../../../src/browser/commands/assert-view/capture-processors/update-refs.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAC/B,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAEvD,OAAO,CAAC,gBAAgB,GAAG,OAAO,CAAC,eAAe,GAAG,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;IAC/F,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;AACnE,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/errors/assert-view-error.d.ts b/build/src/browser/commands/assert-view/errors/assert-view-error.d.ts new file mode 100644 index 000000000..a504753ca --- /dev/null +++ b/build/src/browser/commands/assert-view/errors/assert-view-error.d.ts @@ -0,0 +1,4 @@ +export declare class AssertViewError extends Error { + message: string; + constructor(message?: string); +} diff --git a/build/src/browser/commands/assert-view/errors/assert-view-error.js b/build/src/browser/commands/assert-view/errors/assert-view-error.js new file mode 100644 index 000000000..c7047a8be --- /dev/null +++ b/build/src/browser/commands/assert-view/errors/assert-view-error.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.AssertViewError = void 0; +class AssertViewError extends Error { + constructor(message = "image comparison failed") { + super(); + this.message = message; + this.name = this.constructor.name; + } +} +exports.AssertViewError = AssertViewError; +//# sourceMappingURL=assert-view-error.js.map \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/errors/assert-view-error.js.map b/build/src/browser/commands/assert-view/errors/assert-view-error.js.map new file mode 100644 index 000000000..ea977efc5 --- /dev/null +++ b/build/src/browser/commands/assert-view/errors/assert-view-error.js.map @@ -0,0 +1 @@ +{"version":3,"file":"assert-view-error.js","sourceRoot":"","sources":["../../../../../../src/browser/commands/assert-view/errors/assert-view-error.ts"],"names":[],"mappings":";;;AAAA,MAAa,eAAgB,SAAQ,KAAK;IACtC,YAAmB,UAAkB,yBAAyB;QAC1D,KAAK,EAAE,CAAC;QADO,YAAO,GAAP,OAAO,CAAoC;QAG1D,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IACtC,CAAC;CACJ;AAND,0CAMC"} \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/errors/base-state-error.d.ts b/build/src/browser/commands/assert-view/errors/base-state-error.d.ts new file mode 100644 index 000000000..905031d0c --- /dev/null +++ b/build/src/browser/commands/assert-view/errors/base-state-error.d.ts @@ -0,0 +1,7 @@ +import { ImageInfo } from "../../../../types"; +export declare class BaseStateError extends Error { + stateName: string; + currImg: ImageInfo; + refImg: ImageInfo; + constructor(stateName: string, currImg: ImageInfo, refImg: ImageInfo); +} diff --git a/build/src/browser/commands/assert-view/errors/base-state-error.js b/build/src/browser/commands/assert-view/errors/base-state-error.js new file mode 100644 index 000000000..da7a5da3a --- /dev/null +++ b/build/src/browser/commands/assert-view/errors/base-state-error.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BaseStateError = void 0; +class BaseStateError extends Error { + constructor(stateName, currImg, refImg) { + super(); + this.stateName = stateName; + this.currImg = currImg; + this.refImg = refImg; + this.name = this.constructor.name; + } +} +exports.BaseStateError = BaseStateError; +//# sourceMappingURL=base-state-error.js.map \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/errors/base-state-error.js.map b/build/src/browser/commands/assert-view/errors/base-state-error.js.map new file mode 100644 index 000000000..c86d6aeae --- /dev/null +++ b/build/src/browser/commands/assert-view/errors/base-state-error.js.map @@ -0,0 +1 @@ +{"version":3,"file":"base-state-error.js","sourceRoot":"","sources":["../../../../../../src/browser/commands/assert-view/errors/base-state-error.ts"],"names":[],"mappings":";;;AAEA,MAAa,cAAe,SAAQ,KAAK;IACrC,YAAmB,SAAiB,EAAS,OAAkB,EAAS,MAAiB;QACrF,KAAK,EAAE,CAAC;QADO,cAAS,GAAT,SAAS,CAAQ;QAAS,YAAO,GAAP,OAAO,CAAW;QAAS,WAAM,GAAN,MAAM,CAAW;QAGrF,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IACtC,CAAC;CACJ;AAND,wCAMC"} \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/errors/image-diff-error.d.ts b/build/src/browser/commands/assert-view/errors/image-diff-error.d.ts new file mode 100644 index 000000000..c2de041f5 --- /dev/null +++ b/build/src/browser/commands/assert-view/errors/image-diff-error.d.ts @@ -0,0 +1,33 @@ +/// +import { ImageInfo } from "../../../../types"; +import { BaseStateError } from "./base-state-error"; +import type { LooksSameOptions, LooksSameResult } from "looks-same"; +interface DiffOptions extends LooksSameOptions { + /** Path to the current screenshot */ + current: string; + reference: string; + diffColor: string; +} +type DiffAreas = Pick; +type ImageDiffErrorConstructor = new (stateName: string, currImg: ImageInfo, refImg: ImageInfo, diffOpts: DiffOptions, diffAreas: DiffAreas, diffBuffer: Buffer) => T; +interface ImageDiffErrorData { + stateName: string; + currImg: ImageInfo; + refImg: ImageInfo; + diffOpts: DiffOptions; + diffBounds: LooksSameResult["diffBounds"]; + diffClusters: LooksSameResult["diffClusters"]; + diffBuffer: Buffer; +} +export declare class ImageDiffError extends BaseStateError { + message: string; + diffOpts: DiffOptions; + diffBounds?: DiffAreas["diffBounds"]; + diffClusters?: DiffAreas["diffClusters"]; + diffBuffer: Buffer; + static create(this: ImageDiffErrorConstructor, stateName: string, currImg: ImageInfo, refImg: ImageInfo, diffOpts: DiffOptions, diffAreas: DiffAreas | undefined, diffBuffer: Buffer): T; + static fromObject(this: ImageDiffErrorConstructor, data: ImageDiffErrorData): T; + constructor(stateName: string, currImg: ImageInfo, refImg: ImageInfo, diffOpts: DiffOptions, { diffBounds, diffClusters }: DiffAreas | undefined, diffBuffer: Buffer); + saveDiffTo(diffPath: string): Promise; +} +export {}; diff --git a/build/src/browser/commands/assert-view/errors/image-diff-error.js b/build/src/browser/commands/assert-view/errors/image-diff-error.js new file mode 100644 index 000000000..a87893372 --- /dev/null +++ b/build/src/browser/commands/assert-view/errors/image-diff-error.js @@ -0,0 +1,33 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ImageDiffError = void 0; +const image_1 = __importDefault(require("../../../../image")); +const base_state_error_1 = require("./base-state-error"); +class ImageDiffError extends base_state_error_1.BaseStateError { + static create(stateName, currImg, refImg, diffOpts, diffAreas = {}, diffBuffer) { + return new this(stateName, currImg, refImg, diffOpts, diffAreas, diffBuffer); + } + static fromObject(data) { + const { diffBounds, diffClusters } = data; + return new this(data.stateName, data.currImg, data.refImg, data.diffOpts, { + diffBounds, + diffClusters, + }, data.diffBuffer); + } + constructor(stateName, currImg, refImg, diffOpts, { diffBounds, diffClusters } = {}, diffBuffer) { + super(stateName, currImg, refImg); + this.message = `images are different for "${stateName}" state`; + this.diffOpts = diffOpts; + this.diffBounds = diffBounds; + this.diffClusters = diffClusters; + this.diffBuffer = diffBuffer; + } + saveDiffTo(diffPath) { + return image_1.default.buildDiff({ diff: diffPath, ...this.diffOpts }); + } +} +exports.ImageDiffError = ImageDiffError; +//# sourceMappingURL=image-diff-error.js.map \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/errors/image-diff-error.js.map b/build/src/browser/commands/assert-view/errors/image-diff-error.js.map new file mode 100644 index 000000000..4fb562438 --- /dev/null +++ b/build/src/browser/commands/assert-view/errors/image-diff-error.js.map @@ -0,0 +1 @@ +{"version":3,"file":"image-diff-error.js","sourceRoot":"","sources":["../../../../../../src/browser/commands/assert-view/errors/image-diff-error.ts"],"names":[],"mappings":";;;;;;AAEA,8DAAsC;AACtC,yDAAoD;AAgCpD,MAAa,cAAe,SAAQ,iCAAc;IAO9C,MAAM,CAAC,MAAM,CAET,SAAiB,EACjB,OAAkB,EAClB,MAAiB,EACjB,QAAqB,EACrB,YAAY,EAAe,EAC3B,UAAkB;QAElB,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,CAAC,UAAU,CAAwC,IAAwB;QAC7E,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;QAC1C,OAAO,IAAI,IAAI,CACX,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,QAAQ,EACb;YACI,UAAU;YACV,YAAY;SACf,EACD,IAAI,CAAC,UAAU,CAClB,CAAC;IACN,CAAC;IAED,YACI,SAAiB,EACjB,OAAkB,EAClB,MAAiB,EACjB,QAAqB,EACrB,EAAE,UAAU,EAAE,YAAY,KAAK,EAAe,EAC9C,UAAkB;QAElB,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAElC,IAAI,CAAC,OAAO,GAAG,6BAA6B,SAAS,SAAS,CAAC;QAC/D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IACjC,CAAC;IAED,UAAU,CAAC,QAAgB;QACvB,OAAO,eAAK,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjE,CAAC;CACJ;AAtDD,wCAsDC"} \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/errors/invalid-png-error.d.ts b/build/src/browser/commands/assert-view/errors/invalid-png-error.d.ts new file mode 100644 index 000000000..861da0071 --- /dev/null +++ b/build/src/browser/commands/assert-view/errors/invalid-png-error.d.ts @@ -0,0 +1,5 @@ +export = InvalidPngError; +declare class InvalidPngError extends Error { + constructor(message: any); + message: any; +} diff --git a/build/src/browser/commands/assert-view/errors/invalid-png-error.js b/build/src/browser/commands/assert-view/errors/invalid-png-error.js new file mode 100644 index 000000000..8e8d1b19e --- /dev/null +++ b/build/src/browser/commands/assert-view/errors/invalid-png-error.js @@ -0,0 +1,9 @@ +"use strict"; +module.exports = class InvalidPngError extends Error { + constructor(message) { + super(); + this.name = this.constructor.name; + this.message = message; + } +}; +//# sourceMappingURL=invalid-png-error.js.map \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/errors/invalid-png-error.js.map b/build/src/browser/commands/assert-view/errors/invalid-png-error.js.map new file mode 100644 index 000000000..398df7517 --- /dev/null +++ b/build/src/browser/commands/assert-view/errors/invalid-png-error.js.map @@ -0,0 +1 @@ +{"version":3,"file":"invalid-png-error.js","sourceRoot":"","sources":["../../../../../../src/browser/commands/assert-view/errors/invalid-png-error.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,OAAO,GAAG,MAAM,eAAgB,SAAQ,KAAK;IAChD,YAAY,OAAO;QACf,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/errors/no-ref-image-error.d.ts b/build/src/browser/commands/assert-view/errors/no-ref-image-error.d.ts new file mode 100644 index 000000000..f4c2e5850 --- /dev/null +++ b/build/src/browser/commands/assert-view/errors/no-ref-image-error.d.ts @@ -0,0 +1,14 @@ +import { BaseStateError } from "./base-state-error"; +import { ImageInfo } from "../../../../types"; +type NoRefImageErrorConstructor = new (stateName: string, currImg: ImageInfo, refImg: ImageInfo) => T; +interface NoRefImageErrorData { + stateName: string; + currImg: ImageInfo; + refImg: ImageInfo; +} +export declare class NoRefImageError extends BaseStateError { + static create(this: NoRefImageErrorConstructor, stateName: string, currImg: ImageInfo, refImg: ImageInfo): T; + static fromObject(this: NoRefImageErrorConstructor, data: NoRefImageErrorData): T; + constructor(stateName: string, currImg: ImageInfo, refImg: ImageInfo); +} +export {}; diff --git a/build/src/browser/commands/assert-view/errors/no-ref-image-error.js b/build/src/browser/commands/assert-view/errors/no-ref-image-error.js new file mode 100644 index 000000000..6cdd7d704 --- /dev/null +++ b/build/src/browser/commands/assert-view/errors/no-ref-image-error.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NoRefImageError = void 0; +const base_state_error_1 = require("./base-state-error"); +class NoRefImageError extends base_state_error_1.BaseStateError { + static create(stateName, currImg, refImg) { + return new this(stateName, currImg, refImg); + } + static fromObject(data) { + return new this(data.stateName, data.currImg, data.refImg); + } + constructor(stateName, currImg, refImg) { + super(stateName, currImg, refImg); + this.message = `can not find reference image at ${this.refImg.path} for "${stateName}" state`; + } +} +exports.NoRefImageError = NoRefImageError; +//# sourceMappingURL=no-ref-image-error.js.map \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/errors/no-ref-image-error.js.map b/build/src/browser/commands/assert-view/errors/no-ref-image-error.js.map new file mode 100644 index 000000000..d9b45c4c4 --- /dev/null +++ b/build/src/browser/commands/assert-view/errors/no-ref-image-error.js.map @@ -0,0 +1 @@ +{"version":3,"file":"no-ref-image-error.js","sourceRoot":"","sources":["../../../../../../src/browser/commands/assert-view/errors/no-ref-image-error.ts"],"names":[],"mappings":";;;AAAA,yDAAoD;AAWpD,MAAa,eAAgB,SAAQ,iCAAc;IAC/C,MAAM,CAAC,MAAM,CAET,SAAiB,EACjB,OAAkB,EAClB,MAAiB;QAEjB,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,CAAC,UAAU,CAAiE,IAAyB;QACvG,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC;IAED,YAAY,SAAiB,EAAE,OAAkB,EAAE,MAAiB;QAChE,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAElC,IAAI,CAAC,OAAO,GAAG,mCAAmC,IAAI,CAAC,MAAM,CAAC,IAAI,SAAS,SAAS,SAAS,CAAC;IAClG,CAAC;CACJ;AAnBD,0CAmBC"} \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/index.d.ts b/build/src/browser/commands/assert-view/index.d.ts new file mode 100644 index 000000000..6009cbe49 --- /dev/null +++ b/build/src/browser/commands/assert-view/index.d.ts @@ -0,0 +1,2 @@ +declare function _exports(browser: any): void; +export = _exports; diff --git a/build/src/browser/commands/assert-view/index.js b/build/src/browser/commands/assert-view/index.js new file mode 100644 index 000000000..c7229b32b --- /dev/null +++ b/build/src/browser/commands/assert-view/index.js @@ -0,0 +1,114 @@ +"use strict"; +const fs = require("fs-extra"); +const _ = require("lodash"); +const Promise = require("bluebird"); +const { pngValidator: validatePng } = require("png-validator"); +const Image = require("../../../image"); +const ScreenShooter = require("../../screen-shooter"); +const temp = require("../../../temp"); +const { getCaptureProcessors } = require("./capture-processors"); +const RuntimeConfig = require("../../../config/runtime-config"); +const AssertViewResults = require("./assert-view-results"); +const { BaseStateError } = require("./errors/base-state-error"); +const { AssertViewError } = require("./errors/assert-view-error"); +const InvalidPngError = require("./errors/invalid-png-error"); +module.exports = browser => { + const screenShooter = ScreenShooter.create(browser); + const { publicAPI: session, config } = browser; + const { assertViewOpts, compareOpts, compositeImage, screenshotDelay, tolerance, antialiasingTolerance, disableAnimation, } = config; + const { handleNoRefImage, handleImageDiff } = getCaptureProcessors(); + const assertView = async (state, selectors, opts) => { + opts = _.defaults(opts, assertViewOpts, { + compositeImage, + screenshotDelay, + tolerance, + antialiasingTolerance, + disableAnimation, + }); + const { hermioneCtx } = session.executionContext; + hermioneCtx.assertViewResults = hermioneCtx.assertViewResults || AssertViewResults.create(); + if (hermioneCtx.assertViewResults.hasState(state)) { + return Promise.reject(new AssertViewError(`duplicate name for "${state}" state`)); + } + const handleCaptureProcessorError = e => e instanceof BaseStateError ? hermioneCtx.assertViewResults.add(e) : Promise.reject(e); + const page = await browser.prepareScreenshot([].concat(selectors), { + ignoreSelectors: [].concat(opts.ignoreElements), + allowViewportOverflow: opts.allowViewportOverflow, + captureElementFromTop: opts.captureElementFromTop, + selectorToScroll: opts.selectorToScroll, + disableAnimation: opts.disableAnimation, + }); + const { tempOpts } = RuntimeConfig.getInstance(); + temp.attach(tempOpts); + const screenshoterOpts = _.pick(opts, [ + "allowViewportOverflow", + "compositeImage", + "screenshotDelay", + "selectorToScroll", + ]); + const currImgInst = await screenShooter + .capture(page, screenshoterOpts) + .finally(() => browser.cleanupScreenshot(opts)); + const currSize = await currImgInst.getSize(); + const currImg = { path: temp.path(Object.assign(tempOpts, { suffix: ".png" })), size: currSize }; + const test = session.executionContext.ctx.currentTest; + const refImg = { path: config.getScreenshotPath(test, state), size: null }; + const { emitter } = browser; + if (!fs.existsSync(refImg.path)) { + await currImgInst.save(currImg.path); + return handleNoRefImage(currImg, refImg, state, { emitter }).catch(e => handleCaptureProcessorError(e)); + } + const { canHaveCaret, pixelRatio } = page; + const imageCompareOpts = { + tolerance: opts.tolerance, + antialiasingTolerance: opts.antialiasingTolerance, + canHaveCaret, + pixelRatio, + compareOpts, + }; + const currBuffer = await currImgInst.toPngBuffer({ resolveWithObject: false }); + const refBuffer = await fs.readFile(refImg.path); + try { + validatePng(refBuffer); + } + catch (err) { + throw new InvalidPngError(`Reference image in ${refImg.path} is not a valid png`); + } + const { equal, diffBounds, diffClusters, diffImage, metaInfo = {}, } = await Image.compare(refBuffer, currBuffer, imageCompareOpts); + Object.assign(refImg, metaInfo.refImg); + if (!equal) { + const diffBuffer = await diffImage.createBuffer("png"); + const diffAreas = { diffBounds, diffClusters }; + const { tolerance, antialiasingTolerance } = opts; + const imageDiffOpts = { + tolerance, + antialiasingTolerance, + canHaveCaret, + diffAreas, + config, + emitter, + diffBuffer, + }; + await fs.outputFile(currImg.path, currBuffer); + return handleImageDiff(currImg, refImg, state, imageDiffOpts).catch(e => handleCaptureProcessorError(e)); + } + hermioneCtx.assertViewResults.add({ stateName: state, refImg: refImg }); + }; + session.addCommand("assertView", async function (state, selectors, opts = {}) { + await Promise.map([].concat(selectors), async (selector) => { + await this.$(selector) + .then(el => el.waitForExist()) + .catch(() => { + throw new Error(`element ("${selector}") still not existing after ${this.options.waitforTimeout} ms`); + }); + }); + return assertView(state, selectors, opts); + }); + session.addCommand("assertView", async function (state, opts = {}) { + await this.waitForExist({ timeoutMsg: "custom timeout msg" }).catch(() => { + throw new Error(`element ("${this.selector}") still not existing after ${this.options.waitforTimeout} ms`); + }); + return assertView(state, this.selector, opts); + }, true); +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/browser/commands/assert-view/index.js.map b/build/src/browser/commands/assert-view/index.js.map new file mode 100644 index 000000000..fb03d1cb0 --- /dev/null +++ b/build/src/browser/commands/assert-view/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/browser/commands/assert-view/index.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/browser/commands/getConfig.d.ts b/build/src/browser/commands/getConfig.d.ts new file mode 100644 index 000000000..6009cbe49 --- /dev/null +++ b/build/src/browser/commands/getConfig.d.ts @@ -0,0 +1,2 @@ +declare function _exports(browser: any): void; +export = _exports; diff --git a/build/src/browser/commands/getConfig.js b/build/src/browser/commands/getConfig.js new file mode 100644 index 000000000..29d31bb7f --- /dev/null +++ b/build/src/browser/commands/getConfig.js @@ -0,0 +1,6 @@ +"use strict"; +module.exports = browser => { + const { publicAPI: session, config } = browser; + session.addCommand("getConfig", () => config); +}; +//# sourceMappingURL=getConfig.js.map \ No newline at end of file diff --git a/build/src/browser/commands/getConfig.js.map b/build/src/browser/commands/getConfig.js.map new file mode 100644 index 000000000..48835916e --- /dev/null +++ b/build/src/browser/commands/getConfig.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getConfig.js","sourceRoot":"","sources":["../../../../src/browser/commands/getConfig.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,EAAE;IACvB,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC/C,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;AAClD,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/browser/commands/getPuppeteer.d.ts b/build/src/browser/commands/getPuppeteer.d.ts new file mode 100644 index 000000000..6009cbe49 --- /dev/null +++ b/build/src/browser/commands/getPuppeteer.d.ts @@ -0,0 +1,2 @@ +declare function _exports(browser: any): void; +export = _exports; diff --git a/build/src/browser/commands/getPuppeteer.js b/build/src/browser/commands/getPuppeteer.js new file mode 100644 index 000000000..2916ef46f --- /dev/null +++ b/build/src/browser/commands/getPuppeteer.js @@ -0,0 +1,32 @@ +"use strict"; +const urljoin = require("url-join"); +module.exports = browser => { + const { publicAPI: session, config } = browser; + if (!config.browserWSEndpoint || !session.getPuppeteer) { + return; + } + // temporary hack to be able to change `browserWSEndpoint` for puppeteer (issue - https://github.com/webdriverio/webdriverio/issues/9323) + session.overwriteCommand("getPuppeteer", async (origGetPuppeteer) => { + const prevBrowserWSEndpoint = getCdpEndpoint(session.capabilities); + const newBrowserWSEndpoint = urljoin(config.browserWSEndpoint, session.sessionId); + setCdpEndpoint(session.capabilities, newBrowserWSEndpoint); + try { + return origGetPuppeteer(); + } + finally { + setCdpEndpoint(session.capabilities, prevBrowserWSEndpoint); + } + }); +}; +function getCdpEndpoint(caps) { + return caps.alwaysMatch ? caps.alwaysMatch["se:cdp"] : caps["se:cdp"]; +} +function setCdpEndpoint(caps, value) { + if (caps.alwaysMatch) { + caps.alwaysMatch["se:cdp"] = value; + } + else { + caps["se:cdp"] = value; + } +} +//# sourceMappingURL=getPuppeteer.js.map \ No newline at end of file diff --git a/build/src/browser/commands/getPuppeteer.js.map b/build/src/browser/commands/getPuppeteer.js.map new file mode 100644 index 000000000..9bccee45e --- /dev/null +++ b/build/src/browser/commands/getPuppeteer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getPuppeteer.js","sourceRoot":"","sources":["../../../../src/browser/commands/getPuppeteer.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEpC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,EAAE;IACvB,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAE/C,IAAI,CAAC,MAAM,CAAC,iBAAiB,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QACrD,OAAO;IACX,CAAC;IAED,yIAAyI;IACzI,OAAO,CAAC,gBAAgB,CAAC,cAAc,EAAE,KAAK,EAAC,gBAAgB,EAAC,EAAE;QAC9D,MAAM,qBAAqB,GAAG,cAAc,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACnE,MAAM,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,iBAAiB,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QAElF,cAAc,CAAC,OAAO,CAAC,YAAY,EAAE,oBAAoB,CAAC,CAAC;QAE3D,IAAI,CAAC;YACD,OAAO,gBAAgB,EAAE,CAAC;QAC9B,CAAC;gBAAS,CAAC;YACP,cAAc,CAAC,OAAO,CAAC,YAAY,EAAE,qBAAqB,CAAC,CAAC;QAChE,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,SAAS,cAAc,CAAC,IAAI;IACxB,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,cAAc,CAAC,IAAI,EAAE,KAAK;IAC/B,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC;IACvC,CAAC;SAAM,CAAC;QACJ,IAAI,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC;IAC3B,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/build/src/browser/commands/index.d.ts b/build/src/browser/commands/index.d.ts new file mode 100644 index 000000000..911fcbc5d --- /dev/null +++ b/build/src/browser/commands/index.d.ts @@ -0,0 +1,2 @@ +declare const _exports: string[]; +export = _exports; diff --git a/build/src/browser/commands/index.js b/build/src/browser/commands/index.js new file mode 100644 index 000000000..afc9dfad9 --- /dev/null +++ b/build/src/browser/commands/index.js @@ -0,0 +1,11 @@ +"use strict"; +module.exports = [ + "assert-view", + "getConfig", + "getPuppeteer", + "setOrientation", + "scrollIntoView", + "openAndWait", + "switchToRepl", +]; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/browser/commands/index.js.map b/build/src/browser/commands/index.js.map new file mode 100644 index 000000000..633cbcf45 --- /dev/null +++ b/build/src/browser/commands/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/browser/commands/index.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,OAAO,GAAG;IACb,aAAa;IACb,WAAW;IACX,cAAc;IACd,gBAAgB;IAChB,gBAAgB;IAChB,aAAa;IACb,cAAc;CACjB,CAAC"} \ No newline at end of file diff --git a/build/src/browser/commands/openAndWait.d.ts b/build/src/browser/commands/openAndWait.d.ts new file mode 100644 index 000000000..7b3172a70 --- /dev/null +++ b/build/src/browser/commands/openAndWait.d.ts @@ -0,0 +1,3 @@ +import type { Browser } from "../types"; +declare const _default: (browser: Browser) => void; +export = _default; diff --git a/build/src/browser/commands/openAndWait.js b/build/src/browser/commands/openAndWait.js new file mode 100644 index 000000000..4be9ad81b --- /dev/null +++ b/build/src/browser/commands/openAndWait.js @@ -0,0 +1,87 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const lodash_1 = __importDefault(require("lodash")); +const page_loader_1 = __importDefault(require("../../utils/page-loader")); +const emptyPageUrl = "about:blank"; +const is = { + image: match => match.headers?.Accept?.includes("image"), + stylesheet: match => match.headers?.Accept?.includes("text/css"), + font: match => lodash_1.default.isString(match.url) && [".ttf", ".woff", ".woff2"].some(ext => match.url.endsWith(ext)), + favicon: match => lodash_1.default.isString(match.url) && match.url.endsWith("/favicon.ico"), +}; +function isMatchPatterns(patterns = [], str) { + return patterns.some(pattern => (lodash_1.default.isString(pattern) ? str.includes(pattern) : pattern.exec(str))); +} +function shouldThrowErrorDefault(match) { + if (is.favicon(match)) { + return false; + } + return is.image(match) || is.stylesheet(match) || is.font(match); +} +module.exports = (browser) => { + const { publicAPI: session, config } = browser; + const { openAndWaitOpts } = config; + const isChrome = config.desiredCapabilities?.browserName === "chrome"; + const isCDP = config.automationProtocol === "devtools"; + function openAndWait(uri, { selector = [], predicate, waitNetworkIdle = openAndWaitOpts?.waitNetworkIdle, waitNetworkIdleTimeout = openAndWaitOpts?.waitNetworkIdleTimeout, failOnNetworkError = openAndWaitOpts?.failOnNetworkError, shouldThrowError = shouldThrowErrorDefault, ignoreNetworkErrorsPatterns = openAndWaitOpts?.ignoreNetworkErrorsPatterns, timeout = openAndWaitOpts?.timeout || config?.pageLoadTimeout || 0, } = {}) { + waitNetworkIdle &&= isChrome || isCDP; + if (!uri || uri === emptyPageUrl) { + return new Promise(resolve => { + session.url(uri).then(() => resolve()); + }); + } + const selectors = typeof selector === "string" ? [selector] : selector; + const pageLoader = new page_loader_1.default(session, { + selectors, + predicate, + timeout, + waitNetworkIdle, + waitNetworkIdleTimeout, + }); + let selectorsResolved = !selectors.length; + let predicateResolved = !predicate; + let networkResolved = !waitNetworkIdle; + return new Promise((resolve, reject) => { + const handleError = (err) => { + reject(new Error(`url: ${err.message}`)); + }; + const checkLoaded = () => { + if (selectorsResolved && predicateResolved && networkResolved) { + resolve(); + } + }; + const goToPage = async () => { + await session.url(uri); + }; + pageLoader.on("pageLoadError", handleError); + pageLoader.on("selectorsError", handleError); + pageLoader.on("predicateError", handleError); + pageLoader.on("networkError", match => { + if (!failOnNetworkError) { + return; + } + const shouldIgnore = isMatchPatterns(ignoreNetworkErrorsPatterns, match.url); + if (!shouldIgnore && shouldThrowError(match)) { + reject(new Error(`url: couldn't get content from ${match.url}: ${match.statusCode}`)); + } + }); + pageLoader.on("selectorsExist", () => { + selectorsResolved = true; + checkLoaded(); + }); + pageLoader.on("predicateResolved", () => { + predicateResolved = true; + checkLoaded(); + }); + pageLoader.on("networkResolved", () => { + networkResolved = true; + checkLoaded(); + }); + pageLoader.load(goToPage).then(checkLoaded); + }).finally(() => pageLoader.unsubscribe()); + } + session.addCommand("openAndWait", openAndWait); +}; +//# sourceMappingURL=openAndWait.js.map \ No newline at end of file diff --git a/build/src/browser/commands/openAndWait.js.map b/build/src/browser/commands/openAndWait.js.map new file mode 100644 index 000000000..f89aa4187 --- /dev/null +++ b/build/src/browser/commands/openAndWait.js.map @@ -0,0 +1 @@ +{"version":3,"file":"openAndWait.js","sourceRoot":"","sources":["../../../../src/browser/commands/openAndWait.ts"],"names":[],"mappings":";;;;AAAA,oDAAuB;AAEvB,0EAAiD;AAcjD,MAAM,YAAY,GAAG,aAAa,CAAC;AAEnC,MAAM,EAAE,GAAgD;IACpD,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC;IACxD,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC;IAChE,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACxG,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC;CAChF,CAAC;AA8FF,SAAS,eAAe,CAAC,WAAmC,EAAE,EAAE,GAAW;IACvE,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,gBAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACvG,CAAC;AAED,SAAS,uBAAuB,CAAC,KAAc;IAC3C,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,OAAO,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACrE,CAAC;AAtGD,iBAAS,CAAC,OAAgB,EAAQ,EAAE;IAChC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC/C,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CAAC;IACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,mBAAmB,EAAE,WAAW,KAAK,QAAQ,CAAC;IACtE,MAAM,KAAK,GAAG,MAAM,CAAC,kBAAkB,KAAK,UAAU,CAAC;IAEvD,SAAS,WAAW,CAChB,GAAW,EACX,EACI,QAAQ,GAAG,EAAE,EACb,SAAS,EACT,eAAe,GAAG,eAAe,EAAE,eAAe,EAClD,sBAAsB,GAAG,eAAe,EAAE,sBAAsB,EAChE,kBAAkB,GAAG,eAAe,EAAE,kBAAkB,EACxD,gBAAgB,GAAG,uBAAuB,EAC1C,2BAA2B,GAAG,eAAe,EAAE,2BAA2B,EAC1E,OAAO,GAAG,eAAe,EAAE,OAAO,IAAI,MAAM,EAAE,eAAe,IAAI,CAAC,MACxD,EAAE;QAEhB,eAAe,KAAK,QAAQ,IAAI,KAAK,CAAC;QAEtC,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;YAC/B,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;gBACzB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3C,CAAC,CAAC,CAAC;QACP,CAAC;QAED,MAAM,SAAS,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QAEvE,MAAM,UAAU,GAAG,IAAI,qBAAU,CAAC,OAAO,EAAE;YACvC,SAAS;YACT,SAAS;YACT,OAAO;YACP,eAAe;YACf,sBAAsB;SACzB,CAAC,CAAC;QAEH,IAAI,iBAAiB,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC;QAC1C,IAAI,iBAAiB,GAAG,CAAC,SAAS,CAAC;QACnC,IAAI,eAAe,GAAG,CAAC,eAAe,CAAC;QAEvC,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACzC,MAAM,WAAW,GAAG,CAAC,GAAU,EAAQ,EAAE;gBACrC,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAC7C,CAAC,CAAC;YAEF,MAAM,WAAW,GAAG,GAAS,EAAE;gBAC3B,IAAI,iBAAiB,IAAI,iBAAiB,IAAI,eAAe,EAAE,CAAC;oBAC5D,OAAO,EAAE,CAAC;gBACd,CAAC;YACL,CAAC,CAAC;YAEF,MAAM,QAAQ,GAAG,KAAK,IAAmB,EAAE;gBACvC,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC3B,CAAC,CAAC;YAEF,UAAU,CAAC,EAAE,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;YAC5C,UAAU,CAAC,EAAE,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;YAC7C,UAAU,CAAC,EAAE,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;YAC7C,UAAU,CAAC,EAAE,CAAC,cAAc,EAAE,KAAK,CAAC,EAAE;gBAClC,IAAI,CAAC,kBAAkB,EAAE,CAAC;oBACtB,OAAO;gBACX,CAAC;gBAED,MAAM,YAAY,GAAG,eAAe,CAAC,2BAA2B,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;gBAE7E,IAAI,CAAC,YAAY,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC3C,MAAM,CAAC,IAAI,KAAK,CAAC,kCAAkC,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;gBAC1F,CAAC;YACL,CAAC,CAAC,CAAC;YACH,UAAU,CAAC,EAAE,CAAC,gBAAgB,EAAE,GAAG,EAAE;gBACjC,iBAAiB,GAAG,IAAI,CAAC;gBACzB,WAAW,EAAE,CAAC;YAClB,CAAC,CAAC,CAAC;YAEH,UAAU,CAAC,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;gBACpC,iBAAiB,GAAG,IAAI,CAAC;gBACzB,WAAW,EAAE,CAAC;YAClB,CAAC,CAAC,CAAC;YAEH,UAAU,CAAC,EAAE,CAAC,iBAAiB,EAAE,GAAG,EAAE;gBAClC,eAAe,GAAG,IAAI,CAAC;gBACvB,WAAW,EAAE,CAAC;YAClB,CAAC,CAAC,CAAC;YAEH,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,CAAC,UAAU,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;AACnD,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/browser/commands/runStep.d.ts b/build/src/browser/commands/runStep.d.ts new file mode 100644 index 000000000..6009cbe49 --- /dev/null +++ b/build/src/browser/commands/runStep.d.ts @@ -0,0 +1,2 @@ +declare function _exports(browser: any): void; +export = _exports; diff --git a/build/src/browser/commands/runStep.js b/build/src/browser/commands/runStep.js new file mode 100644 index 000000000..e7dc2cd9a --- /dev/null +++ b/build/src/browser/commands/runStep.js @@ -0,0 +1,15 @@ +"use strict"; +const _ = require("lodash"); +module.exports = browser => { + const { publicAPI: session } = browser; + session.addCommand("runStep", (stepName, stepCb) => { + if (!_.isString(stepName)) { + throw Error(`First argument must be a string, but got ${typeof stepName}`); + } + if (!_.isFunction(stepCb)) { + throw Error(`Second argument must be a function, but got ${typeof stepCb}`); + } + return stepCb(); + }); +}; +//# sourceMappingURL=runStep.js.map \ No newline at end of file diff --git a/build/src/browser/commands/runStep.js.map b/build/src/browser/commands/runStep.js.map new file mode 100644 index 000000000..f2af7f320 --- /dev/null +++ b/build/src/browser/commands/runStep.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runStep.js","sourceRoot":"","sources":["../../../../src/browser/commands/runStep.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE5B,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,EAAE;IACvB,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACvC,OAAO,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE;QAC/C,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxB,MAAM,KAAK,CAAC,4CAA4C,OAAO,QAAQ,EAAE,CAAC,CAAC;QAC/E,CAAC;QAED,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,MAAM,KAAK,CAAC,+CAA+C,OAAO,MAAM,EAAE,CAAC,CAAC;QAChF,CAAC;QAED,OAAO,MAAM,EAAE,CAAC;IACpB,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/browser/commands/scrollIntoView.d.ts b/build/src/browser/commands/scrollIntoView.d.ts new file mode 100644 index 000000000..85a227368 --- /dev/null +++ b/build/src/browser/commands/scrollIntoView.d.ts @@ -0,0 +1,3 @@ +import type { Browser } from "../types"; +declare const _default: (browser: Browser) => Promise; +export = _default; diff --git a/build/src/browser/commands/scrollIntoView.js b/build/src/browser/commands/scrollIntoView.js new file mode 100644 index 000000000..48f040ef2 --- /dev/null +++ b/build/src/browser/commands/scrollIntoView.js @@ -0,0 +1,10 @@ +"use strict"; +module.exports = async (browser) => { + const { publicAPI: session } = browser; + session.overwriteCommand("scrollIntoView", async function (_origScrollIntoView, options = { block: "start", inline: "nearest" }) { + await session.execute(function (elem, options) { + return elem.scrollIntoView(options); + }, this, options); + }, true); +}; +//# sourceMappingURL=scrollIntoView.js.map \ No newline at end of file diff --git a/build/src/browser/commands/scrollIntoView.js.map b/build/src/browser/commands/scrollIntoView.js.map new file mode 100644 index 000000000..d90b15c6f --- /dev/null +++ b/build/src/browser/commands/scrollIntoView.js.map @@ -0,0 +1 @@ +{"version":3,"file":"scrollIntoView.js","sourceRoot":"","sources":["../../../../src/browser/commands/scrollIntoView.ts"],"names":[],"mappings":";AAGA,iBAAS,KAAK,EAAE,OAAgB,EAAiB,EAAE;IAC/C,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAEvC,OAAO,CAAC,gBAAgB,CACpB,gBAAgB,EAChB,KAAK,WAED,mBAAmB,EACnB,UAA2C,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE;QAEhF,MAAM,OAAO,CAAC,OAAO,CACjB,UAAU,IAAI,EAAE,OAAO;YACnB,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACxC,CAAC,EACD,IAAI,EACJ,OAAO,CACV,CAAC;IACN,CAAC,EACD,IAAI,CACP,CAAC;AACN,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/browser/commands/setOrientation.d.ts b/build/src/browser/commands/setOrientation.d.ts new file mode 100644 index 000000000..6009cbe49 --- /dev/null +++ b/build/src/browser/commands/setOrientation.d.ts @@ -0,0 +1,2 @@ +declare function _exports(browser: any): void; +export = _exports; diff --git a/build/src/browser/commands/setOrientation.js b/build/src/browser/commands/setOrientation.js new file mode 100644 index 000000000..1bc8028c3 --- /dev/null +++ b/build/src/browser/commands/setOrientation.js @@ -0,0 +1,32 @@ +/* global document */ +"use strict"; +module.exports = browser => { + const { publicAPI: session, config } = browser; + if (!session.setOrientation) { + return; + } + session.overwriteCommand("setOrientation", async (origSetOrientation, orientation) => { + if (!config.waitOrientationChange) { + return origSetOrientation(orientation); + } + const initialBodyWidth = await getBodyWidth(); + const result = await origSetOrientation(orientation); + if (typeof result === "string" && result.match(/Already in/)) { + return result; + } + await waitForOrientationChange(initialBodyWidth, orientation); + return result; + }); + function getBodyWidth() { + return session.execute(() => document.body.clientWidth); + } + function waitForOrientationChange(initialBodyWidth, orientation) { + const errMsg = `Orientation did not changed to '${orientation}' in ${config.waitTimeout} ms`; + return session.waitUntil(() => isOrientationChanged(initialBodyWidth), config.waitTimeout, errMsg); + } + async function isOrientationChanged(initialBodyWidth) { + const currentBodyWidth = await getBodyWidth(); + return currentBodyWidth !== initialBodyWidth; + } +}; +//# sourceMappingURL=setOrientation.js.map \ No newline at end of file diff --git a/build/src/browser/commands/setOrientation.js.map b/build/src/browser/commands/setOrientation.js.map new file mode 100644 index 000000000..50cb5bf46 --- /dev/null +++ b/build/src/browser/commands/setOrientation.js.map @@ -0,0 +1 @@ +{"version":3,"file":"setOrientation.js","sourceRoot":"","sources":["../../../../src/browser/commands/setOrientation.js"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,YAAY,CAAC;AAEb,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,EAAE;IACvB,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAE/C,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAC1B,OAAO;IACX,CAAC;IAED,OAAO,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,EAAE;QACjF,IAAI,CAAC,MAAM,CAAC,qBAAqB,EAAE,CAAC;YAChC,OAAO,kBAAkB,CAAC,WAAW,CAAC,CAAC;QAC3C,CAAC;QAED,MAAM,gBAAgB,GAAG,MAAM,YAAY,EAAE,CAAC;QAC9C,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,WAAW,CAAC,CAAC;QAErD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;YAC3D,OAAO,MAAM,CAAC;QAClB,CAAC;QAED,MAAM,wBAAwB,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;QAE9D,OAAO,MAAM,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,SAAS,YAAY;QACjB,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5D,CAAC;IAED,SAAS,wBAAwB,CAAC,gBAAgB,EAAE,WAAW;QAC3D,MAAM,MAAM,GAAG,mCAAmC,WAAW,QAAQ,MAAM,CAAC,WAAW,KAAK,CAAC;QAE7F,OAAO,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACvG,CAAC;IAED,KAAK,UAAU,oBAAoB,CAAC,gBAAgB;QAChD,MAAM,gBAAgB,GAAG,MAAM,YAAY,EAAE,CAAC;QAE9C,OAAO,gBAAgB,KAAK,gBAAgB,CAAC;IACjD,CAAC;AACL,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/browser/commands/switchToRepl.d.ts b/build/src/browser/commands/switchToRepl.d.ts new file mode 100644 index 000000000..85a227368 --- /dev/null +++ b/build/src/browser/commands/switchToRepl.d.ts @@ -0,0 +1,3 @@ +import type { Browser } from "../types"; +declare const _default: (browser: Browser) => Promise; +export = _default; diff --git a/build/src/browser/commands/switchToRepl.js b/build/src/browser/commands/switchToRepl.js new file mode 100644 index 000000000..6385ea31c --- /dev/null +++ b/build/src/browser/commands/switchToRepl.js @@ -0,0 +1,64 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const node_repl_1 = __importDefault(require("node:repl")); +const node_path_1 = __importDefault(require("node:path")); +const node_events_1 = require("node:events"); +const chalk_1 = __importDefault(require("chalk")); +const runtime_config_1 = __importDefault(require("../../config/runtime-config")); +const logger_1 = __importDefault(require("../../utils/logger")); +const REPL_LINE_EVENT = "line"; +module.exports = async (browser) => { + const { publicAPI: session } = browser; + const applyContext = (replServer, ctx = {}) => { + if (!ctx.browser) { + ctx.browser = session; + } + for (const [key, value] of Object.entries(ctx)) { + Object.defineProperty(replServer.context, key, { + configurable: false, + enumerable: true, + value, + }); + } + }; + const handleLines = (replServer) => { + const lineEvents = (0, node_events_1.getEventListeners)(replServer, REPL_LINE_EVENT); + replServer.removeAllListeners(REPL_LINE_EVENT); + replServer.on(REPL_LINE_EVENT, cmd => { + const trimmedCmd = cmd.trim(); + const newCmd = trimmedCmd.replace(/(?<=^|\s|;|\(|\{)(let |const )/g, "var "); + for (const event of lineEvents) { + event(newCmd); + } + }); + }; + session.addCommand("switchToRepl", async function (ctx = {}) { + const { replMode } = runtime_config_1.default.getInstance(); + const { onReplMode } = browser.state; + if (!replMode?.enabled) { + throw new Error('Command "switchToRepl" available only in REPL mode, which can be started using cli option: "--repl", "--repl-before-test" or "--repl-on-fail"'); + } + if (onReplMode) { + logger_1.default.warn(chalk_1.default.yellow("Hermione is already in REPL mode")); + return; + } + logger_1.default.log(chalk_1.default.yellow("You have entered REPL mode via terminal")); + const currCwd = process.cwd(); + const testCwd = node_path_1.default.dirname(session.executionContext.ctx.currentTest.file); + process.chdir(testCwd); + const replServer = node_repl_1.default.start({ prompt: "> " }); + browser.applyState({ onReplMode: true }); + applyContext(replServer, ctx); + handleLines(replServer); + return new Promise(resolve => { + return replServer.on("exit", () => { + process.chdir(currCwd); + browser.applyState({ onReplMode: false }); + resolve(); + }); + }); + }); +}; +//# sourceMappingURL=switchToRepl.js.map \ No newline at end of file diff --git a/build/src/browser/commands/switchToRepl.js.map b/build/src/browser/commands/switchToRepl.js.map new file mode 100644 index 000000000..71ff16ed7 --- /dev/null +++ b/build/src/browser/commands/switchToRepl.js.map @@ -0,0 +1 @@ +{"version":3,"file":"switchToRepl.js","sourceRoot":"","sources":["../../../../src/browser/commands/switchToRepl.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/browser/commands/types.d.ts b/build/src/browser/commands/types.d.ts new file mode 100644 index 000000000..d76e5cb0a --- /dev/null +++ b/build/src/browser/commands/types.d.ts @@ -0,0 +1,68 @@ +import { AssertViewOptsConfig } from "../../config/types"; +export interface AssertViewOpts extends Partial { + /** + * Maximum allowed difference between colors. + * Overrides config {@link https://github.com/gemini-testing/hermione#browsers browsers}.{@link https://github.com/gemini-testing/hermione#tolerance tolerance} value. + * + * @remarks + * Indicates maximum allowed CIEDE2000 difference between colors. Used only in non-strict mode. + * Increasing global default is not recommended, prefer changing tolerance for particular suites or states instead. + * By default it's 2.3 which should be enough for the most cases. + * + * @defaultValue `2.3` + */ + tolerance?: number; + /** + * Minimum difference in brightness (zero by default) between the darkest/lightest pixel (which is adjacent to the antialiasing pixel) and theirs adjacent pixels. + * Overrides config {@link https://github.com/gemini-testing/hermione#browsers browsers}.{@link https://github.com/gemini-testing/hermione#antialiasingTolerance antialiasingTolerance} value. + * + * @remarks + * Read more about this option in {@link https://github.com/gemini-testing/looks-same#comparing-images-with-ignoring-antialiasing looks-same} + * + * @defaultValue `4` + */ + antialiasingTolerance?: number; + /** + * Allows testing of regions which bottom bounds are outside of a viewport height. + * Overrides config {@link https://github.com/gemini-testing/hermione#browsers browsers}.{@link https://github.com/gemini-testing/hermione#compositeImage compositeImage} value. + * + * @remarks + * In the resulting screenshot the area which fits the viewport bounds will be joined with the area which is outside of the viewport height. + * + * @defaultValue `true` + */ + compositeImage?: boolean; + /** + * Allows to specify a delay (in milliseconds) before making any screenshot. + * Overrides config {@link https://github.com/gemini-testing/hermione#browsers browsers}.{@link https://github.com/gemini-testing/hermione#screenshotDelay screenshotDelay} value. + * + * @remarks + * This is useful when the page has elements which are animated or if you do not want to screen a scrollbar. + * + * @defaultValue `0` + */ + screenshotDelay?: number; + /** + * Ability to set DOM-node selector which should be scroll when the captured element does not completely fit on the screen. + * + * @remarks + * Useful when you capture the modal (popup). In this case a duplicate of the modal appears on the screenshot. + * That happens because we scroll the page using `window` selector, which scroll only the background of the modal, and the modal itself remains in place. + * Default value is `undefined` (it means scroll relative to `window`). Works only when `compositeImage` is `true` (default). + * + * @defaultValue `undefined` + */ + selectorToScroll?: string; + /** + * Ability to disable animations and transitions while making a screenshot + * + * @remarks + * Usefull when you capture screenshot of a page, having animations and transitions. + * Iframe animations are only disabled when using webdriver protocol. + * + * @defaultValue `true` + */ + disableAnimation?: boolean; +} +export type AssertViewCommand = (state: string, selectors: string | string[], opts?: AssertViewOpts) => Promise; +export type AssertViewElementCommand = (state: string, opts?: AssertViewOpts) => Promise; diff --git a/build/src/browser/commands/types.js b/build/src/browser/commands/types.js new file mode 100644 index 000000000..11e638d1e --- /dev/null +++ b/build/src/browser/commands/types.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/build/src/browser/commands/types.js.map b/build/src/browser/commands/types.js.map new file mode 100644 index 000000000..12a3946a0 --- /dev/null +++ b/build/src/browser/commands/types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/browser/commands/types.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/build/src/browser/core-error.d.ts b/build/src/browser/core-error.d.ts new file mode 100644 index 000000000..2708f515b --- /dev/null +++ b/build/src/browser/core-error.d.ts @@ -0,0 +1,4 @@ +export declare class CoreError extends Error { + name: string; + constructor(message: string); +} diff --git a/build/src/browser/core-error.js b/build/src/browser/core-error.js new file mode 100644 index 000000000..e1ee4cceb --- /dev/null +++ b/build/src/browser/core-error.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CoreError = void 0; +class CoreError extends Error { + constructor(message) { + super(message); + this.name = "CoreError"; + } +} +exports.CoreError = CoreError; +//# sourceMappingURL=core-error.js.map \ No newline at end of file diff --git a/build/src/browser/core-error.js.map b/build/src/browser/core-error.js.map new file mode 100644 index 000000000..c85297284 --- /dev/null +++ b/build/src/browser/core-error.js.map @@ -0,0 +1 @@ +{"version":3,"file":"core-error.js","sourceRoot":"","sources":["../../../src/browser/core-error.ts"],"names":[],"mappings":";;;AAAA,MAAa,SAAU,SAAQ,KAAK;IAGhC,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QAHnB,SAAI,GAAG,WAAW,CAAC;IAInB,CAAC;CACJ;AAND,8BAMC"} \ No newline at end of file diff --git a/build/src/browser/existing-browser.d.ts b/build/src/browser/existing-browser.d.ts new file mode 100644 index 000000000..4504d6d07 --- /dev/null +++ b/build/src/browser/existing-browser.d.ts @@ -0,0 +1,55 @@ +export = ExistingBrowser; +declare class ExistingBrowser extends Browser { + static create(config: any, opts: any): import("./existing-browser"); + _emitter: any; + _camera: Camera; + _meta: any; + init({ sessionId, sessionCaps, sessionOpts }: { + sessionId: any; + sessionCaps: any; + sessionOpts: any; + } | undefined, calibrator: any): globalThis.Promise; + markAsBroken(): void; + quit(): void; + prepareScreenshot(selectors: any, opts?: {}): globalThis.Promise; + cleanupScreenshot(opts?: {}): globalThis.Promise; + open(url: any): any; + evalScript(script: any): any; + injectScript(script: any): any; + captureViewportImage(page: any, screenshotDelay: any): globalThis.Promise; + scrollBy(params: any): any; + _attachSession({ sessionId, sessionCaps, sessionOpts }: { + sessionId: any; + sessionCaps: any; + sessionOpts?: {} | undefined; + }): globalThis.Promise; + _initMeta(): any; + _takeScreenshot(): any; + _addMetaAccessCommands(session: any): void; + _decorateUrlMethod(session: any): void; + _resolveUrl(uri: any): any; + _performIsolation({ sessionCaps, sessionOpts }: { + sessionCaps: any; + sessionOpts: any; + }): globalThis.Promise; + _prepareSession(): globalThis.Promise; + _setOrientation(orientation: any): globalThis.Promise; + _setWindowSize(size: any): globalThis.Promise; + _performCalibration(calibrator: any): any; + _calibration: any; + _buildClientScripts(): Promise; + _clientBridge: clientBridge.ClientBridge | undefined; + _runInEachIframe(cb: any): globalThis.Promise; + _disableFrameAnimations(): globalThis.Promise; + _disableIframeAnimations(): globalThis.Promise; + _cleanupFrameAnimations(): globalThis.Promise; + _cleanupIframeAnimations(): globalThis.Promise; + _cleanupPageAnimations(): globalThis.Promise; + _stubCommands(): void; + get meta(): any; + get emitter(): any; +} +import Browser = require("./browser"); +import Camera = require("./camera"); +import clientBridge = require("./client-bridge"); +import Promise = require("bluebird"); diff --git a/build/src/browser/existing-browser.js b/build/src/browser/existing-browser.js new file mode 100644 index 000000000..8fa47a079 --- /dev/null +++ b/build/src/browser/existing-browser.js @@ -0,0 +1,287 @@ +/* global window, document */ +"use strict"; +const url = require("url"); +const Promise = require("bluebird"); +const _ = require("lodash"); +const webdriverio = require("webdriverio"); +const { sessionEnvironmentDetector } = require("@wdio/utils"); +const Browser = require("./browser"); +const commandsList = require("./commands"); +const Camera = require("./camera"); +const clientBridge = require("./client-bridge"); +const history = require("./history"); +const logger = require("../utils/logger"); +const { WEBDRIVER_PROTOCOL } = require("../constants/config"); +const { MIN_CHROME_VERSION_SUPPORT_ISOLATION } = require("../constants/browser"); +const { isSupportIsolation } = require("../utils/browser"); +const OPTIONAL_SESSION_OPTS = ["transformRequest", "transformResponse"]; +module.exports = class ExistingBrowser extends Browser { + static create(config, opts) { + return new this(config, opts); + } + constructor(config, opts) { + super(config, opts); + this._emitter = opts.emitter; + this._camera = Camera.create(this._config.screenshotMode, () => this._takeScreenshot()); + this._meta = this._initMeta(); + } + async init({ sessionId, sessionCaps, sessionOpts } = {}, calibrator) { + this._session = await this._attachSession({ sessionId, sessionCaps, sessionOpts }); + this._addSteps(); + this._addHistory(); + await history.runGroup(this._callstackHistory, "hermione: init browser", async () => { + this._addCommands(); + await this._performIsolation({ sessionCaps, sessionOpts }); + try { + this.config.prepareBrowser && this.config.prepareBrowser(this.publicAPI); + } + catch (e) { + logger.warn(`WARN: couldn't prepare browser ${this.id}\n`, e.stack); + } + await this._prepareSession(); + await this._performCalibration(calibrator); + await this._buildClientScripts(); + }); + return this; + } + markAsBroken() { + if (this.state.isBroken) { + return; + } + this.applyState({ isBroken: true }); + this._stubCommands(); + } + quit() { + this._meta = this._initMeta(); + this._state = { isBroken: false }; + } + async prepareScreenshot(selectors, opts = {}) { + opts = _.extend(opts, { + usePixelRatio: this._calibration ? this._calibration.usePixelRatio : true, + }); + const result = await this._clientBridge.call("prepareScreenshot", [selectors, opts]); + if (result.error) { + throw new Error(`Prepare screenshot failed with error type '${result.error}' and error message: ${result.message}`); + } + // https://github.com/webdriverio/webdriverio/issues/11396 + if (this._config.automationProtocol === "webdriver" && opts.disableAnimation) { + await this._disableIframeAnimations(); + } + return result; + } + async cleanupScreenshot(opts = {}) { + if (opts.disableAnimation) { + await this._cleanupPageAnimations(); + } + } + open(url) { + return this._session.url(url); + } + evalScript(script) { + return this._session.execute(`return ${script}`); + } + injectScript(script) { + return this._session.execute(script); + } + async captureViewportImage(page, screenshotDelay) { + if (screenshotDelay) { + await Promise.delay(screenshotDelay); + } + return this._camera.captureViewportImage(page); + } + scrollBy(params) { + return this._session.execute(function (params) { + var elem, xVal, yVal; + if (params.selector) { + elem = document.querySelector(params.selector); + if (!elem) { + throw new Error("Scroll screenshot failed with: " + + 'Could not find element with css selector specified in "selectorToScroll" option: ' + + params.selector); + } + xVal = elem.scrollLeft + params.x; + yVal = elem.scrollTop + params.y; + } + else { + elem = window; + xVal = window.pageXOffset + params.x; + yVal = window.pageYOffset + params.y; + } + return elem.scrollTo(xVal, yVal); + }, params); + } + _attachSession({ sessionId, sessionCaps, sessionOpts = {} }) { + const detectedSessionEnvFlags = sessionEnvironmentDetector({ + capabilities: sessionCaps, + requestedCapabilities: sessionOpts.capabilities, + }); + const opts = { + sessionId, + ...sessionOpts, + ...this._getSessionOptsFromConfig(OPTIONAL_SESSION_OPTS), + ...detectedSessionEnvFlags, + ...this._config.sessionEnvFlags, + options: sessionOpts, + capabilities: { ...sessionOpts.capabilities, ...sessionCaps }, + requestedCapabilities: sessionOpts.capabilities, + }; + return webdriverio.attach(opts); + } + _initMeta() { + return { + pid: process.pid, + browserVersion: this.version, + testXReqId: this.testXReqId, + ...this._config.meta, + }; + } + _takeScreenshot() { + return this._session.takeScreenshot(); + } + _addCommands() { + this._addMetaAccessCommands(this._session); + this._decorateUrlMethod(this._session); + commandsList.forEach(command => require(`./commands/${command}`)(this)); + super._addCommands(); + } + _addMetaAccessCommands(session) { + session.addCommand("setMeta", (key, value) => (this._meta[key] = value)); + session.addCommand("getMeta", key => (key ? this._meta[key] : this._meta)); + } + _decorateUrlMethod(session) { + session.overwriteCommand("url", async (origUrlFn, uri) => { + if (!uri) { + return session.getUrl(); + } + const newUri = this._resolveUrl(uri); + this._meta.url = newUri; + if (this._config.urlHttpTimeout) { + this.setHttpTimeout(this._config.urlHttpTimeout); + } + const result = await origUrlFn(newUri); + if (this._config.urlHttpTimeout) { + this.restoreHttpTimeout(); + } + if (this._clientBridge) { + await this._clientBridge.call("resetZoom"); + } + return result; + }); + } + _resolveUrl(uri) { + return this._config.baseUrl ? url.resolve(this._config.baseUrl, uri) : uri; + } + async _performIsolation({ sessionCaps, sessionOpts }) { + if (!this._config.isolation) { + return; + } + const { browserName, browserVersion = "", version = "" } = sessionCaps; + const { automationProtocol } = sessionOpts; + if (!isSupportIsolation(browserName, browserVersion)) { + logger.warn(`WARN: test isolation works only with chrome@${MIN_CHROME_VERSION_SUPPORT_ISOLATION} and higher, ` + + `but got ${browserName}@${browserVersion || version}`); + return; + } + const puppeteer = await this._session.getPuppeteer(); + const browserCtxs = puppeteer.browserContexts(); + const incognitoCtx = await puppeteer.createIncognitoBrowserContext(); + const page = await incognitoCtx.newPage(); + if (automationProtocol === WEBDRIVER_PROTOCOL) { + const windowIds = await this._session.getWindowHandles(); + const incognitoWindowId = windowIds.find(id => id.includes(page.target()._targetId)); + await this._session.switchToWindow(incognitoWindowId); + } + for (const ctx of browserCtxs) { + if (ctx.isIncognito()) { + await ctx.close(); + continue; + } + for (const page of await ctx.pages()) { + await page.close(); + } + } + } + async _prepareSession() { + await this._setOrientation(this.config.orientation); + await this._setWindowSize(this.config.windowSize); + } + async _setOrientation(orientation) { + if (orientation) { + await this._session.setOrientation(orientation); + } + } + async _setWindowSize(size) { + if (size) { + await this._session.setWindowSize(size.width, size.height); + } + } + _performCalibration(calibrator) { + if (!this.config.calibrate || this._calibration) { + return Promise.resolve(); + } + return calibrator.calibrate(this).then(calibration => { + this._calibration = calibration; + this._camera.calibrate(calibration); + }); + } + _buildClientScripts() { + return clientBridge + .build(this, { calibration: this._calibration }) + .then(clientBridge => (this._clientBridge = clientBridge)); + } + async _runInEachIframe(cb) { + const iframes = await this._session.findElements("css selector", "iframe"); + try { + for (const iframe of iframes) { + await this._session.switchToFrame(iframe); + await cb(); + // switchToParentFrame does not work in ios - https://github.com/appium/appium/issues/14882 + await this._session.switchToFrame(null); + } + } + catch (e) { + await this._session.switchToFrame(null); + throw e; + } + } + async _disableFrameAnimations() { + const result = await this._clientBridge.call("disableFrameAnimations"); + if (result && result.error) { + throw new Error(`Disable animations failed with error type '${result.error}' and error message: ${result.message}`); + } + return result; + } + async _disableIframeAnimations() { + await this._runInEachIframe(() => this._disableFrameAnimations()); + } + async _cleanupFrameAnimations() { + return this._clientBridge.call("cleanupFrameAnimations"); + } + async _cleanupIframeAnimations() { + await this._runInEachIframe(() => this._cleanupFrameAnimations()); + } + async _cleanupPageAnimations() { + await this._cleanupFrameAnimations(); + if (this._config.automationProtocol === "webdriver") { + await this._cleanupIframeAnimations(); + } + } + _stubCommands() { + for (let commandName of this._session.commandList) { + if (commandName === "deleteSession") { + continue; + } + if (_.isFunction(this._session[commandName])) { + // eslint-disable-next-line @typescript-eslint/no-empty-function + this._session.overwriteCommand(commandName, () => { }); + } + } + } + get meta() { + return this._meta; + } + get emitter() { + return this._emitter; + } +}; +//# sourceMappingURL=existing-browser.js.map \ No newline at end of file diff --git a/build/src/browser/existing-browser.js.map b/build/src/browser/existing-browser.js.map new file mode 100644 index 000000000..91f299da2 --- /dev/null +++ b/build/src/browser/existing-browser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"existing-browser.js","sourceRoot":"","sources":["../../../src/browser/existing-browser.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/browser/history/callstack.d.ts b/build/src/browser/history/callstack.d.ts new file mode 100644 index 000000000..d01b012fc --- /dev/null +++ b/build/src/browser/history/callstack.d.ts @@ -0,0 +1,9 @@ +export = Callstack; +declare class Callstack { + _history: any[]; + _stack: any[]; + enter(data: any): void; + leave(key: any): void; + markError(shouldPropagateFn: any): void; + release(): any[]; +} diff --git a/build/src/browser/history/callstack.js b/build/src/browser/history/callstack.js new file mode 100644 index 000000000..7bf4e057b --- /dev/null +++ b/build/src/browser/history/callstack.js @@ -0,0 +1,49 @@ +"use strict"; +const _ = require("lodash"); +const { historyDataMap } = require("./utils"); +module.exports = class Callstack { + constructor() { + this._history = []; + this._stack = []; + } + enter(data) { + this._stack.push({ + ...data, + [historyDataMap.TIME_START]: Date.now(), + [historyDataMap.CHILDREN]: [], + }); + } + leave(key) { + const currentNodeIndex = _.findLastIndex(this._stack, node => node[historyDataMap.KEY] === key); + const wasRemovedByParent = currentNodeIndex === -1; + if (wasRemovedByParent) { + return; + } + const removedNodes = this._stack.splice(currentNodeIndex); + const currentNode = _.first(removedNodes); + const parentNode = _.last(this._stack); + const isCurrentNodeRoot = this._stack.length === 0; + currentNode[historyDataMap.TIME_END] = Date.now(); + currentNode[historyDataMap.DURATION] = + currentNode[historyDataMap.TIME_END] - currentNode[historyDataMap.TIME_START]; + isCurrentNodeRoot ? this._history.push(currentNode) : parentNode[historyDataMap.CHILDREN].push(currentNode); + } + markError(shouldPropagateFn) { + let parentNode = null; + let currentNode = _.first(this._stack); + let shouldContinue = Boolean(currentNode); + while (shouldContinue) { + currentNode[historyDataMap.IS_FAILED] = true; + parentNode = currentNode; + currentNode = _.last(currentNode[historyDataMap.CHILDREN]); + shouldContinue = currentNode && shouldPropagateFn(parentNode, currentNode); + } + } + release() { + const history = this._history; + this._stack = []; + this._history = []; + return history; + } +}; +//# sourceMappingURL=callstack.js.map \ No newline at end of file diff --git a/build/src/browser/history/callstack.js.map b/build/src/browser/history/callstack.js.map new file mode 100644 index 000000000..a7e0f59c9 --- /dev/null +++ b/build/src/browser/history/callstack.js.map @@ -0,0 +1 @@ +{"version":3,"file":"callstack.js","sourceRoot":"","sources":["../../../../src/browser/history/callstack.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC5B,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAE9C,MAAM,CAAC,OAAO,GAAG,MAAM,SAAS;IAC5B;QACI,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,IAAI;QACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YACb,GAAG,IAAI;YACP,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE;YACvC,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,EAAE;SAChC,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,GAAG;QACL,MAAM,gBAAgB,GAAG,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;QAChG,MAAM,kBAAkB,GAAG,gBAAgB,KAAK,CAAC,CAAC,CAAC;QAEnD,IAAI,kBAAkB,EAAE,CAAC;YACrB,OAAO;QACX,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC1D,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC1C,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,iBAAiB,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;QAEnD,WAAW,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAClD,WAAW,CAAC,cAAc,CAAC,QAAQ,CAAC;YAChC,WAAW,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QAElF,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAChH,CAAC;IAED,SAAS,CAAC,iBAAiB;QACvB,IAAI,UAAU,GAAG,IAAI,CAAC;QACtB,IAAI,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvC,IAAI,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;QAE1C,OAAO,cAAc,EAAE,CAAC;YACpB,WAAW,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;YAE7C,UAAU,GAAG,WAAW,CAAC;YACzB,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC3D,cAAc,GAAG,WAAW,IAAI,iBAAiB,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAC/E,CAAC;IACL,CAAC;IAED,OAAO;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;QAE9B,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QAEnB,OAAO,OAAO,CAAC;IACnB,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/browser/history/commands.d.ts b/build/src/browser/history/commands.d.ts new file mode 100644 index 000000000..722ca3d88 --- /dev/null +++ b/build/src/browser/history/commands.d.ts @@ -0,0 +1,10 @@ +declare enum Scopes { + BROWSER = "b", + ELEMENT = "e" +} +declare const wdioBrowserCommands: string[]; +declare const wdioElementCommands: string[]; +export declare const getBrowserCommands: () => typeof wdioBrowserCommands; +export declare const getElementCommands: () => typeof wdioElementCommands; +export declare const createScope: (elementScope: boolean) => `${Scopes}`; +export {}; diff --git a/build/src/browser/history/commands.js b/build/src/browser/history/commands.js new file mode 100644 index 000000000..9fcdcebcc --- /dev/null +++ b/build/src/browser/history/commands.js @@ -0,0 +1,105 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createScope = exports.getElementCommands = exports.getBrowserCommands = void 0; +var Scopes; +(function (Scopes) { + Scopes["BROWSER"] = "b"; + Scopes["ELEMENT"] = "e"; +})(Scopes || (Scopes = {})); +const wdioBrowserCommands = [ + "$$", + "$", + "action", + "actions", + "call", + "custom$$", + "custom$", + "debug", + "deleteCookies", + "execute", + "executeAsync", + "getCookies", + "getPuppeteer", + "getWindowSize", + "keys", + "mock", + "mockClearAll", + "mockRestoreAll", + "newWindow", + "pause", + "react$$", + "react$", + "reloadSession", + "savePDF", + "saveRecordingScreen", + "saveScreenshot", + "scroll", + "setCookies", + "setTimeout", + "setWindowSize", + "switchWindow", + "throttle", + "touchAction", + "uploadFile", + "url", + "waitUntil", +]; +const wdioElementCommands = [ + "$$", + "$", + "addValue", + "clearValue", + "click", + "custom$", + "custom$$", + "doubleClick", + "dragAndDrop", + "getAttribute", + "getCSSProperty", + "getComputedRole", + "getComputedLabel", + "getHTML", + "getLocation", + "getProperty", + "getSize", + "getTagName", + "getText", + "getValue", + "isClickable", + "isDisplayed", + "isDisplayedInViewport", + "isEnabled", + "isEqual", + "isExisting", + "isFocused", + "isSelected", + "moveTo", + "nextElement", + "parentElement", + "previousElement", + "react$", + "react$$", + "saveScreenshot", + "scrollIntoView", + "selectByAttribute", + "selectByIndex", + "selectByVisibleText", + "setValue", + "shadow$", + "shadow$$", + "touchAction", + "waitForClickable", + "waitForDisplayed", + "waitForEnabled", + "waitForExist", + "waitUntil", +]; +const getBrowserCommands = () => wdioBrowserCommands; +exports.getBrowserCommands = getBrowserCommands; +const getElementCommands = () => wdioElementCommands; +exports.getElementCommands = getElementCommands; +const createScope = (elementScope) => { + return elementScope ? Scopes.ELEMENT : Scopes.BROWSER; +}; +exports.createScope = createScope; +//# sourceMappingURL=commands.js.map \ No newline at end of file diff --git a/build/src/browser/history/commands.js.map b/build/src/browser/history/commands.js.map new file mode 100644 index 000000000..ca0193746 --- /dev/null +++ b/build/src/browser/history/commands.js.map @@ -0,0 +1 @@ +{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../../src/browser/history/commands.ts"],"names":[],"mappings":";;;AAAA,IAAK,MAGJ;AAHD,WAAK,MAAM;IACP,uBAAa,CAAA;IACb,uBAAa,CAAA;AACjB,CAAC,EAHI,MAAM,KAAN,MAAM,QAGV;AAED,MAAM,mBAAmB,GAAG;IACxB,IAAI;IACJ,GAAG;IACH,QAAQ;IACR,SAAS;IACT,MAAM;IACN,UAAU;IACV,SAAS;IACT,OAAO;IACP,eAAe;IACf,SAAS;IACT,cAAc;IACd,YAAY;IACZ,cAAc;IACd,eAAe;IACf,MAAM;IACN,MAAM;IACN,cAAc;IACd,gBAAgB;IAChB,WAAW;IACX,OAAO;IACP,SAAS;IACT,QAAQ;IACR,eAAe;IACf,SAAS;IACT,qBAAqB;IACrB,gBAAgB;IAChB,QAAQ;IACR,YAAY;IACZ,YAAY;IACZ,eAAe;IACf,cAAc;IACd,UAAU;IACV,aAAa;IACb,YAAY;IACZ,KAAK;IACL,WAAW;CACd,CAAC;AAEF,MAAM,mBAAmB,GAAG;IACxB,IAAI;IACJ,GAAG;IACH,UAAU;IACV,YAAY;IACZ,OAAO;IACP,SAAS;IACT,UAAU;IACV,aAAa;IACb,aAAa;IACb,cAAc;IACd,gBAAgB;IAChB,iBAAiB;IACjB,kBAAkB;IAClB,SAAS;IACT,aAAa;IACb,aAAa;IACb,SAAS;IACT,YAAY;IACZ,SAAS;IACT,UAAU;IACV,aAAa;IACb,aAAa;IACb,uBAAuB;IACvB,WAAW;IACX,SAAS;IACT,YAAY;IACZ,WAAW;IACX,YAAY;IACZ,QAAQ;IACR,aAAa;IACb,eAAe;IACf,iBAAiB;IACjB,QAAQ;IACR,SAAS;IACT,gBAAgB;IAChB,gBAAgB;IAChB,mBAAmB;IACnB,eAAe;IACf,qBAAqB;IACrB,UAAU;IACV,SAAS;IACT,UAAU;IACV,aAAa;IACb,kBAAkB;IAClB,kBAAkB;IAClB,gBAAgB;IAChB,cAAc;IACd,WAAW;CACd,CAAC;AAEK,MAAM,kBAAkB,GAAG,GAA+B,EAAE,CAAC,mBAAmB,CAAC;AAA3E,QAAA,kBAAkB,sBAAyD;AACjF,MAAM,kBAAkB,GAAG,GAA+B,EAAE,CAAC,mBAAmB,CAAC;AAA3E,QAAA,kBAAkB,sBAAyD;AACjF,MAAM,WAAW,GAAG,CAAC,YAAqB,EAAe,EAAE;IAC9D,OAAO,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;AAC1D,CAAC,CAAC;AAFW,QAAA,WAAW,eAEtB"} \ No newline at end of file diff --git a/build/src/browser/history/index.d.ts b/build/src/browser/history/index.d.ts new file mode 100644 index 000000000..eae71736d --- /dev/null +++ b/build/src/browser/history/index.d.ts @@ -0,0 +1,4 @@ +export function initCommandHistory(session: any): Callstack; +export function runGroup(callstack: any, name: any, fn: any): any; +export function shouldPropagateFn(parentNode: any, currentNode: any): boolean; +import Callstack = require("./callstack"); diff --git a/build/src/browser/history/index.js b/build/src/browser/history/index.js new file mode 100644 index 000000000..259127c57 --- /dev/null +++ b/build/src/browser/history/index.js @@ -0,0 +1,101 @@ +"use strict"; +const Callstack = require("./callstack"); +const cmds = require("./commands"); +const { runWithHooks, normalizeCommandArgs, historyDataMap, isGroup } = require("./utils"); +const shouldNotWrapCommand = commandName => ["addCommand", "overwriteCommand", "extendOptions", "setMeta", "getMeta", "runStep"].includes(commandName); +const mkHistoryNode = ({ name, args, elementScope, key, overwrite, isGroup }) => { + const map = { + [historyDataMap.NAME]: name, + [historyDataMap.ARGS]: normalizeCommandArgs(name, args), + [historyDataMap.SCOPE]: cmds.createScope(elementScope), + [historyDataMap.KEY]: key, + }; + if (overwrite) { + map[historyDataMap.IS_OVERWRITTEN] = Number(overwrite); + } + if (isGroup) { + map[historyDataMap.IS_GROUP] = true; + } + return map; +}; +const runWithHistoryHooks = ({ callstack, nodeData, fn }) => { + nodeData.key = nodeData.key || Symbol(); + return runWithHooks({ + before: () => callstack.enter(mkHistoryNode(nodeData)), + fn, + after: () => callstack.leave(nodeData.key), + error: () => callstack.markError(exports.shouldPropagateFn), + }); +}; +const overwriteAddCommand = (session, callstack) => session.overwriteCommand("addCommand", (origCommand, name, wrapper, elementScope) => { + if (shouldNotWrapCommand(name)) { + return origCommand(name, wrapper, elementScope); + } + function decoratedWrapper(...args) { + return runWithHistoryHooks({ + callstack, + nodeData: { name, args, elementScope, overwrite: false }, + fn: () => wrapper.apply(this, args), + }); + } + return origCommand(name, decoratedWrapper, elementScope); +}); +const overwriteOverwriteCommand = (session, callstack) => session.overwriteCommand("overwriteCommand", (origCommand, name, wrapper, elementScope) => { + if (shouldNotWrapCommand(name)) { + return origCommand(name, wrapper, elementScope); + } + function decoratedWrapper(origFn, ...args) { + return runWithHistoryHooks({ + callstack, + nodeData: { name, args, elementScope, overwrite: true }, + fn: () => wrapper.apply(this, [origFn, ...args]), + }); + } + return origCommand(name, decoratedWrapper, elementScope); +}); +const overwriteCommands = ({ session, callstack, commands, elementScope }) => commands.forEach(name => { + function decoratedWrapper(origFn, ...args) { + return runWithHistoryHooks({ + callstack, + nodeData: { name, args, elementScope, overwrite: false }, + fn: () => origFn(...args), + }); + } + session.overwriteCommand(name, decoratedWrapper, elementScope); +}); +const overwriteBrowserCommands = (session, callstack) => overwriteCommands({ + session, + callstack, + commands: cmds.getBrowserCommands(), + elementScope: false, +}); +const overwriteElementCommands = (session, callstack) => overwriteCommands({ + session, + callstack, + commands: cmds.getElementCommands(), + elementScope: true, +}); +const overwriteRunStepCommand = (session, callstack) => session.overwriteCommand("runStep", (origCommand, stepName, stepCb) => { + return exports.runGroup(callstack, stepName, () => origCommand(stepName, stepCb)); +}); +exports.initCommandHistory = session => { + const callstack = new Callstack(); + overwriteAddCommand(session, callstack); + overwriteBrowserCommands(session, callstack); + overwriteElementCommands(session, callstack); + overwriteOverwriteCommand(session, callstack); + overwriteRunStepCommand(session, callstack); + return callstack; +}; +exports.runGroup = (callstack, name, fn) => { + if (!callstack) { + return fn(); + } + return runWithHistoryHooks({ + callstack, + nodeData: { name, isGroup: true }, + fn, + }); +}; +exports.shouldPropagateFn = (parentNode, currentNode) => isGroup(parentNode) || isGroup(currentNode); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/browser/history/index.js.map b/build/src/browser/history/index.js.map new file mode 100644 index 000000000..bfeca3d01 --- /dev/null +++ b/build/src/browser/history/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/browser/history/index.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/browser/history/utils.d.ts b/build/src/browser/history/utils.d.ts new file mode 100644 index 000000000..b564f4d7d --- /dev/null +++ b/build/src/browser/history/utils.d.ts @@ -0,0 +1,21 @@ +export function normalizeCommandArgs(name: any, args?: any[]): any[]; +export namespace historyDataMap { + let NAME: string; + let ARGS: string; + let SCOPE: string; + let DURATION: string; + let TIME_START: string; + let TIME_END: string; + let IS_OVERWRITTEN: string; + let IS_GROUP: string; + let IS_FAILED: string; + let CHILDREN: string; + let KEY: string; +} +export function isGroup(node: any): boolean; +export function runWithHooks({ fn, before, after, error }: { + fn: any; + before: any; + after: any; + error: any; +}): any; diff --git a/build/src/browser/history/utils.js b/build/src/browser/history/utils.js new file mode 100644 index 000000000..c0a267f83 --- /dev/null +++ b/build/src/browser/history/utils.js @@ -0,0 +1,61 @@ +"use strict"; +const _ = require("lodash"); +const MAX_STRING_LENGTH = 50; +exports.normalizeCommandArgs = (name, args = []) => { + if (name === "execute") { + return ["code"]; + } + return args.map(arg => { + if (_.isString(arg)) { + return _.truncate(arg, { length: MAX_STRING_LENGTH }); + } + if (_.isPlainObject(arg)) { + return "obj"; + } + return arg; + }); +}; +exports.historyDataMap = { + NAME: "n", + ARGS: "a", + SCOPE: "s", + DURATION: "d", + TIME_START: "ts", + TIME_END: "te", + IS_OVERWRITTEN: "o", + IS_GROUP: "g", + IS_FAILED: "f", + CHILDREN: "c", + KEY: "k", +}; +const isPromise = val => typeof _.get(val, "then") === "function"; +exports.isGroup = node => Boolean(node && node[exports.historyDataMap.IS_GROUP]); +exports.runWithHooks = ({ fn, before, after, error }) => { + let isReturnedValuePromise = false; + before(); + try { + const value = fn(); + if (isPromise(value)) { + isReturnedValuePromise = true; + return value + .catch(err => { + error(); + throw err; + }) + .finally(after); + } + return value; + } + catch (err) { + if (!isReturnedValuePromise) { + error(); + throw err; + } + } + finally { + if (!isReturnedValuePromise) { + after(); + } + } +}; +//# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/build/src/browser/history/utils.js.map b/build/src/browser/history/utils.js.map new file mode 100644 index 000000000..1d217a6d8 --- /dev/null +++ b/build/src/browser/history/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/browser/history/utils.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE5B,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B,OAAO,CAAC,oBAAoB,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,EAAE;IAC/C,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACrB,OAAO,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;QAClB,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAClB,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,IAAI,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,OAAO,GAAG,CAAC;IACf,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,OAAO,CAAC,cAAc,GAAG;IACrB,IAAI,EAAE,GAAG;IACT,IAAI,EAAE,GAAG;IACT,KAAK,EAAE,GAAG;IACV,QAAQ,EAAE,GAAG;IACb,UAAU,EAAE,IAAI;IAChB,QAAQ,EAAE,IAAI;IACd,cAAc,EAAE,GAAG;IACnB,QAAQ,EAAE,GAAG;IACb,SAAS,EAAE,GAAG;IACd,QAAQ,EAAE,GAAG;IACb,GAAG,EAAE,GAAG;CACX,CAAC;AAEF,MAAM,SAAS,GAAG,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,UAAU,CAAC;AAElE,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;AAEjF,OAAO,CAAC,YAAY,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;IACpD,IAAI,sBAAsB,GAAG,KAAK,CAAC;IAEnC,MAAM,EAAE,CAAC;IAET,IAAI,CAAC;QACD,MAAM,KAAK,GAAG,EAAE,EAAE,CAAC;QAEnB,IAAI,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YACnB,sBAAsB,GAAG,IAAI,CAAC;YAE9B,OAAO,KAAK;iBACP,KAAK,CAAC,GAAG,CAAC,EAAE;gBACT,KAAK,EAAE,CAAC;gBAER,MAAM,GAAG,CAAC;YACd,CAAC,CAAC;iBACD,OAAO,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;QAED,OAAO,KAAK,CAAC;IACjB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAC1B,KAAK,EAAE,CAAC;YAER,MAAM,GAAG,CAAC;QACd,CAAC;IACL,CAAC;YAAS,CAAC;QACP,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAC1B,KAAK,EAAE,CAAC;QACZ,CAAC;IACL,CAAC;AACL,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/browser/new-browser.d.ts b/build/src/browser/new-browser.d.ts new file mode 100644 index 000000000..97009d905 --- /dev/null +++ b/build/src/browser/new-browser.d.ts @@ -0,0 +1,32 @@ +export = NewBrowser; +declare class NewBrowser extends Browser { + init(): Promise; + reset(): Promise; + quit(): Promise; + _createSession(): Promise; + _setPageLoadTimeout(): Promise; + _getSessionOpts(): { + protocol: any; + hostname: any; + port: number; + path: any; + queryParams: { + [k: string]: string; + }; + capabilities: any; + automationProtocol: any; + connectionRetryTimeout: any; + connectionRetryCount: number; + baseUrl: any; + waitforTimeout: any; + waitforInterval: any; + }; + _extendCapabilities(config: any): any; + _addHeadlessCapability(headless: any, capabilities: any): any; + _extendCapabilitiesByVersion(): any; + _getGridHost(url: any): any; + _getQueryParams(query: any): { + [k: string]: string; + }; +} +import Browser = require("./browser"); diff --git a/build/src/browser/new-browser.js b/build/src/browser/new-browser.js new file mode 100644 index 000000000..3087ab9fc --- /dev/null +++ b/build/src/browser/new-browser.js @@ -0,0 +1,144 @@ +"use strict"; +const { URLSearchParams } = require("url"); +const URI = require("urijs"); +const _ = require("lodash"); +const webdriverio = require("webdriverio"); +const Browser = require("./browser"); +const signalHandler = require("../signal-handler"); +const history = require("./history"); +const logger = require("../utils/logger"); +const DEFAULT_PORT = 4444; +const headlessBrowserOptions = { + chrome: { + capabilityName: "goog:chromeOptions", + args: ["headless", "disable-gpu"], + }, + firefox: { + capabilityName: "moz:firefoxOptions", + args: ["-headless"], + }, + msedge: { + capabilityName: "ms:edgeOptions", + args: ["--headless"], + }, + edge: { + capabilityName: "ms:edgeOptions", + args: ["--headless"], + }, +}; +module.exports = class NewBrowser extends Browser { + constructor(config, opts) { + super(config, opts); + signalHandler.on("exit", () => this.quit()); + } + async init() { + this._session = await this._createSession(); + this._addSteps(); + this._addHistory(); + await history.runGroup(this._callstackHistory, "hermione: init browser", async () => { + 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(); + } + catch (e) { + logger.warn(`WARNING: Can not close session: ${e.message}`); + } + } + _createSession() { + const sessionOpts = this._getSessionOpts(); + return webdriverio.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") { + logger.warn(`WARNING: Can not set page load timeout: ${e.message}`); + } + else { + throw e; + } + } + } + _getSessionOpts() { + const config = this._config; + const gridUri = new URI(config.gridUrl); + const capabilities = this._extendCapabilities(config); + 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: config.automationProtocol, + connectionRetryTimeout: config.sessionRequestTimeout || config.httpTimeout, + connectionRetryCount: 0, // hermione has its own advanced retries + baseUrl: config.baseUrl, + waitforTimeout: config.waitTimeout, + waitforInterval: config.waitInterval, + ...this._getSessionOptsFromConfig(), + }; + return options; + } + _extendCapabilities(config) { + const capabilitiesExtendedByVersion = this.version + ? this._extendCapabilitiesByVersion() + : config.desiredCapabilities; + const capabilitiesWithAddedHeadless = this._addHeadlessCapability(config.headless, capabilitiesExtendedByVersion); + return capabilitiesWithAddedHeadless; + } + _addHeadlessCapability(headless, capabilities) { + if (!headless) { + return capabilities; + } + const capabilitySettings = headlessBrowserOptions[capabilities.browserName]; + if (!capabilitySettings) { + logger.warn(`WARNING: Headless setting is not supported for ${capabilities.browserName} browserName`); + return capabilities; + } + const browserCapabilities = capabilities[capabilitySettings.capabilityName] ?? {}; + capabilities[capabilitySettings.capabilityName] = { + ...browserCapabilities, + args: [...(browserCapabilities.args ?? []), ...capabilitySettings.args], + }; + return capabilities; + } + _extendCapabilitiesByVersion() { + const { desiredCapabilities, sessionEnvFlags } = this._config; + const versionKeyName = desiredCapabilities.browserVersion || sessionEnvFlags.isW3C ? "browserVersion" : "version"; + return _.assign({}, desiredCapabilities, { [versionKeyName]: this.version }); + } + _getGridHost(url) { + return new URI({ + username: url.username(), + password: url.password(), + hostname: url.hostname(), + }) + .toString() + .slice(2); // URIjs leaves `//` prefix, removing it + } + _getQueryParams(query) { + if (_.isEmpty(query)) { + return {}; + } + const urlParams = new URLSearchParams(query); + return Object.fromEntries(urlParams); + } +}; +//# sourceMappingURL=new-browser.js.map \ No newline at end of file diff --git a/build/src/browser/new-browser.js.map b/build/src/browser/new-browser.js.map new file mode 100644 index 000000000..df715dc79 --- /dev/null +++ b/build/src/browser/new-browser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"new-browser.js","sourceRoot":"","sources":["../../../src/browser/new-browser.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/browser/screen-shooter/index.d.ts b/build/src/browser/screen-shooter/index.d.ts new file mode 100644 index 000000000..133352b09 --- /dev/null +++ b/build/src/browser/screen-shooter/index.d.ts @@ -0,0 +1,9 @@ +export = ScreenShooter; +declare class ScreenShooter { + static create(browser: any): import("."); + constructor(browser: any); + _browser: any; + capture(page: any, opts?: {}): Promise; + _extendScreenshot(viewport: any, page: any, opts: any): Promise; + _extendImage(viewport: any, page: any, opts: any): Promise; +} diff --git a/build/src/browser/screen-shooter/index.js b/build/src/browser/screen-shooter/index.js new file mode 100644 index 000000000..01021d79f --- /dev/null +++ b/build/src/browser/screen-shooter/index.js @@ -0,0 +1,36 @@ +"use strict"; +const Viewport = require("./viewport"); +module.exports = class ScreenShooter { + static create(browser) { + return new this(browser); + } + constructor(browser) { + this._browser = browser; + } + async capture(page, opts = {}) { + const { allowViewportOverflow, compositeImage, screenshotDelay, selectorToScroll } = opts; + const viewportOpts = { allowViewportOverflow, compositeImage }; + const cropImageOpts = { screenshotDelay, compositeImage, selectorToScroll }; + const capturedImage = await this._browser.captureViewportImage(page, screenshotDelay); + const viewport = Viewport.create(page, capturedImage, viewportOpts); + await viewport.handleImage(capturedImage); + return this._extendScreenshot(viewport, page, cropImageOpts); + } + async _extendScreenshot(viewport, page, opts) { + let shouldExtend = viewport.validate(this._browser); + while (shouldExtend) { + await this._extendImage(viewport, page, opts); + shouldExtend = viewport.validate(this._browser); + } + return viewport.composite(); + } + async _extendImage(viewport, page, opts) { + const physicalScrollHeight = Math.min(viewport.getVerticalOverflow(), page.viewport.height); + const logicalScrollHeight = Math.ceil(physicalScrollHeight / page.pixelRatio); + await this._browser.scrollBy({ x: 0, y: logicalScrollHeight, selector: opts.selectorToScroll }); + page.viewport.top += physicalScrollHeight; + const newImage = await this._browser.captureViewportImage(page, opts.screenshotDelay); + await viewport.extendBy(physicalScrollHeight, newImage); + } +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/browser/screen-shooter/index.js.map b/build/src/browser/screen-shooter/index.js.map new file mode 100644 index 000000000..6cb112abb --- /dev/null +++ b/build/src/browser/screen-shooter/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/browser/screen-shooter/index.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;AAEvC,MAAM,CAAC,OAAO,GAAG,MAAM,aAAa;IAChC,MAAM,CAAC,MAAM,CAAC,OAAO;QACjB,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED,YAAY,OAAO;QACf,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE;QACzB,MAAM,EAAE,qBAAqB,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC;QAC1F,MAAM,YAAY,GAAG,EAAE,qBAAqB,EAAE,cAAc,EAAE,CAAC;QAC/D,MAAM,aAAa,GAAG,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAC;QAE5E,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QACtF,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC;QACpE,MAAM,QAAQ,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;QAE1C,OAAO,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;IACjE,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI;QACxC,IAAI,YAAY,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEpD,OAAO,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAE9C,YAAY,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,QAAQ,CAAC,SAAS,EAAE,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI;QACnC,MAAM,oBAAoB,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,mBAAmB,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC5F,MAAM,mBAAmB,GAAG,IAAI,CAAC,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;QAE9E,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,mBAAmB,EAAE,QAAQ,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;QAEhG,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,oBAAoB,CAAC;QAE1C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAEtF,MAAM,QAAQ,CAAC,QAAQ,CAAC,oBAAoB,EAAE,QAAQ,CAAC,CAAC;IAC5D,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/browser/screen-shooter/viewport/coord-validator/errors/height-viewport-error.d.ts b/build/src/browser/screen-shooter/viewport/coord-validator/errors/height-viewport-error.d.ts new file mode 100644 index 000000000..2eb560e89 --- /dev/null +++ b/build/src/browser/screen-shooter/viewport/coord-validator/errors/height-viewport-error.d.ts @@ -0,0 +1,6 @@ +/** + * Height of the element is larger than viewport + */ +export declare class HeightViewportError extends Error { + constructor(message: string); +} diff --git a/build/src/browser/screen-shooter/viewport/coord-validator/errors/height-viewport-error.js b/build/src/browser/screen-shooter/viewport/coord-validator/errors/height-viewport-error.js new file mode 100644 index 000000000..3d96eb5de --- /dev/null +++ b/build/src/browser/screen-shooter/viewport/coord-validator/errors/height-viewport-error.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.HeightViewportError = void 0; +/** + * Height of the element is larger than viewport + */ +class HeightViewportError extends Error { + constructor(message) { + super(message); + this.name = this.constructor.name; + } +} +exports.HeightViewportError = HeightViewportError; +//# sourceMappingURL=height-viewport-error.js.map \ No newline at end of file diff --git a/build/src/browser/screen-shooter/viewport/coord-validator/errors/height-viewport-error.js.map b/build/src/browser/screen-shooter/viewport/coord-validator/errors/height-viewport-error.js.map new file mode 100644 index 000000000..49906ad23 --- /dev/null +++ b/build/src/browser/screen-shooter/viewport/coord-validator/errors/height-viewport-error.js.map @@ -0,0 +1 @@ +{"version":3,"file":"height-viewport-error.js","sourceRoot":"","sources":["../../../../../../../src/browser/screen-shooter/viewport/coord-validator/errors/height-viewport-error.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,MAAa,mBAAoB,SAAQ,KAAK;IAC1C,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IACtC,CAAC;CACJ;AAND,kDAMC"} \ No newline at end of file diff --git a/build/src/browser/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.d.ts b/build/src/browser/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.d.ts new file mode 100644 index 000000000..1f8b090e9 --- /dev/null +++ b/build/src/browser/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.d.ts @@ -0,0 +1,6 @@ +/** + * Position of an element is outside of a viewport left, top or right bounds + */ +export declare class OffsetViewportError extends Error { + constructor(message: string); +} diff --git a/build/src/browser/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.js b/build/src/browser/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.js new file mode 100644 index 000000000..9ff0c1e4b --- /dev/null +++ b/build/src/browser/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.OffsetViewportError = void 0; +/** + * Position of an element is outside of a viewport left, top or right bounds + */ +class OffsetViewportError extends Error { + constructor(message) { + super(message); + this.name = this.constructor.name; + } +} +exports.OffsetViewportError = OffsetViewportError; +//# sourceMappingURL=offset-viewport-error.js.map \ No newline at end of file diff --git a/build/src/browser/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.js.map b/build/src/browser/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.js.map new file mode 100644 index 000000000..4315c599f --- /dev/null +++ b/build/src/browser/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.js.map @@ -0,0 +1 @@ +{"version":3,"file":"offset-viewport-error.js","sourceRoot":"","sources":["../../../../../../../src/browser/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,MAAa,mBAAoB,SAAQ,KAAK;IAC1C,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IACtC,CAAC;CACJ;AAND,kDAMC"} \ No newline at end of file diff --git a/build/src/browser/screen-shooter/viewport/coord-validator/index.d.ts b/build/src/browser/screen-shooter/viewport/coord-validator/index.d.ts new file mode 100644 index 000000000..c293f7371 --- /dev/null +++ b/build/src/browser/screen-shooter/viewport/coord-validator/index.d.ts @@ -0,0 +1,43 @@ +export = CoordValidator; +declare class CoordValidator { + static create(...args: any[]): import("."); + /** + * @param {Browser} browser session instance + * @param {Object} opts + * @param {Boolean} [opts.allowViewportOverflow] ignore OffsetViewportError + * @param {Boolean} [opts.compositeImage] allow area bottom bound to be outside of viewport + */ + constructor(browser: Browser, opts?: { + allowViewportOverflow?: boolean | undefined; + compositeImage?: boolean | undefined; + }); + _log: any; + _opts: { + allowViewportOverflow?: boolean | undefined; + compositeImage?: boolean | undefined; + }; + /** + * Validates compatibility of viewport and crop area coordinates + * @param {Object} viewport + * @param {Object} cropArea + */ + validate(viewport: Object, cropArea: Object): true | HeightViewportError | OffsetViewportError | undefined; + /** + * Reports error if crop area is outside of viewport + * @returns {OffsetViewportError} + * @private + */ + private _reportOffsetViewportError; + /** + * This case is handled specially because of Opera 12 browser. + * Problem, described in error message occurs there much more often then + * for other browsers and has different workaround + * @param {Object} viewport + * @param {Object} cropArea - crop area + * @returns {HeightViewportError} + * @private + */ + private _reportHeightViewportError; +} +import { HeightViewportError } from "./errors/height-viewport-error"; +import { OffsetViewportError } from "./errors/offset-viewport-error"; diff --git a/build/src/browser/screen-shooter/viewport/coord-validator/index.js b/build/src/browser/screen-shooter/viewport/coord-validator/index.js new file mode 100644 index 000000000..ed203d8ff --- /dev/null +++ b/build/src/browser/screen-shooter/viewport/coord-validator/index.js @@ -0,0 +1,76 @@ +"use strict"; +const debug = require("debug"); +const { HeightViewportError } = require("./errors/height-viewport-error"); +const { OffsetViewportError } = require("./errors/offset-viewport-error"); +const isOutsideOfViewport = (viewport, cropArea) => cropArea.top < 0 || cropArea.left < 0 || cropArea.left + cropArea.width > viewport.width; +module.exports = class CoordValidator { + static create(...args) { + return new CoordValidator(...args); + } + /** + * @param {Browser} browser session instance + * @param {Object} opts + * @param {Boolean} [opts.allowViewportOverflow] ignore OffsetViewportError + * @param {Boolean} [opts.compositeImage] allow area bottom bound to be outside of viewport + */ + constructor(browser, opts = {}) { + this._log = debug("coord-validator:" + browser.id); + this._opts = opts; + } + /** + * Validates compatibility of viewport and crop area coordinates + * @param {Object} viewport + * @param {Object} cropArea + */ + validate(viewport, cropArea) { + this._log("viewport size", viewport); + this._log("crop area", cropArea); + if (this._opts.allowViewportOverflow && !this._opts.compositeImage) { + return; + } + if (!this._opts.allowViewportOverflow && isOutsideOfViewport(viewport, cropArea)) { + return this._reportOffsetViewportError(); + } + if (cropArea.top + cropArea.height > viewport.top + viewport.height) { + return this._opts.compositeImage || this._reportHeightViewportError(viewport, cropArea); + } + } + /** + * Reports error if crop area is outside of viewport + * @returns {OffsetViewportError} + * @private + */ + _reportOffsetViewportError() { + this._log("crop area is outside of the viewport left, top or right bounds"); + const message = `Can not capture the specified region of the viewport. + Position of the region is outside of the viewport left, top or right bounds. + Check that elements: + - does not overflows the document + - does not overflows browser viewport + Alternatively, you can increase browser window size using + "setWindowSize" or "windowSize" option in the config file. + But if viewport overflow is expected behavior then you can use + option "allowViewportOverflow" in "assertView" command.`; + throw new OffsetViewportError(message); + } + /** + * This case is handled specially because of Opera 12 browser. + * Problem, described in error message occurs there much more often then + * for other browsers and has different workaround + * @param {Object} viewport + * @param {Object} cropArea - crop area + * @returns {HeightViewportError} + * @private + */ + _reportHeightViewportError(viewport, cropArea) { + this._log("crop area bottom bound is outside of the viewport height"); + const message = `Can not capture the specified region of the viewport. + The region bottom bound is outside of the viewport height. + Alternatively, you can test such cases by setting "true" value to option "compositeImage" in the config file + or setting "false" to "compositeImage" and "true" to option "allowViewportOverflow" in "assertView" command. + Element position: ${cropArea.left}, ${cropArea.top}; size: ${cropArea.width}, ${cropArea.height}. + Viewport size: ${viewport.width}, ${viewport.height}.`; + throw new HeightViewportError(message); + } +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/browser/screen-shooter/viewport/coord-validator/index.js.map b/build/src/browser/screen-shooter/viewport/coord-validator/index.js.map new file mode 100644 index 000000000..b26f4341d --- /dev/null +++ b/build/src/browser/screen-shooter/viewport/coord-validator/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/browser/screen-shooter/viewport/coord-validator/index.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAC/B,MAAM,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,gCAAgC,CAAC,CAAC;AAC1E,MAAM,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,gCAAgC,CAAC,CAAC;AAE1E,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAC/C,QAAQ,CAAC,GAAG,GAAG,CAAC,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,IAAI,QAAQ,CAAC,IAAI,GAAG,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;AAE7F,MAAM,CAAC,OAAO,GAAG,MAAM,cAAc;IACjC,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI;QACjB,OAAO,IAAI,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;IACvC,CAAC;IAED;;;;;OAKG;IACH,YAAY,OAAO,EAAE,IAAI,GAAG,EAAE;QAC1B,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,kBAAkB,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACtB,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ;QACvB,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAEjC,IAAI,IAAI,CAAC,KAAK,CAAC,qBAAqB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;YACjE,OAAO;QACX,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,qBAAqB,IAAI,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;YAC/E,OAAO,IAAI,CAAC,0BAA0B,EAAE,CAAC;QAC7C,CAAC;QAED,IAAI,QAAQ,CAAC,GAAG,GAAG,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,GAAG,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClE,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,IAAI,IAAI,CAAC,0BAA0B,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC5F,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,0BAA0B;QACtB,IAAI,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;QAE5E,MAAM,OAAO,GAAG;;;;;;;;oEAQ4C,CAAC;QAE7D,MAAM,IAAI,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;;;OAQG;IACH,0BAA0B,CAAC,QAAQ,EAAE,QAAQ;QACzC,IAAI,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;QAEtE,MAAM,OAAO,GAAG;;;;gCAIQ,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,GAAG,WAAW,QAAQ,CAAC,KAAK,KAAK,QAAQ,CAAC,MAAM;6BAC9E,QAAQ,CAAC,KAAK,KAAK,QAAQ,CAAC,MAAM,GAAG,CAAC;QAE3D,MAAM,IAAI,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/browser/screen-shooter/viewport/index.d.ts b/build/src/browser/screen-shooter/viewport/index.d.ts new file mode 100644 index 000000000..0130fcc94 --- /dev/null +++ b/build/src/browser/screen-shooter/viewport/index.d.ts @@ -0,0 +1,56 @@ +export = Viewport; +declare class Viewport { + static create(...args: any[]): import("."); + constructor(page: any, image: any, opts: any); + _viewport: any; + _captureArea: { + left: number; + top: number; + width: number; + height: number; + }; + _ignoreAreas: any; + _image: any; + _opts: any; + _summaryHeight: number; + validate(browser: any): true | import("./coord-validator/errors/height-viewport-error").HeightViewportError | import("./coord-validator/errors/offset-viewport-error").OffsetViewportError | undefined; + ignoreAreas(image: any, imageArea: any): Promise; + handleImage(image: any, area?: {}): Promise; + composite(): Promise; + save(path: any): Promise; + extendBy(physicalScrollHeight: any, newImage: any): Promise; + getVerticalOverflow(): number; + _sanitize(area: any): { + left: number; + top: number; + width: number; + height: number; + }; + _getIntersection(...areas: any[]): { + left: number; + top: number; + width: number; + height: number; + } | null; + _shiftArea(area: any, { left, top }?: { + left: any; + top: any; + }): { + left: any; + top: any; + width: any; + height: any; + }; + _transformToCaptureArea(area: any): { + left: any; + top: any; + width: any; + height: any; + }; + _transformToViewportOrigin(area: any): { + left: any; + top: any; + width: any; + height: any; + }; +} diff --git a/build/src/browser/screen-shooter/viewport/index.js b/build/src/browser/screen-shooter/viewport/index.js new file mode 100644 index 000000000..2eaf5ccde --- /dev/null +++ b/build/src/browser/screen-shooter/viewport/index.js @@ -0,0 +1,104 @@ +"use strict"; +const _ = require("lodash"); +const CoordValidator = require("./coord-validator"); +module.exports = class Viewport { + static create(...args) { + return new this(...args); + } + constructor(page, image, opts) { + this._viewport = _.clone(page.viewport); + this._captureArea = this._sanitize(page.captureArea); + this._ignoreAreas = page.ignoreAreas; + this._image = image; + this._opts = opts; + this._summaryHeight = 0; + } + validate(browser) { + const coordValidator = CoordValidator.create(browser, this._opts); + return coordValidator.validate(this._viewport, this._captureArea); + } + async ignoreAreas(image, imageArea) { + for (const area of this._ignoreAreas) { + const imageClearArea = this._getIntersection(area, imageArea); + if (imageClearArea !== null) { + await image.addClear(this._shiftArea(imageClearArea, { left: -imageArea.left, top: -imageArea.top })); + } + } + image.applyClear(); + } + async handleImage(image, area = {}) { + const { width, height } = await image.getSize(); + _.defaults(area, { left: 0, top: 0, width, height }); + const capturedArea = this._transformToCaptureArea(area); + await this.ignoreAreas(image, this._shiftArea(capturedArea, { left: -area.left, top: -area.top })); + await image.crop(this._sanitize(this._transformToViewportOrigin(capturedArea))); + this._summaryHeight += capturedArea.height; + } + async composite() { + await this._image.applyJoin(); + return this._image; + } + async save(path) { + return this._image.save(path); + } + async extendBy(physicalScrollHeight, newImage) { + this._viewport.height += physicalScrollHeight; + const { width, height } = await newImage.getSize(); + await this.handleImage(newImage, { + left: 0, + top: height - physicalScrollHeight, + width, + height: physicalScrollHeight, + }); + this._image.addJoin(newImage); + } + getVerticalOverflow() { + return getAreaBottom(this._captureArea) - getAreaBottom(this._viewport); + } + _sanitize(area) { + return { + left: Math.max(area.left, 0), + top: Math.max(area.top, 0), + width: Math.max(area.width, 0), + height: Math.max(area.height, 0), + }; + } + _getIntersection(...areas) { + const top = Math.max(...areas.map(area => area.top)); + const bottom = Math.min(...areas.map(getAreaBottom)); + const left = Math.max(...areas.map(area => area.left)); + const right = Math.min(...areas.map(getAreaRight)); + if (left >= right || top >= bottom) { + return null; + } + return { left, top, width: right - left, height: bottom - top }; + } + _shiftArea(area, { left, top } = {}) { + left = left || 0; + top = top || 0; + return { + left: area.left + left, + top: area.top + top, + width: area.width, + height: area.height, + }; + } + _transformToCaptureArea(area) { + const shiftX = area.left - this._viewport.left; + const shiftY = area.top - this._viewport.top; + const shiftedImageArea = this._shiftArea(area, { top: this._summaryHeight }); + const shiftedCaptureArea = this._sanitize(this._shiftArea(this._captureArea, { left: shiftX, top: shiftY })); + const intersectingArea = this._getIntersection(shiftedImageArea, shiftedCaptureArea) || shiftedImageArea; + return this._shiftArea(intersectingArea, { left: this._viewport.left, top: this._viewport.top }); + } + _transformToViewportOrigin(area) { + return this._shiftArea(area, { left: -this._viewport.left, top: -this._viewport.top - this._summaryHeight }); + } +}; +function getAreaBottom(area) { + return area.top + area.height; +} +function getAreaRight(area) { + return area.left + area.width; +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/browser/screen-shooter/viewport/index.js.map b/build/src/browser/screen-shooter/viewport/index.js.map new file mode 100644 index 000000000..55ca91c44 --- /dev/null +++ b/build/src/browser/screen-shooter/viewport/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/browser/screen-shooter/viewport/index.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE5B,MAAM,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAEpD,MAAM,CAAC,OAAO,GAAG,MAAM,QAAQ;IAC3B,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI;QACjB,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,YAAY,IAAI,EAAE,KAAK,EAAE,IAAI;QACzB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC;QACrC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,QAAQ,CAAC,OAAO;QACZ,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAElE,OAAO,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,SAAS;QAC9B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACnC,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAE9D,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;gBAC1B,MAAM,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAC1G,CAAC;QACL,CAAC;QAED,KAAK,CAAC,UAAU,EAAE,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE;QAC9B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;QAChD,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACrD,MAAM,YAAY,GAAG,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;QAExD,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACnG,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,0BAA0B,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAEhF,IAAI,CAAC,cAAc,IAAI,YAAY,CAAC,MAAM,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,SAAS;QACX,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QAE9B,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAI;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,oBAAoB,EAAE,QAAQ;QACzC,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,oBAAoB,CAAC;QAC9C,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;QAEnD,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE;YAC7B,IAAI,EAAE,CAAC;YACP,GAAG,EAAE,MAAM,GAAG,oBAAoB;YAClC,KAAK;YACL,MAAM,EAAE,oBAAoB;SAC/B,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED,mBAAmB;QACf,OAAO,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5E,CAAC;IAED,SAAS,CAAC,IAAI;QACV,OAAO;YACH,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5B,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YAC1B,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;YAC9B,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;SACnC,CAAC;IACN,CAAC;IAED,gBAAgB,CAAC,GAAG,KAAK;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;QACrD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACvD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;QAEnD,IAAI,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI,MAAM,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,EAAE,CAAC;IACpE,CAAC;IAED,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE;QAC/B,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC;QACjB,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;QAEf,OAAO;YACH,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,IAAI;YACtB,GAAG,EAAE,IAAI,CAAC,GAAG,GAAG,GAAG;YACnB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;SACtB,CAAC;IACN,CAAC;IAED,uBAAuB,CAAC,IAAI;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;QAC7C,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;QAC7E,MAAM,kBAAkB,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QAC7G,MAAM,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,kBAAkB,CAAC,IAAI,gBAAgB,CAAC;QAEzG,OAAO,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC;IACrG,CAAC;IAED,0BAA0B,CAAC,IAAI;QAC3B,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;IACjH,CAAC;CACJ,CAAC;AAEF,SAAS,aAAa,CAAC,IAAI;IACvB,OAAO,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC;AAClC,CAAC;AAED,SAAS,YAAY,CAAC,IAAI;IACtB,OAAO,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;AAClC,CAAC"} \ No newline at end of file diff --git a/build/src/browser/types.d.ts b/build/src/browser/types.d.ts new file mode 100644 index 000000000..450cc43e9 --- /dev/null +++ b/build/src/browser/types.d.ts @@ -0,0 +1,121 @@ +/// +import type { AssertViewCommand, AssertViewElementCommand } from "./commands/types"; +import type { BrowserConfig } from "./../config/browser-config"; +import type { AssertViewResult, RunnerTest, RunnerHook } from "../types"; +export interface BrowserMeta { + pid: number; + browserVersion: string; + [name: string]: unknown; +} +export interface Browser { + publicAPI: WebdriverIO.Browser; + config: BrowserConfig; + state: Record; + applyState: (state: Record) => void; +} +declare global { + namespace WebdriverIO { + interface Browser { + getMeta(): Promise; + getMeta(key: string): Promise; + setMeta(key: string, value: unknown): Promise; + extendOptions(opts: { + [name: string]: unknown; + }): Promise; + /** + * Takes a screenshot of the passed selector and compares the received screenshot with the reference. + * + * @remarks + * For more details, see {@link https://github.com/gemini-testing/hermione#assertview documentation}. + * + * @example + * ```ts + * + * it('some test', async function() { + * await this.browser.url('some/url'); + * await this.browser.assertView('plain', '.button', { + * ignoreElements: ['.link'], + * tolerance: 2.3, + * antialiasingTolerance: 4, + * allowViewportOverflow: true, + * captureElementFromTop: true, + * compositeImage: true, + * screenshotDelay: 600, + * selectorToScroll: '.modal' + * }); + *}); + * ``` + * + * @param state state name, should be unique within one test + * @param selectors DOM-node selector that you need to capture + * @param opts additional options, currently available: + * "ignoreElements", "tolerance", "antialiasingTolerance", "allowViewportOverflow", "captureElementFromTop", + * "compositeImage", "screenshotDelay", "selectorToScroll" + */ + assertView: AssertViewCommand; + /** + * Command that allows to add human-readable description for commands in history + * + * @remarks + * For more details, see {@link https://github.com/gemini-testing/hermione#runstep documentation} + * + * @example + * ```ts + * it('some test', async function () { + * await this.browser.runStep('step name', async () => { + * await this.browser.url('some/url'); + * ... + * }); + * }) + * ``` + * + * @param stepName step name + * @param stepCb step callback + * @returns {Promise} value, returned by `stepCb` + */ + runStep(stepName: string, stepCb: () => Promise | unknown): Promise; + executionContext: (RunnerTest | RunnerHook) & { + hermioneCtx: { + assertViewResults: Array; + }; + ctx: { + browser: WebdriverIO.Browser; + currentTest: RunnerTest; + }; + }; + } + interface Element { + /** + * Takes a screenshot of the element and compares the received screenshot with the reference. + * + * @remarks + * For more details, see {@link https://github.com/gemini-testing/hermione#assertview documentation}. + * + * @example + * ```ts + * + * it('some test', async function() { + * await this.browser.url('some/url'); + * const button = await this.browser.$('.button'); + * await button.assertView('plain', { + * ignoreElements: ['.link'], + * tolerance: 2.3, + * antialiasingTolerance: 4, + * allowViewportOverflow: true, + * captureElementFromTop: true, + * compositeImage: true, + * screenshotDelay: 600, + * selectorToScroll: '.modal' + * }); + *}); + * ``` + * + * @param state state name, should be unique within one test + * @param opts additional options, currently available: + * "ignoreElements", "tolerance", "antialiasingTolerance", "allowViewportOverflow", "captureElementFromTop", + * "compositeImage", "screenshotDelay", "selectorToScroll" + */ + assertView: AssertViewElementCommand; + } + } +} diff --git a/build/src/browser/types.js b/build/src/browser/types.js new file mode 100644 index 000000000..11e638d1e --- /dev/null +++ b/build/src/browser/types.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/build/src/browser/types.js.map b/build/src/browser/types.js.map new file mode 100644 index 000000000..a1bb2f714 --- /dev/null +++ b/build/src/browser/types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/browser/types.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/build/src/cli/index.d.ts b/build/src/cli/index.d.ts new file mode 100644 index 000000000..8b203f8eb --- /dev/null +++ b/build/src/cli/index.d.ts @@ -0,0 +1 @@ +export function run(): void; diff --git a/build/src/cli/index.js b/build/src/cli/index.js new file mode 100644 index 000000000..3c4689b87 --- /dev/null +++ b/build/src/cli/index.js @@ -0,0 +1,106 @@ +"use strict"; +const _ = require("lodash"); +const { Command } = require("@gemini-testing/commander"); +const escapeRe = require("escape-string-regexp"); +const defaults = require("../config/defaults"); +const info = require("./info"); +const { Hermione } = require("../hermione"); +const pkg = require("../../package.json"); +const logger = require("../utils/logger"); +const { requireModule } = require("../utils/module"); +let hermione; +process.on("uncaughtException", err => { + logger.error(err.stack); + process.exit(1); +}); +process.on("unhandledRejection", (reason, p) => { + if (reason && reason.name === "ProtocolError") { + logger.warn(`Unhandled Rejection "${reason}" in hermione:master:${process.pid} was ignored`); + return; + } + const error = [ + `Unhandled Rejection in hermione:master:${process.pid}:`, + `Promise: ${JSON.stringify(p)}`, + `Reason: ${_.get(reason, "stack", reason)}`, + ].join("\n"); + if (hermione) { + hermione.halt(error); + } + else { + logger.error(error); + process.exit(1); + } +}); +exports.run = () => { + const program = new Command(); + program.version(pkg.version).allowUnknownOption().option("-c, --config ", "path to configuration file"); + const configPath = preparseOption(program, "config"); + hermione = Hermione.create(configPath); + program + .on("--help", () => logger.log(info.configOverriding)) + .option("-b, --browser ", "run tests only in specified browser", collect) + .option("-s, --set ", "run tests only in the specified set", collect) + .option("-r, --require ", "require module", collect) + .option("--reporter ", "test reporters", collect) + .option("--grep ", "run only tests matching the pattern", compileGrep) + .option("--update-refs", 'update screenshot references or gather them if they do not exist ("assertView" command)') + .option("--inspect [inspect]", "nodejs inspector on [=[host:]port]") + .option("--inspect-brk [inspect-brk]", "nodejs inspector with break at the start") + .option("--repl [type]", "run one test, call `browser.switchToRepl` in test code to open repl interface", Boolean, false) + .option("--repl-before-test [type]", "open repl interface before test run", Boolean, false) + .option("--repl-on-fail [type]", "open repl interface on test fail only", Boolean, false) + .arguments("[paths...]") + .action(async (paths) => { + try { + const { reporter: reporters, browser: browsers, set: sets, grep, updateRefs, require: requireModules, inspect, inspectBrk, repl, replBeforeTest, replOnFail, } = program; + await handleRequires(requireModules); + const isTestsSuccess = await hermione.run(paths, { + reporters: reporters || defaults.reporters, + browsers, + sets, + grep, + updateRefs, + requireModules, + inspectMode: (inspect || inspectBrk) && { inspect, inspectBrk }, + replMode: { + enabled: repl || replBeforeTest || replOnFail, + beforeTest: replBeforeTest, + onFail: replOnFail, + }, + }); + process.exit(isTestsSuccess ? 0 : 1); + } + catch (err) { + logger.error(err.stack || err); + process.exit(1); + } + }); + hermione.extendCli(program); + program.parse(process.argv); +}; +function collect(newValue, array = []) { + return array.concat(newValue); +} +function preparseOption(program, option) { + // do not display any help, do not exit + const configFileParser = Object.create(program); + configFileParser.options = [].concat(program.options); + configFileParser.option("-h, --help"); + configFileParser.parse(process.argv); + return configFileParser[option]; +} +function compileGrep(grep) { + try { + return new RegExp(`(${grep})|(${escapeRe(grep)})`); + } + catch (error) { + logger.warn(`Invalid regexp provided to grep, searching by its string representation. ${error}`); + return new RegExp(escapeRe(grep)); + } +} +async function handleRequires(requires = []) { + for (const modulePath of requires) { + await requireModule(modulePath); + } +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/cli/index.js.map b/build/src/cli/index.js.map new file mode 100644 index 000000000..707dd0d9a --- /dev/null +++ b/build/src/cli/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/cli/info.d.ts b/build/src/cli/info.d.ts new file mode 100644 index 000000000..b10890550 --- /dev/null +++ b/build/src/cli/info.d.ts @@ -0,0 +1 @@ +export const configOverriding: " Overriding config\n To override any config option use full option path converted to --kebab-case\n\n Examples:\n hermione --system-debug true\n hermione --base-url http://example.com\n hermione --browsers-firefox-sessions-per-browser 10\n\n You can also use environment variables converted to snake_case with\n hermione_ prefix\n\n Examples:\n hermione_system_debug=true hermione\n hermione_base_url=http://example.com hermione\n hermione_browsers_firefox_sessions_per_browser=10 hermione\n\n If both cli option and environment variable are used, cli option takes precedence\n"; diff --git a/build/src/cli/info.js b/build/src/cli/info.js new file mode 100644 index 000000000..bd32a662e --- /dev/null +++ b/build/src/cli/info.js @@ -0,0 +1,20 @@ +"use strict"; +exports.configOverriding = ` Overriding config + To override any config option use full option path converted to --kebab-case + + Examples: + hermione --system-debug true + hermione --base-url http://example.com + hermione --browsers-firefox-sessions-per-browser 10 + + You can also use environment variables converted to snake_case with + hermione_ prefix + + Examples: + hermione_system_debug=true hermione + hermione_base_url=http://example.com hermione + hermione_browsers_firefox_sessions_per_browser=10 hermione + + If both cli option and environment variable are used, cli option takes precedence +`; +//# sourceMappingURL=info.js.map \ No newline at end of file diff --git a/build/src/cli/info.js.map b/build/src/cli/info.js.map new file mode 100644 index 000000000..dadf17a5a --- /dev/null +++ b/build/src/cli/info.js.map @@ -0,0 +1 @@ +{"version":3,"file":"info.js","sourceRoot":"","sources":["../../../src/cli/info.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,CAAC,gBAAgB,GAAG;;;;;;;;;;;;;;;;;CAiB1B,CAAC"} \ No newline at end of file diff --git a/build/src/config/browser-config.d.ts b/build/src/config/browser-config.d.ts new file mode 100644 index 000000000..2b8ffe4c8 --- /dev/null +++ b/build/src/config/browser-config.d.ts @@ -0,0 +1,7 @@ +import type { Test } from "../types"; +import type { CommonConfig } from "./types"; +export declare class BrowserConfig { + constructor(browserOptions: CommonConfig); + getScreenshotPath(test: Test, stateName: string): string; + serialize(): Omit; +} diff --git a/build/src/config/browser-config.js b/build/src/config/browser-config.js new file mode 100644 index 000000000..8a60aa6b2 --- /dev/null +++ b/build/src/config/browser-config.js @@ -0,0 +1,45 @@ +"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; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BrowserConfig = void 0; +const path = __importStar(require("path")); +const _ = __importStar(require("lodash")); +class BrowserConfig { + constructor(browserOptions) { + _.extend(this, browserOptions); + } + getScreenshotPath(test, stateName) { + const filename = `${stateName}.png`; + const { screenshotsDir } = this; + return _.isFunction(screenshotsDir) + ? path.resolve(screenshotsDir(test), filename) + : path.resolve(process.cwd(), screenshotsDir, test.id, this.id, filename); + } + serialize() { + return _.omit(this, ["system"]); + } +} +exports.BrowserConfig = BrowserConfig; +//# sourceMappingURL=browser-config.js.map \ No newline at end of file diff --git a/build/src/config/browser-config.js.map b/build/src/config/browser-config.js.map new file mode 100644 index 000000000..b2f1a1089 --- /dev/null +++ b/build/src/config/browser-config.js.map @@ -0,0 +1 @@ +{"version":3,"file":"browser-config.js","sourceRoot":"","sources":["../../../src/config/browser-config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA6B;AAC7B,0CAA4B;AAI5B,MAAa,aAAa;IACtB,YAAY,cAA4B;QACpC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IACnC,CAAC;IAED,iBAAiB,CAAC,IAAU,EAAE,SAAiB;QAC3C,MAAM,QAAQ,GAAG,GAAG,SAAS,MAAM,CAAC;QACpC,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;QAEhC,OAAO,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC;YAC/B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;YAC9C,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IAClF,CAAC;IAED,SAAS;QACL,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpC,CAAC;CACJ;AAjBD,sCAiBC"} \ No newline at end of file diff --git a/build/src/config/browser-options.d.ts b/build/src/config/browser-options.d.ts new file mode 100644 index 000000000..712e51d19 --- /dev/null +++ b/build/src/config/browser-options.d.ts @@ -0,0 +1,2 @@ +export function getTopLevel(): any; +export function getPerBrowser(): any; diff --git a/build/src/config/browser-options.js b/build/src/config/browser-options.js new file mode 100644 index 000000000..aa513c3aa --- /dev/null +++ b/build/src/config/browser-options.js @@ -0,0 +1,270 @@ +"use strict"; +const _ = require("lodash"); +const option = require("gemini-configparser").option; +const defaults = require("./defaults"); +const optionsBuilder = require("./options-builder"); +const utils = require("./utils"); +const { WEBDRIVER_PROTOCOL, DEVTOOLS_PROTOCOL, SAVE_HISTORY_MODE } = require("../constants/config"); +const { isSupportIsolation } = require("../utils/browser"); +const is = utils.is; +function provideRootDefault(name) { + return () => defaults[name]; +} +exports.getTopLevel = () => { + return buildBrowserOptions(provideRootDefault, { + desiredCapabilities: optionsBuilder(provideRootDefault).optionalObject("desiredCapabilities"), + }); +}; +exports.getPerBrowser = () => { + return buildBrowserOptions(provideTopLevelDefault, { + desiredCapabilities: option({ + defaultValue: defaults.desiredCapabilities, + parseEnv: JSON.parse, + parseCli: JSON.parse, + validate: (value, config) => { + if (_.isNull(value) && _.isNull(config.desiredCapabilities)) { + throw new Error('Each browser must have "desiredCapabilities" option'); + } + else { + utils.assertOptionalObject(value, "desiredCapabilities"); + } + }, + map: (value, config) => _.extend({}, config.desiredCapabilities, value), + }), + }); +}; +function provideTopLevelDefault(name) { + return config => { + const value = config[name]; + if (_.isUndefined(value)) { + throw new Error(`"${name}" should be set at the top level or per-browser option`); + } + return value; + }; +} +function buildBrowserOptions(defaultFactory, extra) { + const options = optionsBuilder(defaultFactory); + return _.extend(extra, { + gridUrl: options.string("gridUrl"), + baseUrl: option({ + defaultValue: defaultFactory("baseUrl"), + validate: is("string", "baseUrl"), + map: (value, config) => { + return config.baseUrl && !value.match(/^https?:\/\//) + ? [config.baseUrl.replace(/\/$/, ""), value.replace(/^\//, "")].join("/") + : value; + }, + }), + browserWSEndpoint: option({ + defaultValue: defaultFactory("browserWSEndpoint"), + validate: value => { + if (_.isNull(value)) { + return; + } + is("string", "browserWSEndpoint")(value); + if (!/wss?:\/\//.test(value)) { + throw new Error(`"browserWSEndpoint" must start with "ws://" or "wss://" prefix`); + } + }, + }), + automationProtocol: option({ + defaultValue: defaultFactory("automationProtocol"), + validate: value => { + is("string", "automationProtocol")(value); + if (value !== WEBDRIVER_PROTOCOL && value !== DEVTOOLS_PROTOCOL) { + throw new Error(`"automationProtocol" must be "${WEBDRIVER_PROTOCOL}" or "${DEVTOOLS_PROTOCOL}"`); + } + }, + }), + sessionEnvFlags: option({ + defaultValue: defaultFactory("sessionEnvFlags"), + validate: value => { + if (!_.isPlainObject(value)) { + throw new Error('"sessionEnvFlags" must be an object'); + } + if (_.isEmpty(value)) { + return; + } + const availableSessionEnvFlags = [ + "isW3C", + "isChrome", + "isMobile", + "isIOS", + "isAndroid", + "isSauce", + "isSeleniumStandalone", + ]; + Object.keys(value).forEach(key => { + if (!availableSessionEnvFlags.includes(key)) { + throw new Error(`keys of "sessionEnvFlags" must be one of: ${availableSessionEnvFlags.join(", ")}`); + } + if (!_.isBoolean(value[key])) { + throw new Error('values of "sessionEnvFlags" must be boolean'); + } + }); + }, + }), + sessionsPerBrowser: options.positiveInteger("sessionsPerBrowser"), + testsPerSession: options.positiveIntegerOrInfinity("testsPerSession"), + retry: options.nonNegativeInteger("retry"), + shouldRetry: options.optionalFunction("shouldRetry"), + httpTimeout: options.nonNegativeInteger("httpTimeout"), + urlHttpTimeout: options.optionalNonNegativeInteger("urlHttpTimeout"), + pageLoadTimeout: options.optionalNonNegativeInteger("pageLoadTimeout"), + sessionRequestTimeout: options.optionalNonNegativeInteger("sessionRequestTimeout"), + sessionQuitTimeout: options.optionalNonNegativeInteger("sessionQuitTimeout"), + testTimeout: options.optionalNonNegativeInteger("testTimeout"), + waitTimeout: options.positiveInteger("waitTimeout"), + waitInterval: options.positiveInteger("waitInterval"), + saveHistoryMode: option({ + defaultValue: defaultFactory("saveHistoryMode"), + validate: value => { + const availableValues = Object.values(SAVE_HISTORY_MODE); + if (!availableValues.includes(value)) { + throw new Error(`"saveHistoryMode" must be one of: ${availableValues.join(", ")}`); + } + }, + }), + takeScreenshotOnFails: option({ + defaultValue: defaultFactory("takeScreenshotOnFails"), + parseEnv: JSON.parse, + parseCli: JSON.parse, + validate: value => { + if (!_.isPlainObject(value)) { + throw new Error('"takeScreenshotOnFails" must be an object'); + } + const allowedProps = ["assertViewFail", "testFail"]; + const unknownProps = _.keys(value).filter(prop => !allowedProps.includes(prop)); + if (unknownProps.length) { + throw new Error(`"takeScreenshotOnFails" contains unknown properties: ${unknownProps}. Allowed: ${allowedProps}.`); + } + }, + map: (value, config) => ({ + ...defaultFactory("takeScreenshotOnFails")(config), + ...value, + }), + }), + takeScreenshotOnFailsTimeout: options.optionalNonNegativeInteger("takeScreenshotOnFailsTimeout"), + takeScreenshotOnFailsMode: options.enumeration("takeScreenshotOnFailsMode", ["fullpage", "viewport"]), + prepareBrowser: options.optionalFunction("prepareBrowser"), + screenshotsDir: options.stringOrFunction("screenshotsDir"), + calibrate: options.boolean("calibrate"), + compositeImage: options.boolean("compositeImage"), + strictTestsOrder: options.boolean("strictTestsOrder"), + screenshotMode: options.enumeration("screenshotMode", ["fullpage", "viewport", "auto"], { + map: (value, config, currentNode) => { + if (value !== defaults.screenshotMode) { + return value; + } + // Chrome mobile returns screenshots that are larger than visible viewport due to a bug: + // https://bugs.chromium.org/p/chromedriver/issues/detail?id=2853 + // Due to this, screenshot is cropped incorrectly. + const capabilities = _.get(currentNode, "desiredCapabilities"); + const isAndroid = capabilities && + Boolean((capabilities.platformName && capabilities.platformName.match(/Android/i)) || + (capabilities.browserName && capabilities.browserName.match(/Android/i))); + return isAndroid ? "viewport" : value; + }, + }), + screenshotDelay: options.nonNegativeInteger("screenshotDelay"), + tolerance: option({ + defaultValue: defaultFactory("tolerance"), + parseEnv: Number, + parseCli: Number, + validate: value => utils.assertNonNegativeNumber(value, "tolerance"), + }), + antialiasingTolerance: option({ + defaultValue: defaultFactory("antialiasingTolerance"), + parseEnv: Number, + parseCli: Number, + validate: value => utils.assertNonNegativeNumber(value, "antialiasingTolerance"), + }), + disableAnimation: options.boolean("disableAnimation"), + compareOpts: options.optionalObject("compareOpts"), + buildDiffOpts: options.optionalObject("buildDiffOpts"), + assertViewOpts: option({ + defaultValue: defaultFactory("assertViewOpts"), + parseEnv: JSON.parse, + parseCli: JSON.parse, + validate: value => utils.assertOptionalObject(value, "assertViewOpts"), + map: value => { + return value === defaults.assertViewOpts ? value : { ...defaults.assertViewOpts, ...value }; + }, + }), + openAndWaitOpts: option({ + defaultValue: defaultFactory("openAndWaitOpts"), + parseEnv: JSON.parse, + parseCli: JSON.parse, + validate: value => utils.assertOptionalObject(value, "openAndWaitOpts"), + map: value => ({ ...defaults.openAndWaitOpts, ...value }), + }), + meta: options.optionalObject("meta"), + windowSize: option({ + defaultValue: defaultFactory("windowSize"), + validate: value => { + if (_.isNull(value)) { + return; + } + if (_.isObject(value)) { + if (_.isNumber(value.width) && _.isNumber(value.height)) { + return; + } + else { + throw new Error('"windowSize" must be an object with "width" and "height" keys'); + } + } + if (!_.isString(value)) { + throw new Error('"windowSize" must be string, object or null'); + } + else if (!/^\d+x\d+$/.test(value)) { + throw new Error('"windowSize" should have form of x (i.e. 1600x1200)'); + } + }, + map: value => { + if (_.isNull(value) || _.isObject(value)) { + return value; + } + const [width, height] = value.split("x").map(v => parseInt(v, 10)); + return { width, height }; + }, + }), + orientation: option({ + defaultValue: defaultFactory("orientation"), + validate: value => { + if (_.isNull(value)) { + return; + } + is("string", "orientation")(value); + if (value !== "landscape" && value !== "portrait") { + throw new Error('"orientation" must be "landscape" or "portrait"'); + } + }, + }), + waitOrientationChange: options.boolean("waitOrientationChange"), + resetCursor: options.boolean("resetCursor"), + outputDir: options.optionalString("outputDir"), + agent: options.optionalObject("agent"), + headers: options.optionalObject("headers"), + transformRequest: options.optionalFunction("transformRequest"), + transformResponse: options.optionalFunction("transformResponse"), + strictSSL: options.optionalBoolean("strictSSL"), + user: options.optionalString("user"), + key: options.optionalString("key"), + region: options.optionalString("region"), + headless: options.optionalBoolean("headless"), + isolation: option({ + defaultValue: defaultFactory("isolation"), + parseCli: value => utils.parseBoolean(value, "isolation"), + parseEnv: value => utils.parseBoolean(value, "isolation"), + validate: value => _.isNull(value) || is("boolean", "isolation")(value), + map: (value, config, currentNode, meta) => { + if (meta.isSetByUser || !_.isNull(value)) { + return value; + } + const caps = _.get(currentNode, "desiredCapabilities"); + return caps ? isSupportIsolation(caps.browserName, caps.browserVersion) : value; + }, + }), + }); +} +//# sourceMappingURL=browser-options.js.map \ No newline at end of file diff --git a/build/src/config/browser-options.js.map b/build/src/config/browser-options.js.map new file mode 100644 index 000000000..b3e68c41c --- /dev/null +++ b/build/src/config/browser-options.js.map @@ -0,0 +1 @@ +{"version":3,"file":"browser-options.js","sourceRoot":"","sources":["../../../src/config/browser-options.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/config/defaults.d.ts b/build/src/config/defaults.d.ts new file mode 100644 index 000000000..50b761df8 --- /dev/null +++ b/build/src/config/defaults.d.ts @@ -0,0 +1,91 @@ +import { WEBDRIVER_PROTOCOL } from "../constants/config"; +export declare let baseUrl: string; +export declare let gridUrl: string; +export declare let browserWSEndpoint: null; +export declare let desiredCapabilities: null; +export { WEBDRIVER_PROTOCOL as automationProtocol }; +export declare let sessionEnvFlags: {}; +export declare let screenshotsDir: string; +export declare let diffColor: string; +export declare let tolerance: number; +export declare let antialiasingTolerance: number; +export declare let disableAnimation: boolean; +export declare namespace compareOpts { + let shouldCluster: boolean; + let clustersSize: number; + let stopOnFirstFail: boolean; +} +export declare namespace buildDiffOpts { + let ignoreAntialiasing: boolean; + let ignoreCaret: boolean; +} +export declare namespace assertViewOpts { + let ignoreElements: never[]; + let captureElementFromTop: boolean; + let allowViewportOverflow: boolean; +} +export declare namespace openAndWaitOpts { + let waitNetworkIdle: boolean; + let waitNetworkIdleTimeout: number; + let failOnNetworkError: boolean; + let ignoreNetworkErrorsPatterns: never[]; +} +export declare let calibrate: boolean; +export declare let screenshotMode: string; +export declare let screenshotDelay: number; +export declare let compositeImage: boolean; +export declare let prepareBrowser: null; +export declare let prepareEnvironment: null; +export declare let waitTimeout: number; +export declare let waitInterval: number; +export declare let httpTimeout: number; +export declare let urlHttpTimeout: null; +export declare let pageLoadTimeout: number; +export declare let sessionRequestTimeout: null; +export declare let sessionQuitTimeout: number; +export declare let testTimeout: null; +export declare namespace takeScreenshotOnFails { + let testFail: boolean; + let assertViewFail: boolean; +} +export declare let takeScreenshotOnFailsTimeout: number; +export declare let takeScreenshotOnFailsMode: string; +export declare let reporters: string[]; +export declare let debug: boolean; +export declare let parallelLimit: number; +export declare let sessionsPerBrowser: number; +export declare let testsPerSession: number; +export declare let workers: number; +export declare let testsPerWorker: number; +export declare let retry: number; +export declare let shouldRetry: null; +export declare namespace mochaOpts { + let slow: number; + let timeout: number; +} +export declare namespace expectOpts { + let wait: number; + let interval: number; +} +export declare let patternsOnReject: never[]; +export declare let meta: null; +export declare let windowSize: null; +export declare let tempDir: string; +export declare let orientation: null; +export declare let waitOrientationChange: boolean; +export declare let resetCursor: boolean; +export declare let strictTestsOrder: boolean; +export declare let saveHistoryMode: string; +export declare let fileExtensions: string[]; +export declare let outputDir: null; +export declare let agent: null; +export declare let headers: null; +export declare let transformRequest: null; +export declare let transformResponse: null; +export declare let strictSSL: null; +export declare let user: null; +export declare let key: null; +export declare let region: null; +export declare let headless: null; +export declare let isolation: null; +export declare let configPaths: string[]; diff --git a/build/src/config/defaults.js b/build/src/config/defaults.js new file mode 100644 index 000000000..6fb3735c8 --- /dev/null +++ b/build/src/config/defaults.js @@ -0,0 +1,95 @@ +"use strict"; +const { WEBDRIVER_PROTOCOL, SAVE_HISTORY_MODE } = require("../constants/config"); +module.exports = { + baseUrl: "http://localhost", + gridUrl: "http://localhost:4444/wd/hub", + browserWSEndpoint: null, + desiredCapabilities: null, + automationProtocol: WEBDRIVER_PROTOCOL, + sessionEnvFlags: {}, + screenshotsDir: "hermione/screens", + diffColor: "#ff00ff", + tolerance: 2.3, + antialiasingTolerance: 4, + disableAnimation: true, + compareOpts: { + shouldCluster: false, + clustersSize: 10, + stopOnFirstFail: false, + }, + buildDiffOpts: { + ignoreAntialiasing: true, + ignoreCaret: true, + }, + assertViewOpts: { + ignoreElements: [], + captureElementFromTop: true, + allowViewportOverflow: false, + }, + openAndWaitOpts: { + waitNetworkIdle: true, + waitNetworkIdleTimeout: 500, + failOnNetworkError: true, + ignoreNetworkErrorsPatterns: [], + }, + calibrate: false, + screenshotMode: "auto", + screenshotDelay: 0, + compositeImage: true, + prepareBrowser: null, + prepareEnvironment: null, + waitTimeout: 3000, + waitInterval: 500, + httpTimeout: 30000, + urlHttpTimeout: null, + pageLoadTimeout: 20000, + sessionRequestTimeout: null, + sessionQuitTimeout: 5000, + testTimeout: null, + takeScreenshotOnFails: { + testFail: true, + assertViewFail: true, + }, + takeScreenshotOnFailsTimeout: 5000, + takeScreenshotOnFailsMode: "fullpage", + reporters: ["flat"], + debug: false, + parallelLimit: Infinity, + sessionsPerBrowser: 1, + testsPerSession: Infinity, + workers: 1, + testsPerWorker: Infinity, + retry: 0, + shouldRetry: null, + mochaOpts: { + slow: 10000, + timeout: 60000, + }, + expectOpts: { + wait: 3000, + interval: 100, + }, + patternsOnReject: [], + meta: null, + windowSize: null, + tempDir: "", + orientation: null, + waitOrientationChange: true, + resetCursor: true, + strictTestsOrder: false, + saveHistoryMode: SAVE_HISTORY_MODE.ALL, + fileExtensions: [".js", ".mjs", ".ts", ".mts"], + outputDir: null, + agent: null, + headers: null, + transformRequest: null, + transformResponse: null, + strictSSL: null, + user: null, + key: null, + region: null, + headless: null, + isolation: null, +}; +module.exports.configPaths = [".hermione.conf.ts", ".hermione.conf.js"]; +//# sourceMappingURL=defaults.js.map \ No newline at end of file diff --git a/build/src/config/defaults.js.map b/build/src/config/defaults.js.map new file mode 100644 index 000000000..4d578e31f --- /dev/null +++ b/build/src/config/defaults.js.map @@ -0,0 +1 @@ +{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../../src/config/defaults.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/config/index.d.ts b/build/src/config/index.d.ts new file mode 100644 index 000000000..bcad3e9e5 --- /dev/null +++ b/build/src/config/index.d.ts @@ -0,0 +1,16 @@ +import { BrowserConfig } from "./browser-config"; +import { ConfigInput } from "./types"; +export declare class Config { + configPath: string; + static create(config?: string | ConfigInput): Config; + static read(configPath: string): unknown; + constructor(config?: string | ConfigInput); + forBrowser(id: string): BrowserConfig; + getBrowserIds(): Array; + serialize(): Omit; + /** + * This method is used in subrocesses to merge a created config + * in a subrocess with a config from the main process + */ + mergeWith(config: Config): void; +} diff --git a/build/src/config/index.js b/build/src/config/index.js new file mode 100644 index 000000000..72ed95a73 --- /dev/null +++ b/build/src/config/index.js @@ -0,0 +1,121 @@ +"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.Config = void 0; +const path = __importStar(require("path")); +const _ = __importStar(require("lodash")); +const defaults_1 = __importDefault(require("./defaults")); +const browser_config_1 = require("./browser-config"); +const options_1 = __importDefault(require("./options")); +const logger_1 = __importDefault(require("../utils/logger")); +class Config { + static create(config) { + return new Config(config); + } + static read(configPath) { + try { + return require(path.resolve(process.cwd(), configPath)); + } + catch (e) { + logger_1.default.error(`Unable to read config from path ${configPath}`); + throw e; + } + } + constructor(config) { + let options; + if (_.isObjectLike(config)) { + options = config; + } + else if (typeof config === "string") { + this.configPath = config; + options = Config.read(config); + } + else { + for (const configPath of defaults_1.default.configPaths) { + try { + const resolvedConfigPath = path.resolve(configPath); + require(resolvedConfigPath); + this.configPath = resolvedConfigPath; + break; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } + catch (err) { + if (err.code !== "MODULE_NOT_FOUND") { + throw err; + } + } + } + if (!this.configPath) { + throw new Error(`Unable to read config from paths: ${defaults_1.default.configPaths.join(", ")}`); + } + options = Config.read(this.configPath); + } + if (_.isFunction(options.prepareEnvironment)) { + options.prepareEnvironment(); + } + _.extend(this, (0, options_1.default)({ + options, + env: process.env, + argv: process.argv, + })); + this.browsers = _.mapValues(this.browsers, (browser, id) => { + const browserOptions = _.extend({}, browser, { + id: id, + system: this.system, + }); + return new browser_config_1.BrowserConfig(browserOptions); + }); + } + forBrowser(id) { + return this.browsers[id]; + } + getBrowserIds() { + return _.keys(this.browsers); + } + serialize() { + return _.extend({}, this, { + browsers: _.mapValues(this.browsers, broConf => broConf.serialize()), + }); + } + /** + * This method is used in subrocesses to merge a created config + * in a subrocess with a config from the main process + */ + mergeWith(config) { + _.mergeWith(this, config, (l, r) => { + if (_.isObjectLike(l)) { + return; + } + // When passing stringified config from the master to workers + // all functions are transformed to strings and all regular expressions to empty objects + return typeof l === typeof r ? r : l; + }); + } +} +exports.Config = Config; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/config/index.js.map b/build/src/config/index.js.map new file mode 100644 index 000000000..2239a31bf --- /dev/null +++ b/build/src/config/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/config/options-builder.d.ts b/build/src/config/options-builder.d.ts new file mode 100644 index 000000000..f8b7362d5 --- /dev/null +++ b/build/src/config/options-builder.d.ts @@ -0,0 +1,22 @@ +declare function _exports(defaultFactory: any): { + boolean: (name: any, opts?: { + isDeprecated: boolean; + }) => configparser.Parser; + optionalBoolean: (name: any) => configparser.Parser; + optionalArray: (name: any) => configparser.Parser; + optionalObject: (name: any) => configparser.Parser; + optionalFunction: (name: any) => configparser.Parser; + anyObject: () => any; + nonNegativeInteger: (name: any) => configparser.Parser; + optionalNonNegativeInteger: (name: any, opts?: { + isDeprecated: boolean; + }) => configparser.Parser; + string: (name: any) => configparser.Parser; + optionalString: (name: any) => configparser.Parser; + positiveInteger: (name: any) => configparser.Parser; + positiveIntegerOrInfinity: (name: any) => configparser.Parser; + stringOrFunction: (name: any) => configparser.Parser; + hexString: (name: any) => configparser.Parser; + enumeration: (name: any, enumValues: any, customOptionConfig: any) => configparser.Parser; +}; +export = _exports; diff --git a/build/src/config/options-builder.js b/build/src/config/options-builder.js new file mode 100644 index 000000000..5c6120f66 --- /dev/null +++ b/build/src/config/options-builder.js @@ -0,0 +1,153 @@ +"use strict"; +const _ = require("lodash"); +const configparser = require("gemini-configparser"); +const utils = require("./utils"); +const option = configparser.option; +const map = configparser.map; +const assertNonNegativeInteger = utils.assertNonNegativeInteger; +const assertPositiveInteger = utils.assertPositiveInteger; +const assertPositiveIntegerOrInfinity = utils.assertPositiveIntegerOrInfinity; +const assertOptionalObject = utils.assertOptionalObject; +const assertOptionalArray = utils.assertOptionalArray; +const assertEnum = utils.assertEnum; +const parseBoolean = utils.parseBoolean; +const parsePrimitive = utils.parsePrimitive; +const is = utils.is; +module.exports = defaultFactory => { + return { + boolean, + optionalBoolean, + optionalArray, + optionalObject, + optionalFunction, + anyObject, + nonNegativeInteger, + optionalNonNegativeInteger, + string, + optionalString, + positiveInteger, + positiveIntegerOrInfinity, + stringOrFunction, + hexString, + enumeration, + }; + function boolean(name, opts = { isDeprecated: false }) { + return option({ + defaultValue: defaultFactory(name), + parseCli: value => parseBoolean(value, name), + parseEnv: value => parseBoolean(value, name), + validate: is("boolean", name), + isDeprecated: opts.isDeprecated, + }); + } + function optionalBoolean(name) { + return option({ + parseCli: value => parseBoolean(value, name), + parseEnv: value => parseBoolean(value, name), + defaultValue: defaultFactory(name), + validate: value => _.isNull(value) || is("boolean", name)(value), + }); + } + function optionalArray(name) { + return option({ + parseEnv: JSON.parse, + parseCli: JSON.parse, + defaultValue: defaultFactory(name), + validate: value => assertOptionalArray(value, name), + }); + } + function optionalObject(name) { + return option({ + parseEnv: JSON.parse, + parseCli: JSON.parse, + defaultValue: defaultFactory(name), + validate: value => assertOptionalObject(value, name), + }); + } + function optionalFunction(name) { + return option({ + defaultValue: defaultFactory(name), + validate: value => _.isNull(value) || is("function", name)(value), + }); + } + function anyObject() { + return map(option({ + parseEnv: parsePrimitive, + parseCli: parsePrimitive, + })); + } + function nonNegativeInteger(name) { + return option({ + parseEnv: Number, + parseCli: Number, + defaultValue: defaultFactory(name), + validate: value => assertNonNegativeInteger(value, name), + }); + } + function optionalNonNegativeInteger(name, opts = { isDeprecated: false }) { + return option({ + parseEnv: Number, + parseCli: Number, + defaultValue: defaultFactory(name), + validate: value => _.isNull(value) || assertNonNegativeInteger(value, name), + isDeprecated: opts.isDeprecated, + }); + } + function string(name) { + return option({ + defaultValue: defaultFactory(name), + validate: is("string", name), + }); + } + function optionalString(name) { + return option({ + defaultValue: defaultFactory(name), + validate: value => _.isNull(value) || is("string", name)(value), + }); + } + function positiveInteger(name) { + return option({ + parseEnv: Number, + parseCli: Number, + defaultValue: defaultFactory(name), + validate: value => assertPositiveInteger(value, name), + }); + } + function positiveIntegerOrInfinity(name) { + return option({ + parseEnv: Number, + parseCli: Number, + defaultValue: defaultFactory(name), + validate: value => assertPositiveIntegerOrInfinity(value, name), + }); + } + function stringOrFunction(name) { + return option({ + defaultValue: defaultFactory(name), + validate: value => { + if (!_.isString(value) && !_.isFunction(value)) { + throw new Error(`"${name}" must be a string or function`); + } + }, + }); + } + function hexString(name) { + return option({ + defaultValue: defaultFactory(name), + validate: value => { + is("string", name)(value); + if (!/^#[\da-f]{6}$/i.test(value)) { + throw new Error(`"${name}" must be a hexadecimal color string (i.e. #ff0000)`); + } + }, + }); + } + function enumeration(name, enumValues, customOptionConfig) { + return option({ + defaultValue: defaultFactory(name), + validate: value => assertEnum(enumValues, value, name), + ...customOptionConfig, + }); + } +}; +//# sourceMappingURL=options-builder.js.map \ No newline at end of file diff --git a/build/src/config/options-builder.js.map b/build/src/config/options-builder.js.map new file mode 100644 index 000000000..72728a97d --- /dev/null +++ b/build/src/config/options-builder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"options-builder.js","sourceRoot":"","sources":["../../../src/config/options-builder.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC5B,MAAM,YAAY,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;AAEpD,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAEjC,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC;AACnC,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC;AAE7B,MAAM,wBAAwB,GAAG,KAAK,CAAC,wBAAwB,CAAC;AAChE,MAAM,qBAAqB,GAAG,KAAK,CAAC,qBAAqB,CAAC;AAC1D,MAAM,+BAA+B,GAAG,KAAK,CAAC,+BAA+B,CAAC;AAC9E,MAAM,oBAAoB,GAAG,KAAK,CAAC,oBAAoB,CAAC;AACxD,MAAM,mBAAmB,GAAG,KAAK,CAAC,mBAAmB,CAAC;AACtD,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;AACpC,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;AACxC,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC;AAC5C,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;AAEpB,MAAM,CAAC,OAAO,GAAG,cAAc,CAAC,EAAE;IAC9B,OAAO;QACH,OAAO;QACP,eAAe;QACf,aAAa;QACb,cAAc;QACd,gBAAgB;QAChB,SAAS;QACT,kBAAkB;QAClB,0BAA0B;QAC1B,MAAM;QACN,cAAc;QACd,eAAe;QACf,yBAAyB;QACzB,gBAAgB;QAChB,SAAS;QACT,WAAW;KACd,CAAC;IAEF,SAAS,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE;QACjD,OAAO,MAAM,CAAC;YACV,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC;YAClC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC;YAC5C,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC;YAC5C,QAAQ,EAAE,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC;YAC7B,YAAY,EAAE,IAAI,CAAC,YAAY;SAClC,CAAC,CAAC;IACP,CAAC;IAED,SAAS,eAAe,CAAC,IAAI;QACzB,OAAO,MAAM,CAAC;YACV,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC;YAC5C,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC;YAC5C,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC;YAClC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC;SACnE,CAAC,CAAC;IACP,CAAC;IAED,SAAS,aAAa,CAAC,IAAI;QACvB,OAAO,MAAM,CAAC;YACV,QAAQ,EAAE,IAAI,CAAC,KAAK;YACpB,QAAQ,EAAE,IAAI,CAAC,KAAK;YACpB,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC;YAClC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC;SACtD,CAAC,CAAC;IACP,CAAC;IAED,SAAS,cAAc,CAAC,IAAI;QACxB,OAAO,MAAM,CAAC;YACV,QAAQ,EAAE,IAAI,CAAC,KAAK;YACpB,QAAQ,EAAE,IAAI,CAAC,KAAK;YACpB,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC;YAClC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC;SACvD,CAAC,CAAC;IACP,CAAC;IAED,SAAS,gBAAgB,CAAC,IAAI;QAC1B,OAAO,MAAM,CAAC;YACV,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC;YAClC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC;SACpE,CAAC,CAAC;IACP,CAAC;IAED,SAAS,SAAS;QACd,OAAO,GAAG,CACN,MAAM,CAAC;YACH,QAAQ,EAAE,cAAc;YACxB,QAAQ,EAAE,cAAc;SAC3B,CAAC,CACL,CAAC;IACN,CAAC;IAED,SAAS,kBAAkB,CAAC,IAAI;QAC5B,OAAO,MAAM,CAAC;YACV,QAAQ,EAAE,MAAM;YAChB,QAAQ,EAAE,MAAM;YAChB,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC;YAClC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAAC,KAAK,EAAE,IAAI,CAAC;SAC3D,CAAC,CAAC;IACP,CAAC;IAED,SAAS,0BAA0B,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE;QACpE,OAAO,MAAM,CAAC;YACV,QAAQ,EAAE,MAAM;YAChB,QAAQ,EAAE,MAAM;YAChB,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC;YAClC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,wBAAwB,CAAC,KAAK,EAAE,IAAI,CAAC;YAC3E,YAAY,EAAE,IAAI,CAAC,YAAY;SAClC,CAAC,CAAC;IACP,CAAC;IAED,SAAS,MAAM,CAAC,IAAI;QAChB,OAAO,MAAM,CAAC;YACV,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC;YAClC,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC;SAC/B,CAAC,CAAC;IACP,CAAC;IAED,SAAS,cAAc,CAAC,IAAI;QACxB,OAAO,MAAM,CAAC;YACV,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC;YAClC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC;SAClE,CAAC,CAAC;IACP,CAAC;IAED,SAAS,eAAe,CAAC,IAAI;QACzB,OAAO,MAAM,CAAC;YACV,QAAQ,EAAE,MAAM;YAChB,QAAQ,EAAE,MAAM;YAChB,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC;YAClC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC;SACxD,CAAC,CAAC;IACP,CAAC;IAED,SAAS,yBAAyB,CAAC,IAAI;QACnC,OAAO,MAAM,CAAC;YACV,QAAQ,EAAE,MAAM;YAChB,QAAQ,EAAE,MAAM;YAChB,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC;YAClC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,+BAA+B,CAAC,KAAK,EAAE,IAAI,CAAC;SAClE,CAAC,CAAC;IACP,CAAC;IAED,SAAS,gBAAgB,CAAC,IAAI;QAC1B,OAAO,MAAM,CAAC;YACV,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC;YAClC,QAAQ,EAAE,KAAK,CAAC,EAAE;gBACd,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC7C,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,gCAAgC,CAAC,CAAC;gBAC9D,CAAC;YACL,CAAC;SACJ,CAAC,CAAC;IACP,CAAC;IAED,SAAS,SAAS,CAAC,IAAI;QACnB,OAAO,MAAM,CAAC;YACV,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC;YAClC,QAAQ,EAAE,KAAK,CAAC,EAAE;gBACd,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC;gBAE1B,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBAChC,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,qDAAqD,CAAC,CAAC;gBACnF,CAAC;YACL,CAAC;SACJ,CAAC,CAAC;IACP,CAAC;IAED,SAAS,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,kBAAkB;QACrD,OAAO,MAAM,CAAC;YACV,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC;YAClC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC;YACtD,GAAG,kBAAkB;SACxB,CAAC,CAAC;IACP,CAAC;AACL,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/config/options.d.ts b/build/src/config/options.d.ts new file mode 100644 index 000000000..92d3a8627 --- /dev/null +++ b/build/src/config/options.d.ts @@ -0,0 +1,3 @@ +/// +declare const _exports: import("gemini-configparser").RootParser; +export = _exports; diff --git a/build/src/config/options.js b/build/src/config/options.js new file mode 100644 index 000000000..f291465e4 --- /dev/null +++ b/build/src/config/options.js @@ -0,0 +1,75 @@ +"use strict"; +const _ = require("lodash"); +const { root, section, map, option } = require("gemini-configparser"); +const browserOptions = require("./browser-options"); +const defaults = require("./defaults"); +const optionsBuilder = require("./options-builder"); +const options = optionsBuilder(_.propertyOf(defaults)); +const ENV_PREFIX = `${require("../../package").name}_`; +const rootSection = section(_.extend(browserOptions.getTopLevel(), { + browsers: map(section(browserOptions.getPerBrowser())), + prepareEnvironment: options.optionalFunction("prepareEnvironment"), + system: section({ + debug: options.boolean("debug"), + mochaOpts: options.optionalObject("mochaOpts"), + expectOpts: options.optionalObject("expectOpts"), + ctx: options.anyObject(), + patternsOnReject: options.optionalArray("patternsOnReject"), + workers: options.positiveInteger("workers"), + testsPerWorker: options.positiveIntegerOrInfinity("testsPerWorker"), + diffColor: options.hexString("diffColor"), + tempDir: options.string("tempDir"), + parallelLimit: options.positiveIntegerOrInfinity("parallelLimit"), + fileExtensions: option({ + parseEnv: JSON.parse, + parseCli: JSON.parse, + defaultValue: defaults.fileExtensions, + validate: value => { + if (!(_.isArray(value) && value.every(_.isString))) { + throw new Error(`"fileExtensions" must be an array of strings but got ${JSON.stringify(value)}`); + } + if (value.some(v => !v.startsWith("."))) { + throw new Error(`Each extension from "fileExtensions" must start with dot symbol but got ${JSON.stringify(value)}`); + } + }, + }), + }), + plugins: options.anyObject(), + sets: map(section({ + files: option({ + validate: value => { + if (!_.isArray(value) && !_.isString(value)) { + throw new Error('"sets.files" must be an array or string'); + } + if (_.isArray(value) && !_.every(value, _.isString)) { + throw new Error('"sets.files" must be an array of strings'); + } + }, + map: val => [].concat(val), + }), + ignoreFiles: option({ + defaultValue: [], + validate: value => { + if (!_.isArray(value) || !_.every(value, _.isString)) { + throw new Error('"sets.ignoreFiles" must be an array of strings'); + } + }, + }), + browsers: option({ + defaultValue: config => _.keys(config.browsers), + validate: (value, config) => { + if (!_.isArray(value)) { + throw new Error('"sets.browsers" must be an array'); + } + const unknownBrowsers = _.difference(value, _.keys(config.browsers)); + if (!_.isEmpty(unknownBrowsers)) { + throw new Error(`Unknown browsers for "sets.browsers": ${unknownBrowsers.join(", ")}`); + } + }, + }), + }), { + "": { files: [] }, // Use `all` set with default values if sets were not specified in a config + }), +})); +module.exports = root(rootSection, { envPrefix: ENV_PREFIX }); +//# sourceMappingURL=options.js.map \ No newline at end of file diff --git a/build/src/config/options.js.map b/build/src/config/options.js.map new file mode 100644 index 000000000..6b6247b65 --- /dev/null +++ b/build/src/config/options.js.map @@ -0,0 +1 @@ +{"version":3,"file":"options.js","sourceRoot":"","sources":["../../../src/config/options.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/config/runtime-config.d.ts b/build/src/config/runtime-config.d.ts new file mode 100644 index 000000000..78c7d84d2 --- /dev/null +++ b/build/src/config/runtime-config.d.ts @@ -0,0 +1 @@ +export function getInstance(): any; diff --git a/build/src/config/runtime-config.js b/build/src/config/runtime-config.js new file mode 100644 index 000000000..ee387f8b2 --- /dev/null +++ b/build/src/config/runtime-config.js @@ -0,0 +1,21 @@ +"use strict"; +/** + * @singleton + */ +class RuntimeConfig { + static create() { + return new RuntimeConfig(); + } + extend(data) { + Object.assign(this, data); + return this; + } +} +let runtimeConfig; +exports.getInstance = () => { + if (!runtimeConfig) { + runtimeConfig = RuntimeConfig.create(); + } + return runtimeConfig; +}; +//# sourceMappingURL=runtime-config.js.map \ No newline at end of file diff --git a/build/src/config/runtime-config.js.map b/build/src/config/runtime-config.js.map new file mode 100644 index 000000000..28b3d6abc --- /dev/null +++ b/build/src/config/runtime-config.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runtime-config.js","sourceRoot":"","sources":["../../../src/config/runtime-config.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb;;GAEG;AACH,MAAM,aAAa;IACf,MAAM,CAAC,MAAM;QACT,OAAO,IAAI,aAAa,EAAE,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,IAAI;QACP,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAE1B,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ;AAED,IAAI,aAAa,CAAC;AAElB,OAAO,CAAC,WAAW,GAAG,GAAG,EAAE;IACvB,IAAI,CAAC,aAAa,EAAE,CAAC;QACjB,aAAa,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC;IAC3C,CAAC;IAED,OAAO,aAAa,CAAC;AACzB,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/config/types.d.ts b/build/src/config/types.d.ts new file mode 100644 index 000000000..83a0e35c2 --- /dev/null +++ b/build/src/config/types.d.ts @@ -0,0 +1,154 @@ +import type { SetRequired } from "type-fest"; +import type { BrowserConfig } from "./browser-config"; +import type { Test } from "../types"; +export interface CompareOptsConfig { + shouldCluster: boolean; + clustersSize: number; + stopOnFirstFail: boolean; +} +export interface BuildDiffOptsConfig { + ignoreAntialiasing: boolean; + ignoreCaret: boolean; +} +export interface AssertViewOptsConfig { + /** + * DOM-node selectors which will be ignored (painted with a black rectangle) when comparing images. + * + * @defaultValue `[]` + */ + ignoreElements: string | Array; + /** + * Ability to set capture element from the top area or from current position. + * + * @remarks + * In the first case viewport will be scrolled to the top of the element. + * + * @defaultValue `true` + */ + captureElementFromTop: boolean; + /** + * Disables check that element is outside of the viewport left, top, right or bottom bounds. + * + * @remarks + * By default Hermione throws an error if element is outside the viewport bounds. + * This option disables check that element is outside of the viewport left, top, right or bottom bounds. + * And in this case if browser option {@link https://github.com/gemini-testing/hermione#compositeimage compositeImage} set to `false`, then only visible part of the element will be captured. + * But if {@link https://github.com/gemini-testing/hermione#compositeimage compositeImage} set to `true` (default), then in the resulting screenshot will appear the whole element with not visible parts outside of the bottom bounds of viewport. + * + * @defaultValue `false` + */ + allowViewportOverflow: boolean; +} +export interface ExpectOptsConfig { + wait: number; + interval: number; +} +export interface MochaOpts { + /** milliseconds to wait before considering a test slow. */ + slow?: number; + /** timeout in milliseconds or time string like '1s'. */ + timeout?: number; + /** string or regexp to filter tests with. */ + grep?: string | RegExp; +} +export interface SystemConfig { + debug: boolean; + mochaOpts: MochaOpts; + expectOpts: ExpectOptsConfig; + ctx: { + [name: string]: unknown; + }; + patternsOnReject: Array; + workers: number; + testsPerWorker: number; + diffColor: string; + tempDir: string; + parallelLimit: number; + fileExtensions: Array; +} +export interface CommonConfig { + configPath?: string; + automationProtocol: "webdriver" | "devtools"; + desiredCapabilities: WebDriver.DesiredCapabilities | null; + gridUrl: string; + baseUrl: string; + sessionsPerBrowser: number; + testsPerSession: number; + retry: number; + shouldRetry(testInfo: { + ctx: Test; + retriesLeft: number; + }): boolean | null; + httpTimeout: number; + urlHttpTimeout: number | null; + pageLoadTimeout: number | null; + sessionRequestTimeout: number | null; + sessionQuitTimeout: number | null; + testTimeout: number | null; + waitTimeout: number; + saveHistoryMode: "all" | "none" | "onlyFailed"; + takeScreenshotOnFails: { + testFail: boolean; + assertViewFail: boolean; + }; + takeScreenshotOnFailsTimeout: number | null; + takeScreenshotOnFailsMode: "fullpage" | "viewport"; + prepareBrowser(browser: WebdriverIO.Browser): void | null; + screenshotPath: string | null; + screenshotsDir(test: Test): string; + calibrate: boolean; + compositeImage: boolean; + strictTestsOrder: boolean; + screenshotMode: "fullpage" | "viewport" | "auto"; + screenshotDelay: number; + tolerance: number; + antialiasingTolerance: number; + compareOpts: CompareOptsConfig; + buildDiffOpts: BuildDiffOptsConfig; + assertViewOpts: AssertViewOptsConfig; + expectOpts: ExpectOptsConfig; + meta: { + [name: string]: unknown; + }; + windowSize: string | { + width: number; + height: number; + } | null; + orientation: "landscape" | "portrait" | null; + resetCursor: boolean; + headers: Record | null; + system: SystemConfig; + headless: boolean | null; + isolation: boolean; + openAndWaitOpts: { + timeout?: number; + waitNetworkIdle: boolean; + waitNetworkIdleTimeout: number; + failOnNetworkError: boolean; + ignoreNetworkErrorsPatterns: Array; + }; +} +export interface SetsConfig { + files: string | Array; + ignoreFiles?: Array; + browsers?: Array; +} +export type ConfigInput = { + browsers: Record, "desiredCapabilities">>; + plugins?: Record; + sets?: Record; + prepareEnvironment?: () => void | null; +}; +declare module "." { + interface Config extends CommonConfig { + browsers: Record; + plugins: Record>; + sets: Record; + prepareEnvironment?: () => void | null; + } +} +declare module "./browser-config" { + interface BrowserConfig extends CommonConfig { + id: string; + } +} diff --git a/build/src/config/types.js b/build/src/config/types.js new file mode 100644 index 000000000..11e638d1e --- /dev/null +++ b/build/src/config/types.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/build/src/config/types.js.map b/build/src/config/types.js.map new file mode 100644 index 000000000..04a6f7d2c --- /dev/null +++ b/build/src/config/types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/build/src/config/utils.d.ts b/build/src/config/utils.d.ts new file mode 100644 index 000000000..bbd8dbca5 --- /dev/null +++ b/build/src/config/utils.d.ts @@ -0,0 +1,11 @@ +export function assertNonNegativeNumber(value: any, name: any): void; +export function assertOptionalObject(value: any, name: any): void; +export function assertOptionalArray(value: any, name: any): void; +export function assertNonNegativeInteger(value: any, name: any): void; +export function assertEnum(enumValues: any, value: any, name: any): void; +export function assertPositiveInteger(value: any, name: any): void; +export function assertPositiveIntegerOrInfinity(value: any, name: any): void; +export const parseBoolean: any; +export const parsePrimitive: any; +export function resolveWithProjectDir(value: any): any; +export function is(type: any, name: any): (value: any) => void; diff --git a/build/src/config/utils.js b/build/src/config/utils.js new file mode 100644 index 000000000..58d05f69a --- /dev/null +++ b/build/src/config/utils.js @@ -0,0 +1,73 @@ +"use strict"; +const path = require("path"); +const _ = require("lodash"); +const is = (type, name) => { + return value => { + if (typeof value !== type) { + throw new Error(`"${name}" must be a ${type}`); + } + }; +}; +exports.is = is; +exports.assertNonNegativeNumber = (value, name) => { + is("number", name)(value); + if (value < 0) { + throw new Error(`"${name}" must be non-negative`); + } +}; +exports.assertOptionalObject = (value, name) => { + if (!_.isNull(value) && !_.isPlainObject(value)) { + throw new Error(`"${name}" must be an object`); + } +}; +exports.assertOptionalArray = (value, name) => { + if (!_.isArray(value)) { + throw new Error(`"${name}" must be an array`); + } +}; +exports.assertNonNegativeInteger = (value, name) => { + if (!Number.isInteger(value) || value < 0) { + throw new Error(`"${name}" must be a non-negative integer`); + } +}; +exports.assertEnum = (enumValues, value, name) => { + is("string", name)(value); + if (!_.includes(enumValues, value)) { + throw new Error(`"${name}" must be one of: ${enumValues.join(", ")}`); + } +}; +const isPositiveInteger = value => Number.isInteger(value) && value > 0; +exports.assertPositiveInteger = (value, name) => { + if (!isPositiveInteger(value)) { + throw new Error(`"${name}" must be a positive integer`); + } +}; +exports.assertPositiveIntegerOrInfinity = (value, name) => { + if (!isPositiveInteger(value) && value !== Infinity) { + throw new Error(`"${name}" must be a positive integer or Infinity`); + } +}; +exports.parseBoolean = exports.parseBoolean = (value, name) => { + switch (value.toLowerCase()) { + case "1": + case "yes": + case "true": + return true; + case "0": + case "no": + case "false": + return false; + default: + throw new Error(`Unexpected value for boolean option "${name}"`); + } +}; +exports.parsePrimitive = exports.parsePrimitive = str => { + try { + return JSON.parse(str); + } + catch (error) { + throw new Error("a value must be a primitive type"); + } +}; +exports.resolveWithProjectDir = value => (value ? path.resolve(process.cwd(), value) : value); +//# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/build/src/config/utils.js.map b/build/src/config/utils.js.map new file mode 100644 index 000000000..c1d5009b1 --- /dev/null +++ b/build/src/config/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/config/utils.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAC7B,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE5B,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;IACtB,OAAO,KAAK,CAAC,EAAE;QACX,IAAI,OAAO,KAAK,KAAK,IAAI,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,eAAe,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;IACL,CAAC,CAAC;AACN,CAAC,CAAC;AAEF,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;AAEhB,OAAO,CAAC,uBAAuB,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IAC9C,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC;IAC1B,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,wBAAwB,CAAC,CAAC;IACtD,CAAC;AACL,CAAC,CAAC;AAEF,OAAO,CAAC,oBAAoB,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IAC3C,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,qBAAqB,CAAC,CAAC;IACnD,CAAC;AACL,CAAC,CAAC;AAEF,OAAO,CAAC,mBAAmB,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IAC1C,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,oBAAoB,CAAC,CAAC;IAClD,CAAC;AACL,CAAC,CAAC;AAEF,OAAO,CAAC,wBAAwB,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IAC/C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,kCAAkC,CAAC,CAAC;IAChE,CAAC;AACL,CAAC,CAAC;AAEF,OAAO,CAAC,UAAU,GAAG,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAC7C,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC;IAE1B,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,qBAAqB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;AAExE,OAAO,CAAC,qBAAqB,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IAC5C,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,8BAA8B,CAAC,CAAC;IAC5D,CAAC;AACL,CAAC,CAAC;AAEF,OAAO,CAAC,+BAA+B,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACtD,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,0CAA0C,CAAC,CAAC;IACxE,CAAC;AACL,CAAC,CAAC;AAEF,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IAC1D,QAAQ,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QAC1B,KAAK,GAAG,CAAC;QACT,KAAK,KAAK,CAAC;QACX,KAAK,MAAM;YACP,OAAO,IAAI,CAAC;QAChB,KAAK,GAAG,CAAC;QACT,KAAK,IAAI,CAAC;QACV,KAAK,OAAO;YACR,OAAO,KAAK,CAAC;QACjB;YACI,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,GAAG,CAAC,CAAC;IACzE,CAAC;AACL,CAAC,CAAC;AAEF,OAAO,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,GAAG,GAAG,CAAC,EAAE;IACpD,IAAI,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACxD,CAAC;AACL,CAAC,CAAC;AAEF,OAAO,CAAC,qBAAqB,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/constants/browser.d.ts b/build/src/constants/browser.d.ts new file mode 100644 index 000000000..fd3a9402a --- /dev/null +++ b/build/src/constants/browser.d.ts @@ -0,0 +1,2 @@ +export declare const MIN_CHROME_VERSION_SUPPORT_ISOLATION = 93; +export declare const X_REQUEST_ID_DELIMITER = "__"; diff --git a/build/src/constants/browser.js b/build/src/constants/browser.js new file mode 100644 index 000000000..b9362afd4 --- /dev/null +++ b/build/src/constants/browser.js @@ -0,0 +1,6 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.X_REQUEST_ID_DELIMITER = exports.MIN_CHROME_VERSION_SUPPORT_ISOLATION = void 0; +exports.MIN_CHROME_VERSION_SUPPORT_ISOLATION = 93; +exports.X_REQUEST_ID_DELIMITER = "__"; +//# sourceMappingURL=browser.js.map \ No newline at end of file diff --git a/build/src/constants/browser.js.map b/build/src/constants/browser.js.map new file mode 100644 index 000000000..35e4fa07b --- /dev/null +++ b/build/src/constants/browser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../../src/constants/browser.ts"],"names":[],"mappings":";;;AAAa,QAAA,oCAAoC,GAAG,EAAE,CAAC;AAC1C,QAAA,sBAAsB,GAAG,IAAI,CAAC"} \ No newline at end of file diff --git a/build/src/constants/config.d.ts b/build/src/constants/config.d.ts new file mode 100644 index 000000000..cd0fdafe5 --- /dev/null +++ b/build/src/constants/config.d.ts @@ -0,0 +1,7 @@ +export let WEBDRIVER_PROTOCOL: string; +export let DEVTOOLS_PROTOCOL: string; +export namespace SAVE_HISTORY_MODE { + let ALL: string; + let NONE: string; + let ONLY_FAILED: string; +} diff --git a/build/src/constants/config.js b/build/src/constants/config.js new file mode 100644 index 000000000..598b644bd --- /dev/null +++ b/build/src/constants/config.js @@ -0,0 +1,11 @@ +"use strict"; +module.exports = { + WEBDRIVER_PROTOCOL: "webdriver", + DEVTOOLS_PROTOCOL: "devtools", + SAVE_HISTORY_MODE: { + ALL: "all", + NONE: "none", + ONLY_FAILED: "onlyFailed", + }, +}; +//# sourceMappingURL=config.js.map \ No newline at end of file diff --git a/build/src/constants/config.js.map b/build/src/constants/config.js.map new file mode 100644 index 000000000..d7e23c336 --- /dev/null +++ b/build/src/constants/config.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/constants/config.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,OAAO,GAAG;IACb,kBAAkB,EAAE,WAAW;IAC/B,iBAAiB,EAAE,UAAU;IAC7B,iBAAiB,EAAE;QACf,GAAG,EAAE,KAAK;QACV,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,YAAY;KAC5B;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/constants/process-messages.d.ts b/build/src/constants/process-messages.d.ts new file mode 100644 index 000000000..69aadb638 --- /dev/null +++ b/build/src/constants/process-messages.d.ts @@ -0,0 +1,5 @@ +export declare const MASTER_INIT = "master.init"; +export declare const MASTER_SYNC_CONFIG = "master.syncConfig"; +export declare const WORKER_INIT = "worker.init"; +export declare const WORKER_SYNC_CONFIG = "worker.syncConfig"; +export declare const WORKER_UNHANDLED_REJECTION = "worker.unhandledRejection"; diff --git a/build/src/constants/process-messages.js b/build/src/constants/process-messages.js new file mode 100644 index 000000000..22d726fd2 --- /dev/null +++ b/build/src/constants/process-messages.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.WORKER_UNHANDLED_REJECTION = exports.WORKER_SYNC_CONFIG = exports.WORKER_INIT = exports.MASTER_SYNC_CONFIG = exports.MASTER_INIT = void 0; +exports.MASTER_INIT = "master.init"; +exports.MASTER_SYNC_CONFIG = "master.syncConfig"; +exports.WORKER_INIT = "worker.init"; +exports.WORKER_SYNC_CONFIG = "worker.syncConfig"; +exports.WORKER_UNHANDLED_REJECTION = "worker.unhandledRejection"; +//# sourceMappingURL=process-messages.js.map \ No newline at end of file diff --git a/build/src/constants/process-messages.js.map b/build/src/constants/process-messages.js.map new file mode 100644 index 000000000..13c896c27 --- /dev/null +++ b/build/src/constants/process-messages.js.map @@ -0,0 +1 @@ +{"version":3,"file":"process-messages.js","sourceRoot":"","sources":["../../../src/constants/process-messages.ts"],"names":[],"mappings":";;;AAAa,QAAA,WAAW,GAAG,aAAa,CAAC;AAC5B,QAAA,kBAAkB,GAAG,mBAAmB,CAAC;AAEzC,QAAA,WAAW,GAAG,aAAa,CAAC;AAC5B,QAAA,kBAAkB,GAAG,mBAAmB,CAAC;AACzC,QAAA,0BAA0B,GAAG,2BAA2B,CAAC"} \ No newline at end of file diff --git a/build/src/constants/test-statuses.d.ts b/build/src/constants/test-statuses.d.ts new file mode 100644 index 000000000..e841e2857 --- /dev/null +++ b/build/src/constants/test-statuses.d.ts @@ -0,0 +1,4 @@ +export let SUCCESS: string; +export let FAIL: string; +export let RETRY: string; +export let SKIPPED: string; diff --git a/build/src/constants/test-statuses.js b/build/src/constants/test-statuses.js new file mode 100644 index 000000000..14a8d6018 --- /dev/null +++ b/build/src/constants/test-statuses.js @@ -0,0 +1,8 @@ +"use strict"; +module.exports = { + SUCCESS: "success", + FAIL: "fail", + RETRY: "retry", + SKIPPED: "skipped", +}; +//# sourceMappingURL=test-statuses.js.map \ No newline at end of file diff --git a/build/src/constants/test-statuses.js.map b/build/src/constants/test-statuses.js.map new file mode 100644 index 000000000..803733071 --- /dev/null +++ b/build/src/constants/test-statuses.js.map @@ -0,0 +1 @@ +{"version":3,"file":"test-statuses.js","sourceRoot":"","sources":["../../../src/constants/test-statuses.js"],"names":[],"mappings":";AAAA,MAAM,CAAC,OAAO,GAAG;IACb,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;CACrB,CAAC"} \ No newline at end of file diff --git a/build/src/errors.d.ts b/build/src/errors.d.ts new file mode 100644 index 000000000..bdc6367c7 --- /dev/null +++ b/build/src/errors.d.ts @@ -0,0 +1,19 @@ +import { CoreError } from "./browser/core-error"; +import { CancelledError } from "./browser-pool/cancelled-error"; +import { ClientBridgeError } from "./browser/client-bridge/error"; +import { HeightViewportError } from "./browser/screen-shooter/viewport/coord-validator/errors/height-viewport-error"; +import { OffsetViewportError } from "./browser/screen-shooter/viewport/coord-validator/errors/offset-viewport-error"; +import { AssertViewError } from "./browser/commands/assert-view/errors/assert-view-error"; +import { ImageDiffError } from "./browser/commands/assert-view/errors/image-diff-error"; +import { NoRefImageError } from "./browser/commands/assert-view/errors/no-ref-image-error"; +declare const Errors: { + readonly CoreError: typeof CoreError; + readonly CancelledError: typeof CancelledError; + readonly ClientBridgeError: typeof ClientBridgeError; + readonly HeightViewportError: typeof HeightViewportError; + readonly OffsetViewportError: typeof OffsetViewportError; + readonly AssertViewError: typeof AssertViewError; + readonly ImageDiffError: typeof ImageDiffError; + readonly NoRefImageError: typeof NoRefImageError; +}; +export default Errors; diff --git a/build/src/errors.js b/build/src/errors.js new file mode 100644 index 000000000..9b91d454b --- /dev/null +++ b/build/src/errors.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const core_error_1 = require("./browser/core-error"); +const cancelled_error_1 = require("./browser-pool/cancelled-error"); +const error_1 = require("./browser/client-bridge/error"); +const height_viewport_error_1 = require("./browser/screen-shooter/viewport/coord-validator/errors/height-viewport-error"); +const offset_viewport_error_1 = require("./browser/screen-shooter/viewport/coord-validator/errors/offset-viewport-error"); +const assert_view_error_1 = require("./browser/commands/assert-view/errors/assert-view-error"); +const image_diff_error_1 = require("./browser/commands/assert-view/errors/image-diff-error"); +const no_ref_image_error_1 = require("./browser/commands/assert-view/errors/no-ref-image-error"); +const Errors = { + CoreError: core_error_1.CoreError, + CancelledError: cancelled_error_1.CancelledError, + ClientBridgeError: error_1.ClientBridgeError, + HeightViewportError: height_viewport_error_1.HeightViewportError, + OffsetViewportError: offset_viewport_error_1.OffsetViewportError, + AssertViewError: assert_view_error_1.AssertViewError, + ImageDiffError: image_diff_error_1.ImageDiffError, + NoRefImageError: no_ref_image_error_1.NoRefImageError, +}; +exports.default = Errors; +//# sourceMappingURL=errors.js.map \ No newline at end of file diff --git a/build/src/errors.js.map b/build/src/errors.js.map new file mode 100644 index 000000000..04e959cc5 --- /dev/null +++ b/build/src/errors.js.map @@ -0,0 +1 @@ +{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":";;AAAA,qDAAiD;AACjD,oEAAgE;AAChE,yDAAkE;AAClE,0HAAqH;AACrH,0HAAqH;AACrH,+FAA0F;AAC1F,6FAAwF;AACxF,iGAA2F;AAG3F,MAAM,MAAM,GAAG;IACX,SAAS,EAAT,sBAAS;IACT,cAAc,EAAd,gCAAc;IACd,iBAAiB,EAAjB,yBAAiB;IACjB,mBAAmB,EAAnB,2CAAmB;IACnB,mBAAmB,EAAnB,2CAAmB;IACnB,eAAe,EAAf,mCAAe;IACf,cAAc,EAAd,iCAAc;IACd,eAAe,EAAf,oCAAe;CACoC,CAAC;AAExD,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/build/src/events/async-emitter/index.d.ts b/build/src/events/async-emitter/index.d.ts new file mode 100644 index 000000000..9945e7c47 --- /dev/null +++ b/build/src/events/async-emitter/index.d.ts @@ -0,0 +1,5 @@ +/// +import { EventEmitter } from "events"; +export declare class AsyncEmitter extends EventEmitter { + emitAndWait(event: string | symbol, ...args: unknown[]): Promise; +} diff --git a/build/src/events/async-emitter/index.js b/build/src/events/async-emitter/index.js new file mode 100644 index 000000000..de2eb1b0d --- /dev/null +++ b/build/src/events/async-emitter/index.js @@ -0,0 +1,19 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.AsyncEmitter = void 0; +const events_1 = require("events"); +const bluebird_1 = __importDefault(require("bluebird")); +class AsyncEmitter extends events_1.EventEmitter { + async emitAndWait(event, ...args) { + const results = await Promise.allSettled(this.listeners(event).map(l => bluebird_1.default.method(l).apply(this, args))); + const rejected = results.find(({ status }) => status === "rejected"); + return rejected + ? Promise.reject(rejected.reason) + : results.map(r => r.value); + } +} +exports.AsyncEmitter = AsyncEmitter; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/events/async-emitter/index.js.map b/build/src/events/async-emitter/index.js.map new file mode 100644 index 000000000..510940424 --- /dev/null +++ b/build/src/events/async-emitter/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/events/async-emitter/index.ts"],"names":[],"mappings":";;;;;;AAAA,mCAAsC;AACtC,wDAAuC;AAEvC,MAAa,YAAa,SAAQ,qBAAY;IAC1C,KAAK,CAAC,WAAW,CAAC,KAAsB,EAAE,GAAG,IAAe;QACxD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CACpC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAC1B,kBAAe,CAAC,MAAM,CAAC,CAAoC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,IAAU,CAAC,CACvF,CACJ,CAAC;QAEF,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC;QACrE,OAAO,QAAQ;YACX,CAAC,CAAC,OAAO,CAAC,MAAM,CAAE,QAAkC,CAAC,MAAM,CAAC;YAC5D,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAE,CAAqC,CAAC,KAAK,CAAC,CAAC;IACzE,CAAC;CACJ;AAbD,oCAaC"} \ No newline at end of file diff --git a/build/src/events/index.d.ts b/build/src/events/index.d.ts new file mode 100644 index 000000000..be3e7740b --- /dev/null +++ b/build/src/events/index.d.ts @@ -0,0 +1,134 @@ +import { ValueOf } from "type-fest"; +export * from "./async-emitter"; +export * from "./types"; +export declare const TestReaderEvents: { + readonly NEW_BUILD_INSTRUCTION: "newBuildInstruction"; +}; +export type TestReaderEvents = typeof TestReaderEvents; +export type TestReaderEvent = ValueOf; +export declare const MasterAsyncEvents: { + readonly INIT: "init"; + readonly RUNNER_START: "startRunner"; + readonly RUNNER_END: "endRunner"; + readonly SESSION_START: "startSession"; + readonly SESSION_END: "endSession"; + readonly EXIT: "exit"; +}; +export type MasterAsyncEvents = typeof MasterAsyncEvents; +export type MasterAsyncEvent = ValueOf; +export declare const RunnerSyncEvents: { + readonly NEW_WORKER_PROCESS: "newWorkerProcess"; + readonly SUITE_BEGIN: "beginSuite"; + readonly SUITE_END: "endSuite"; + readonly TEST_BEGIN: "beginTest"; + readonly TEST_END: "endTest"; + readonly TEST_PASS: "passTest"; + readonly TEST_FAIL: "failTest"; + readonly TEST_PENDING: "pendingTest"; + readonly RETRY: "retry"; +}; +export type RunnerSyncEvents = typeof RunnerSyncEvents; +export type RunnerSyncEvent = ValueOf; +export declare const CommonSyncEvents: { + readonly CLI: "cli"; + readonly BEGIN: "begin"; + readonly END: "end"; + readonly BEFORE_FILE_READ: "beforeFileRead"; + readonly AFTER_FILE_READ: "afterFileRead"; + readonly AFTER_TESTS_READ: "afterTestsRead"; + readonly INFO: "info"; + readonly WARNING: "warning"; + readonly ERROR: "err"; +}; +export type CommonSyncEvents = typeof CommonSyncEvents; +export type CommonSyncEvent = ValueOf; +export declare const MasterSyncEvents: { + CLI: "cli"; + BEGIN: "begin"; + END: "end"; + BEFORE_FILE_READ: "beforeFileRead"; + AFTER_FILE_READ: "afterFileRead"; + AFTER_TESTS_READ: "afterTestsRead"; + INFO: "info"; + WARNING: "warning"; + ERROR: "err"; + NEW_WORKER_PROCESS: "newWorkerProcess"; + SUITE_BEGIN: "beginSuite"; + SUITE_END: "endSuite"; + TEST_BEGIN: "beginTest"; + TEST_END: "endTest"; + TEST_PASS: "passTest"; + TEST_FAIL: "failTest"; + TEST_PENDING: "pendingTest"; + RETRY: "retry"; +}; +export type MasterSyncEvents = typeof MasterSyncEvents; +export type MasterSyncEvent = RunnerSyncEvent | CommonSyncEvent; +export declare const MasterEvents: { + readonly CLI: "cli"; + readonly BEGIN: "begin"; + readonly END: "end"; + readonly BEFORE_FILE_READ: "beforeFileRead"; + readonly AFTER_FILE_READ: "afterFileRead"; + readonly AFTER_TESTS_READ: "afterTestsRead"; + readonly INFO: "info"; + readonly WARNING: "warning"; + readonly ERROR: "err"; + readonly NEW_WORKER_PROCESS: "newWorkerProcess"; + readonly SUITE_BEGIN: "beginSuite"; + readonly SUITE_END: "endSuite"; + readonly TEST_BEGIN: "beginTest"; + readonly TEST_END: "endTest"; + readonly TEST_PASS: "passTest"; + readonly TEST_FAIL: "failTest"; + readonly TEST_PENDING: "pendingTest"; + readonly RETRY: "retry"; + readonly INIT: "init"; + readonly RUNNER_START: "startRunner"; + readonly RUNNER_END: "endRunner"; + readonly SESSION_START: "startSession"; + readonly SESSION_END: "endSession"; + readonly EXIT: "exit"; +}; +export type MasterEvents = typeof MasterEvents; +export type MasterEvent = MasterAsyncEvent | MasterSyncEvent; +export declare const WorkerEvents: { + readonly INIT: "init"; + readonly BEFORE_FILE_READ: "beforeFileRead"; + readonly AFTER_FILE_READ: "afterFileRead"; + readonly AFTER_TESTS_READ: "afterTestsRead"; + readonly NEW_BROWSER: "newBrowser"; + readonly UPDATE_REFERENCE: "updateReference"; +}; +export type WorkerEvents = typeof WorkerEvents; +export type WorkerEvent = ValueOf; +export type InterceptedEvent = ValueOf>; +export declare const Events: { + readonly INIT: "init"; + readonly BEFORE_FILE_READ: "beforeFileRead"; + readonly AFTER_FILE_READ: "afterFileRead"; + readonly AFTER_TESTS_READ: "afterTestsRead"; + readonly NEW_BROWSER: "newBrowser"; + readonly UPDATE_REFERENCE: "updateReference"; + readonly CLI: "cli"; + readonly BEGIN: "begin"; + readonly END: "end"; + readonly INFO: "info"; + readonly WARNING: "warning"; + readonly ERROR: "err"; + readonly NEW_WORKER_PROCESS: "newWorkerProcess"; + readonly SUITE_BEGIN: "beginSuite"; + readonly SUITE_END: "endSuite"; + readonly TEST_BEGIN: "beginTest"; + readonly TEST_END: "endTest"; + readonly TEST_PASS: "passTest"; + readonly TEST_FAIL: "failTest"; + readonly TEST_PENDING: "pendingTest"; + readonly RETRY: "retry"; + readonly RUNNER_START: "startRunner"; + readonly RUNNER_END: "endRunner"; + readonly SESSION_START: "startSession"; + readonly SESSION_END: "endSession"; + readonly EXIT: "exit"; +}; +export type Events = typeof Events; diff --git a/build/src/events/index.js b/build/src/events/index.js new file mode 100644 index 000000000..40284ab58 --- /dev/null +++ b/build/src/events/index.js @@ -0,0 +1,73 @@ +"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 __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Events = exports.WorkerEvents = exports.MasterEvents = exports.MasterSyncEvents = exports.CommonSyncEvents = exports.RunnerSyncEvents = exports.MasterAsyncEvents = exports.TestReaderEvents = void 0; +__exportStar(require("./async-emitter"), exports); +__exportStar(require("./types"), exports); +exports.TestReaderEvents = { + NEW_BUILD_INSTRUCTION: "newBuildInstruction", +}; +exports.MasterAsyncEvents = { + INIT: "init", + RUNNER_START: "startRunner", + RUNNER_END: "endRunner", + SESSION_START: "startSession", + SESSION_END: "endSession", + EXIT: "exit", +}; +exports.RunnerSyncEvents = { + NEW_WORKER_PROCESS: "newWorkerProcess", + SUITE_BEGIN: "beginSuite", + SUITE_END: "endSuite", + TEST_BEGIN: "beginTest", + TEST_END: "endTest", + TEST_PASS: "passTest", + TEST_FAIL: "failTest", + TEST_PENDING: "pendingTest", + RETRY: "retry", +}; +exports.CommonSyncEvents = { + CLI: "cli", + BEGIN: "begin", + END: "end", + BEFORE_FILE_READ: "beforeFileRead", + AFTER_FILE_READ: "afterFileRead", + AFTER_TESTS_READ: "afterTestsRead", + INFO: "info", + WARNING: "warning", + ERROR: "err", +}; +exports.MasterSyncEvents = { + ...exports.RunnerSyncEvents, + ...exports.CommonSyncEvents, +}; +exports.MasterEvents = { + ...exports.MasterAsyncEvents, + ...exports.MasterSyncEvents, +}; +exports.WorkerEvents = { + INIT: exports.MasterEvents.INIT, + BEFORE_FILE_READ: exports.MasterEvents.BEFORE_FILE_READ, + AFTER_FILE_READ: exports.MasterEvents.AFTER_FILE_READ, + AFTER_TESTS_READ: exports.MasterEvents.AFTER_TESTS_READ, + NEW_BROWSER: "newBrowser", + UPDATE_REFERENCE: "updateReference", +}; +exports.Events = { + ...exports.MasterEvents, + ...exports.WorkerEvents, +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/events/index.js.map b/build/src/events/index.js.map new file mode 100644 index 000000000..fb53370bd --- /dev/null +++ b/build/src/events/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/events/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAEA,kDAAgC;AAChC,0CAAwB;AAEX,QAAA,gBAAgB,GAAG;IAC5B,qBAAqB,EAAE,qBAAqB;CACtC,CAAC;AAME,QAAA,iBAAiB,GAAG;IAC7B,IAAI,EAAE,MAAM;IAEZ,YAAY,EAAE,aAAa;IAC3B,UAAU,EAAE,WAAW;IAEvB,aAAa,EAAE,cAAc;IAC7B,WAAW,EAAE,YAAY;IAEzB,IAAI,EAAE,MAAM;CACN,CAAC;AAME,QAAA,gBAAgB,GAAG;IAC5B,kBAAkB,EAAE,kBAAkB;IAEtC,WAAW,EAAE,YAAY;IACzB,SAAS,EAAE,UAAU;IAErB,UAAU,EAAE,WAAW;IACvB,QAAQ,EAAE,SAAS;IAEnB,SAAS,EAAE,UAAU;IACrB,SAAS,EAAE,UAAU;IACrB,YAAY,EAAE,aAAa;IAE3B,KAAK,EAAE,OAAO;CACR,CAAC;AAME,QAAA,gBAAgB,GAAG;IAC5B,GAAG,EAAE,KAAK;IAEV,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,KAAK;IAEV,gBAAgB,EAAE,gBAAgB;IAClC,eAAe,EAAE,eAAe;IAEhC,gBAAgB,EAAE,gBAAgB;IAElC,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,KAAK;CACN,CAAC;AAME,QAAA,gBAAgB,GAAG;IAC5B,GAAG,wBAAgB;IACnB,GAAG,wBAAgB;CACtB,CAAC;AAMW,QAAA,YAAY,GAAG;IACxB,GAAG,yBAAiB;IACpB,GAAG,wBAAgB;CACb,CAAC;AAME,QAAA,YAAY,GAAG;IACxB,IAAI,EAAE,oBAAY,CAAC,IAAI;IAEvB,gBAAgB,EAAE,oBAAY,CAAC,gBAAgB;IAC/C,eAAe,EAAE,oBAAY,CAAC,eAAe;IAE7C,gBAAgB,EAAE,oBAAY,CAAC,gBAAgB;IAE/C,WAAW,EAAE,YAAY;IAEzB,gBAAgB,EAAE,iBAAiB;CAC7B,CAAC;AAaE,QAAA,MAAM,GAAG;IAClB,GAAG,oBAAY;IACf,GAAG,oBAAY;CACT,CAAC"} \ No newline at end of file diff --git a/build/src/events/types.d.ts b/build/src/events/types.d.ts new file mode 100644 index 000000000..0c8060a82 --- /dev/null +++ b/build/src/events/types.d.ts @@ -0,0 +1,11 @@ +import { InterceptedEvent } from "."; +import { Test } from "../test-reader/test-object/test"; +export interface InterceptData { + event?: InterceptedEvent; + data?: Test; +} +export type InterceptHandler = (arg: InterceptData) => InterceptData | void; +export interface Interceptor { + event: InterceptedEvent; + handler: InterceptHandler; +} diff --git a/build/src/events/types.js b/build/src/events/types.js new file mode 100644 index 000000000..11e638d1e --- /dev/null +++ b/build/src/events/types.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/build/src/events/types.js.map b/build/src/events/types.js.map new file mode 100644 index 000000000..f6cda6c3b --- /dev/null +++ b/build/src/events/types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/events/types.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/build/src/events/utils.d.ts b/build/src/events/utils.d.ts new file mode 100644 index 000000000..4db005c56 --- /dev/null +++ b/build/src/events/utils.d.ts @@ -0,0 +1,2 @@ +export function passthroughEvent(from: any, to: any, event: any): void; +export function passthroughEventAsync(from: any, to: any, event: any): void; diff --git a/build/src/events/utils.js b/build/src/events/utils.js new file mode 100644 index 000000000..4b2236be8 --- /dev/null +++ b/build/src/events/utils.js @@ -0,0 +1,14 @@ +"use strict"; +const mkPassthroughFn = methodName => { + const passEvents = (from, to, event) => { + if (typeof event === "string") { + from.on(event, (...args) => to[methodName](event, ...args)); + return; + } + event.forEach(event => passEvents(from, to, event)); + }; + return passEvents; +}; +exports.passthroughEvent = mkPassthroughFn("emit"); +exports.passthroughEventAsync = mkPassthroughFn("emitAndWait"); +//# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/build/src/events/utils.js.map b/build/src/events/utils.js.map new file mode 100644 index 000000000..411675d9c --- /dev/null +++ b/build/src/events/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/events/utils.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,eAAe,GAAG,UAAU,CAAC,EAAE;IACjC,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE;QACnC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC5B,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;YAC5D,OAAO;QACX,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC;IAEF,OAAO,UAAU,CAAC;AACtB,CAAC,CAAC;AAEF,OAAO,CAAC,gBAAgB,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;AACnD,OAAO,CAAC,qBAAqB,GAAG,eAAe,CAAC,aAAa,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/hermione.d.ts b/build/src/hermione.d.ts new file mode 100644 index 000000000..d0d8ad15b --- /dev/null +++ b/build/src/hermione.d.ts @@ -0,0 +1,47 @@ +import { CommanderStatic } from "@gemini-testing/commander"; +import { BaseHermione } from "./base-hermione"; +import { MainRunner } from "./runner"; +import { TestCollection } from "./test-collection"; +import { ConfigInput } from "./config/types"; +import { MasterEventHandler, Test } from "./types"; +interface RunOpts { + browsers: string[]; + sets: string[]; + grep: RegExp; + updateRefs: boolean; + requireModules: string[]; + inspectMode: { + inspect: boolean; + inspectBrk: boolean; + }; + reporters: string[]; + replMode: { + enabled: boolean; + beforeTest: boolean; + onFail: boolean; + }; +} +interface ReadTestsOpts extends Pick { + silent: boolean; + ignore: string | string[]; +} +export interface Hermione { + on: MasterEventHandler; + once: MasterEventHandler; + prependListener: MasterEventHandler; +} +export declare class Hermione extends BaseHermione { + protected failed: boolean; + protected runner: MainRunner | null; + constructor(config?: string | ConfigInput); + extendCli(parser: CommanderStatic): void; + run(testPaths: TestCollection | string[], { browsers, sets, grep, updateRefs, requireModules, inspectMode, replMode, reporters, }?: Partial): Promise; + protected _readTests(testPaths: string[] | TestCollection, opts: Partial): Promise; + addTestToRun(test: Test, browserId: string): boolean; + readTests(testPaths: string[], { browsers, sets, grep, silent, ignore, replMode }?: Partial): Promise; + isFailed(): boolean; + protected _fail(): void; + isWorker(): boolean; + halt(err: Error, timeout?: number): void; +} +export {}; diff --git a/build/src/hermione.js b/build/src/hermione.js new file mode 100644 index 000000000..af871f8fe --- /dev/null +++ b/build/src/hermione.js @@ -0,0 +1,121 @@ +"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.Hermione = void 0; +const _ = __importStar(require("lodash")); +const stats_1 = require("./stats"); +const base_hermione_1 = require("./base-hermione"); +const runner_1 = require("./runner"); +const runtime_config_1 = __importDefault(require("./config/runtime-config")); +const events_1 = require("./events"); +const utils_1 = __importDefault(require("./events/utils")); +const signal_handler_1 = __importDefault(require("./signal-handler")); +const test_reader_1 = __importDefault(require("./test-reader")); +const test_collection_1 = require("./test-collection"); +const validators_1 = require("./validators"); +const reporters_1 = require("./reporters"); +const logger_1 = __importDefault(require("./utils/logger")); +class Hermione extends base_hermione_1.BaseHermione { + constructor(config) { + super(config); + this.failed = false; + this.runner = null; + } + extendCli(parser) { + this.emit(events_1.MasterEvents.CLI, parser); + } + async run(testPaths, { browsers, sets, grep, updateRefs, requireModules, inspectMode, replMode, reporters = [], } = {}) { + (0, validators_1.validateUnknownBrowsers)(browsers, _.keys(this._config.browsers)); + runtime_config_1.default.getInstance().extend({ updateRefs, requireModules, inspectMode, replMode }); + if (replMode?.enabled) { + this._config.system.mochaOpts.timeout = 0; + } + const runner = runner_1.MainRunner.create(this._config, this._interceptors); + this.runner = runner; + this.on(events_1.MasterEvents.TEST_FAIL, () => this._fail()).on(events_1.MasterEvents.ERROR, (err) => this.halt(err)); + await (0, reporters_1.initReporters)(reporters, this); + utils_1.default.passthroughEvent(this.runner, this, _.values(events_1.MasterSyncEvents)); + utils_1.default.passthroughEventAsync(this.runner, this, _.values(events_1.MasterAsyncEvents)); + utils_1.default.passthroughEventAsync(signal_handler_1.default, this, events_1.MasterEvents.EXIT); + await this._init(); + runner.init(); + await runner.run(await this._readTests(testPaths, { browsers, sets, grep, replMode }), stats_1.Stats.create(this)); + return !this.isFailed(); + } + async _readTests(testPaths, opts) { + return testPaths instanceof test_collection_1.TestCollection ? testPaths : await this.readTests(testPaths, opts); + } + addTestToRun(test, browserId) { + return this.runner ? this.runner.addTestToRun(test, browserId) : false; + } + async readTests(testPaths, { browsers, sets, grep, silent, ignore, replMode } = {}) { + const testReader = test_reader_1.default.create(this._config); + if (!silent) { + await this._init(); + utils_1.default.passthroughEvent(testReader, this, [ + events_1.MasterEvents.BEFORE_FILE_READ, + events_1.MasterEvents.AFTER_FILE_READ, + ]); + } + const specs = await testReader.read({ paths: testPaths, browsers, ignore, sets, grep, replMode }); + const collection = test_collection_1.TestCollection.create(specs); + collection.getBrowsers().forEach(bro => { + if (this._config.forBrowser(bro).strictTestsOrder) { + collection.sortTests(bro, ({ id: a }, { id: b }) => (a < b ? -1 : 1)); + } + }); + if (!silent) { + this.emit(events_1.MasterEvents.AFTER_TESTS_READ, collection); + } + return collection; + } + isFailed() { + return this.failed; + } + _fail() { + this.failed = true; + } + isWorker() { + return false; + } + halt(err, timeout = 60000) { + logger_1.default.error("Terminating on critical error:", err); + this._fail(); + if (timeout > 0) { + setTimeout(() => { + logger_1.default.error("Forcing shutdown..."); + process.exit(1); + }, timeout).unref(); + } + if (this.runner) { + this.runner.cancel(); + } + } +} +exports.Hermione = Hermione; +//# sourceMappingURL=hermione.js.map \ No newline at end of file diff --git a/build/src/hermione.js.map b/build/src/hermione.js.map new file mode 100644 index 000000000..8fa43e824 --- /dev/null +++ b/build/src/hermione.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hermione.js","sourceRoot":"","sources":["../../src/hermione.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/image.d.ts b/build/src/image.d.ts new file mode 100644 index 000000000..54dcec007 --- /dev/null +++ b/build/src/image.d.ts @@ -0,0 +1,55 @@ +export = Image; +declare class Image { + static create(buffer: any): import("./image"); + static fromBase64(base64: any): import("./image"); + static compare(path1: any, path2: any, opts?: {}): globalThis.Promise; + static buildDiff(opts: any): globalThis.Promise; + constructor(buffer: any); + _img: sharp.Sharp; + _imageData: { + data: Buffer; + info: sharp.OutputInfo; + } | null; + _ignoreData: any[]; + _composeImages: any[]; + getSize(): globalThis.Promise<{ + width: number; + height: number; + }>; + crop(rect: any): globalThis.Promise; + addJoin(attachedImages: any): void; + applyJoin(): globalThis.Promise; + addClear({ width, height, left, top }: { + width: any; + height: any; + left: any; + top: any; + }): globalThis.Promise; + applyClear(): void; + _getImageData(): globalThis.Promise<{ + data: Buffer; + info: sharp.OutputInfo; + }>; + _forceRefreshImageData(): globalThis.Promise; + getRGBA(x: any, y: any): globalThis.Promise<{ + r: number; + g: number; + b: number; + a: number; + }>; + save(file: any): globalThis.Promise; + toPngBuffer(opts?: { + resolveWithObject: boolean; + }): globalThis.Promise<(Buffer & { + data: Buffer; + info: sharp.OutputInfo; + }) | { + data: Buffer; + size: { + height: number; + width: number; + }; + }>; +} +import sharp = require("sharp"); +import looksSame = require("looks-same"); diff --git a/build/src/image.js b/build/src/image.js new file mode 100644 index 000000000..16c15d36c --- /dev/null +++ b/build/src/image.js @@ -0,0 +1,144 @@ +"use strict"; +const Promise = require("bluebird"); +const looksSame = require("looks-same"); +const sharp = require("sharp"); +module.exports = class Image { + static create(buffer) { + return new this(buffer); + } + constructor(buffer) { + this._img = sharp(buffer); + this._imageData = null; + this._ignoreData = []; + this._composeImages = []; + } + async getSize() { + const imgSizes = await Promise.map([this].concat(this._composeImages), img => img._img.metadata()); + return imgSizes.reduce((totalSize, img) => { + return { + width: Math.max(totalSize.width, img.width), + height: totalSize.height + img.height, + }; + }, { width: 0, height: 0 }); + } + async crop(rect) { + const { height, width } = await this._img.metadata(); + this._img.extract({ + left: rect.left, + top: rect.top, + width: Math.min(width, rect.left + rect.width) - rect.left, + height: Math.min(height, rect.top + rect.height) - rect.top, + }); + await this._forceRefreshImageData(); + } + addJoin(attachedImages) { + this._composeImages = this._composeImages.concat(attachedImages); + } + async applyJoin() { + if (!this._composeImages.length) { + return; + } + const { height, width } = await this._img.metadata(); + const imagesData = await Promise.all(this._composeImages.map(img => img._getImageData())); + const compositeData = []; + let newHeight = height; + for (const { data, info } of imagesData) { + compositeData.push({ + input: data, + left: 0, + top: newHeight, + raw: { + width: info.width, + height: info.height, + channels: info.channels, + }, + }); + newHeight += info.height; + } + this._img.resize({ + width, + height: newHeight, + fit: "contain", + position: "top", + }); + this._img.composite(compositeData); + } + async addClear({ width, height, left, top }) { + const { channels } = await this._img.metadata(); + this._ignoreData.push({ + input: { + create: { + channels, + background: { r: 0, g: 0, b: 0, alpha: 1 }, + width, + height, + }, + }, + left, + top, + }); + } + applyClear() { + this._img.composite(this._ignoreData); + } + async _getImageData() { + if (!this._imageData) { + this._imageData = await this._img.raw().toBuffer({ resolveWithObject: true }); + } + return this._imageData; + } + async _forceRefreshImageData() { + this._imageData = await this._img.raw().toBuffer({ resolveWithObject: true }); + this._img = sharp(this._imageData.data, { + raw: { + width: this._imageData.info.width, + height: this._imageData.info.height, + channels: this._imageData.info.channels, + }, + }); + this._composeImages = []; + this._ignoreData = []; + } + async getRGBA(x, y) { + const { data, info } = await this._getImageData(); + const idx = (info.width * y + x) * info.channels; + return { + r: data[idx], + g: data[idx + 1], + b: data[idx + 2], + a: info.channels === 4 ? data[idx + 3] : 1, + }; + } + async save(file) { + await this._img.png().toFile(file); + } + static fromBase64(base64) { + return new this(Buffer.from(base64, "base64")); + } + async toPngBuffer(opts = { resolveWithObject: true }) { + const imgData = await this._img.png().toBuffer(opts); + return opts.resolveWithObject + ? { data: imgData.data, size: { height: imgData.info.height, width: imgData.info.width } } + : imgData; + } + static compare(path1, path2, opts = {}) { + const compareOptions = { + ignoreCaret: opts.canHaveCaret, + pixelRatio: opts.pixelRatio, + ...opts.compareOpts, + createDiffImage: true, + }; + ["tolerance", "antialiasingTolerance"].forEach(option => { + if (option in opts) { + compareOptions[option] = opts[option]; + } + }); + return looksSame(path1, path2, compareOptions); + } + static buildDiff(opts) { + const { diffColor: highlightColor, ...otherOpts } = opts; + const diffOptions = { highlightColor, ...otherOpts }; + return looksSame.createDiff(diffOptions); + } +}; +//# sourceMappingURL=image.js.map \ No newline at end of file diff --git a/build/src/image.js.map b/build/src/image.js.map new file mode 100644 index 000000000..f77eb3a22 --- /dev/null +++ b/build/src/image.js.map @@ -0,0 +1 @@ +{"version":3,"file":"image.js","sourceRoot":"","sources":["../../src/image.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/index.d.ts b/build/src/index.d.ts new file mode 100644 index 000000000..96f45ae43 --- /dev/null +++ b/build/src/index.d.ts @@ -0,0 +1,13 @@ +/// +import "../typings/global"; +import "./browser/types"; +import "expect-webdriverio"; +import { GlobalHelper } from "./types"; +export { Hermione as default } from "./hermione"; +export type { WdioBrowser, TestResult, Test, Suite } from "./types"; +export type { Config } from "./config"; +export type { ConfigInput } from "./config/types"; +export type { TestCollection } from "./test-collection"; +declare global { + const hermione: GlobalHelper; +} diff --git a/build/src/index.js b/build/src/index.js new file mode 100644 index 000000000..5d12e9752 --- /dev/null +++ b/build/src/index.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = void 0; +// Declares global hooks +require("../typings/global"); +// Augments browser and element methods +require("./browser/types"); +// Declares global expect function +require("expect-webdriverio"); +var hermione_1 = require("./hermione"); +Object.defineProperty(exports, "default", { enumerable: true, get: function () { return hermione_1.Hermione; } }); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/index.js.map b/build/src/index.js.map new file mode 100644 index 000000000..203458c0a --- /dev/null +++ b/build/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,wBAAwB;AACxB,6BAA2B;AAC3B,uCAAuC;AACvC,2BAAyB;AACzB,kCAAkC;AAClC,8BAA4B;AAG5B,uCAAiD;AAAxC,mGAAA,QAAQ,OAAW"} \ No newline at end of file diff --git a/build/src/reporters/base.d.ts b/build/src/reporters/base.d.ts new file mode 100644 index 000000000..83ea96a12 --- /dev/null +++ b/build/src/reporters/base.d.ts @@ -0,0 +1,17 @@ +export = BaseReporter; +declare class BaseReporter { + static create(opts?: {}): Promise; + constructor(informer: any); + informer: any; + attachRunner(runner: any): void; + _onTestPass(test: any): void; + _onTestFail(test: any): void; + _onRetry(test: any): void; + _onTestPending(test: any): void; + _onBeforeRunnerEnd(stats: any): void; + _onRunnerEnd(stats: any): void; + _onWarning(info: any): void; + _onError(error: any): void; + _onInfo(info: any): void; + _logTestInfo(test: any, icon: any): void; +} diff --git a/build/src/reporters/base.js b/build/src/reporters/base.js new file mode 100644 index 000000000..f0bbdeeb8 --- /dev/null +++ b/build/src/reporters/base.js @@ -0,0 +1,65 @@ +"use strict"; +const chalk = require("chalk"); +const { MasterEvents } = require("../events"); +const icons = require("./utils/icons"); +const helpers = require("./utils/helpers"); +const { initInformer } = require("./informers"); +module.exports = class BaseReporter { + static async create(opts = {}) { + const informer = await initInformer(opts); + return new this(informer, opts); + } + constructor(informer) { + this.informer = informer; + } + attachRunner(runner) { + runner.on(MasterEvents.TEST_PASS, test => this._onTestPass(test)); + runner.on(MasterEvents.TEST_FAIL, test => this._onTestFail(test)); + runner.on(MasterEvents.RETRY, test => this._onRetry(test)); + runner.on(MasterEvents.TEST_PENDING, test => this._onTestPending(test)); + runner.on(MasterEvents.RUNNER_END, stats => this._onRunnerEnd(stats)); + runner.on(MasterEvents.WARNING, info => this._onWarning(info)); + runner.on(MasterEvents.ERROR, error => this._onError(error)); + runner.on(MasterEvents.INFO, info => this._onInfo(info)); + } + _onTestPass(test) { + this._logTestInfo(test, icons.SUCCESS); + } + _onTestFail(test) { + this._logTestInfo(test, icons.FAIL); + } + _onRetry(test) { + this._logTestInfo(test, icons.RETRY); + this.informer.log(`Will be retried. Retries left: ${chalk.yellow(test.retriesLeft)}`); + } + _onTestPending(test) { + this._logTestInfo(test, icons.WARN); + } + _onBeforeRunnerEnd(stats) { + const message = [ + `Total: ${chalk.underline(stats.total)}`, + `Passed: ${chalk.green(stats.passed)}`, + `Failed: ${chalk.red(stats.failed)}`, + `Skipped: ${chalk.cyan(stats.skipped)}`, + `Retries: ${chalk.yellow(stats.retries)}`, + ]; + this.informer.log(message.join(" ")); + } + _onRunnerEnd(stats) { + this._onBeforeRunnerEnd(stats); + this.informer.end(); + } + _onWarning(info) { + this.informer.warn(info); + } + _onError(error) { + this.informer.error(chalk.red(error)); + } + _onInfo(info) { + this.informer.log(info); + } + _logTestInfo(test, icon) { + this.informer.log(`${icon}${helpers.formatTestInfo(test)}`); + } +}; +//# sourceMappingURL=base.js.map \ No newline at end of file diff --git a/build/src/reporters/base.js.map b/build/src/reporters/base.js.map new file mode 100644 index 000000000..8de44f18b --- /dev/null +++ b/build/src/reporters/base.js.map @@ -0,0 +1 @@ +{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/reporters/base.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/reporters/flat.d.ts b/build/src/reporters/flat.d.ts new file mode 100644 index 000000000..1039905ff --- /dev/null +++ b/build/src/reporters/flat.d.ts @@ -0,0 +1,6 @@ +export = FlatReporter; +declare class FlatReporter extends BaseReporter { + constructor(...args: any[]); + _tests: any[]; +} +import BaseReporter = require("./base"); diff --git a/build/src/reporters/flat.js b/build/src/reporters/flat.js new file mode 100644 index 000000000..2f7f4e9be --- /dev/null +++ b/build/src/reporters/flat.js @@ -0,0 +1,33 @@ +"use strict"; +const _ = require("lodash"); +const BaseReporter = require("./base"); +const helpers = require("./utils/helpers"); +const icons = require("./utils/icons"); +module.exports = class FlatReporter extends BaseReporter { + constructor(...args) { + super(...args); + this._tests = []; + } + _onTestFail(test) { + super._onTestFail(test); + this._tests.push(helpers.extendTestInfo(test, { isFailed: true })); + } + _onRetry(test) { + super._onRetry(test); + this._tests.push(helpers.extendTestInfo(test, { isFailed: false })); + } + _onBeforeRunnerEnd(stats) { + super._onBeforeRunnerEnd(stats); + const failedTests = helpers.formatFailedTests(this._tests); + failedTests.forEach((test, index) => { + this.informer.log(`\n${index + 1}) ${test.fullTitle}`); + this.informer.log(` in file ${test.file}\n`); + _.forEach(test.browsers, testCase => { + const icon = testCase.isFailed ? icons.FAIL : icons.RETRY; + this.informer.log(` ${testCase.browserId}`); + this.informer.log(` ${icon} ${testCase.error}`); + }); + }); + } +}; +//# sourceMappingURL=flat.js.map \ No newline at end of file diff --git a/build/src/reporters/flat.js.map b/build/src/reporters/flat.js.map new file mode 100644 index 000000000..f0b973935 --- /dev/null +++ b/build/src/reporters/flat.js.map @@ -0,0 +1 @@ +{"version":3,"file":"flat.js","sourceRoot":"","sources":["../../../src/reporters/flat.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC5B,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AACvC,MAAM,OAAO,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;AAEvC,MAAM,CAAC,OAAO,GAAG,MAAM,YAAa,SAAQ,YAAY;IACpD,YAAY,GAAG,IAAI;QACf,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;QAEf,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IACrB,CAAC;IAED,WAAW,CAAC,IAAI;QACZ,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAExB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACvE,CAAC;IAED,QAAQ,CAAC,IAAI;QACT,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAErB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,kBAAkB,CAAC,KAAK;QACpB,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAEhC,MAAM,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE3D,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YAChC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;YACvD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;YAE/C,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE;gBAChC,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC;gBAE1D,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;gBAC9C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;YACxD,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/reporters/index.d.ts b/build/src/reporters/index.d.ts new file mode 100644 index 000000000..0b076aecc --- /dev/null +++ b/build/src/reporters/index.d.ts @@ -0,0 +1 @@ +export function initReporters(rawReporters: any, runner: any): Promise; diff --git a/build/src/reporters/index.js b/build/src/reporters/index.js new file mode 100644 index 000000000..d5f68d00d --- /dev/null +++ b/build/src/reporters/index.js @@ -0,0 +1,86 @@ +"use strict"; +exports.initReporters = async (rawReporters, runner) => { + await Promise.all([].concat(rawReporters).map(rawReporter => applyReporter(rawReporter, runner))); +}; +const reporterHandlers = [ + { + isMatched: rawReporter => typeof rawReporter === "string" && isJSON(rawReporter), + initReporter: rawReporter => initReporter(getReporterDefinition(rawReporter, JSON.parse)), + }, + { + isMatched: rawReporter => typeof rawReporter === "string", + initReporter: rawReporter => initReporter({ ...getReporterDefinition(rawReporter), type: rawReporter }), + }, + { + isMatched: rawReporter => typeof rawReporter === "object", + initReporter: rawReporter => initReporter(getReporterDefinition(rawReporter, v => v)), + }, + { + isMatched: rawReporter => typeof rawReporter === "function", + initReporter: rawReporter => { + validateReporter(rawReporter); + return rawReporter.create(getReporterDefinition(rawReporter)); + }, + }, + { + isMatched: () => true, + initReporter: rawReporter => { + throw new TypeError(`Specified reporter must be a string, object or function, but got: "${typeof rawReporter}"`); + }, + }, +]; +async function applyReporter(rawReporter, runner) { + for (const handler of reporterHandlers) { + if (!handler.isMatched(rawReporter)) { + continue; + } + const reporter = await handler.initReporter(rawReporter); + if (typeof reporter.attachRunner !== "function") { + throw new TypeError('Initialized reporter must have an "attachRunner" function for subscribe on test result events'); + } + return reporter.attachRunner(runner); + } +} +function initReporter(reporter) { + let Reporter; + try { + Reporter = require(`./${reporter.type}`); + } + catch (e) { + if (e.code === "MODULE_NOT_FOUND") { + throw new Error(`No such reporter: "${reporter.type}"`); + } + throw e; + } + validateReporter(Reporter); + return Reporter.create(reporter); +} +function getReporterDefinition(rawReporter, parser) { + if (!parser) { + return { type: null, path: null }; + } + const { type, path } = parser(rawReporter); + if (!type) { + const strRawReporter = typeof rawReporter !== "string" ? JSON.stringify(rawReporter) : rawReporter; + throw new Error(`Failed to find required "type" field in reporter definition: "${strRawReporter}"`); + } + return { type, path }; +} +function validateReporter(Reporter) { + if (typeof Reporter !== "function") { + throw new TypeError(`Imported reporter must be a function, but got: "${typeof Reporter}"`); + } + if (typeof Reporter.create !== "function") { + throw new TypeError('Imported reporter must have a "create" function for initialization'); + } +} +function isJSON(str) { + try { + JSON.parse(str); + } + catch (e) { + return false; + } + return true; +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/reporters/index.js.map b/build/src/reporters/index.js.map new file mode 100644 index 000000000..99f507c41 --- /dev/null +++ b/build/src/reporters/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/reporters/index.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/reporters/informers/base.d.ts b/build/src/reporters/informers/base.d.ts new file mode 100644 index 000000000..1f458657b --- /dev/null +++ b/build/src/reporters/informers/base.d.ts @@ -0,0 +1,8 @@ +export = BaseInformer; +declare class BaseInformer { + static create(...args: any[]): import("./base"); + log(): void; + warn(): void; + error(): void; + end(): void; +} diff --git a/build/src/reporters/informers/base.js b/build/src/reporters/informers/base.js new file mode 100644 index 000000000..c538413e4 --- /dev/null +++ b/build/src/reporters/informers/base.js @@ -0,0 +1,19 @@ +"use strict"; +module.exports = class BaseInformer { + static create(...args) { + return new this(...args); + } + log() { + throw new Error("Method must be implemented in child classes"); + } + warn() { + throw new Error("Method must be implemented in child classes"); + } + error() { + throw new Error("Method must be implemented in child classes"); + } + end() { + throw new Error("Method must be implemented in child classes"); + } +}; +//# sourceMappingURL=base.js.map \ No newline at end of file diff --git a/build/src/reporters/informers/base.js.map b/build/src/reporters/informers/base.js.map new file mode 100644 index 000000000..5b2cc6b35 --- /dev/null +++ b/build/src/reporters/informers/base.js.map @@ -0,0 +1 @@ +{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../../src/reporters/informers/base.js"],"names":[],"mappings":";AAAA,MAAM,CAAC,OAAO,GAAG,MAAM,YAAY;IAC/B,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI;QACjB,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,GAAG;QACC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACnE,CAAC;IAED,IAAI;QACA,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACnE,CAAC;IAED,KAAK;QACD,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACnE,CAAC;IAED,GAAG;QACC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACnE,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/reporters/informers/console.d.ts b/build/src/reporters/informers/console.d.ts new file mode 100644 index 000000000..5e751cb7a --- /dev/null +++ b/build/src/reporters/informers/console.d.ts @@ -0,0 +1,8 @@ +export = ConsoleInformer; +declare class ConsoleInformer extends BaseInformer { + log(message: any): void; + warn(message: any): void; + error(message: any): void; + end(message: any): void; +} +import BaseInformer = require("./base"); diff --git a/build/src/reporters/informers/console.js b/build/src/reporters/informers/console.js new file mode 100644 index 000000000..75ae2dc85 --- /dev/null +++ b/build/src/reporters/informers/console.js @@ -0,0 +1,20 @@ +"use strict"; +const BaseInformer = require("./base"); +const logger = require("../../utils/logger"); +module.exports = class ConsoleInformer extends BaseInformer { + log(message) { + logger.log(message); + } + warn(message) { + logger.warn(message); + } + error(message) { + logger.error(message); + } + end(message) { + if (message) { + logger.log(message); + } + } +}; +//# sourceMappingURL=console.js.map \ No newline at end of file diff --git a/build/src/reporters/informers/console.js.map b/build/src/reporters/informers/console.js.map new file mode 100644 index 000000000..c4179b7ed --- /dev/null +++ b/build/src/reporters/informers/console.js.map @@ -0,0 +1 @@ +{"version":3,"file":"console.js","sourceRoot":"","sources":["../../../../src/reporters/informers/console.js"],"names":[],"mappings":";AAAA,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AACvC,MAAM,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAE7C,MAAM,CAAC,OAAO,GAAG,MAAM,eAAgB,SAAQ,YAAY;IACvD,GAAG,CAAC,OAAO;QACP,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;IAED,IAAI,CAAC,OAAO;QACR,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,OAAO;QACT,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;IAED,GAAG,CAAC,OAAO;QACP,IAAI,OAAO,EAAE,CAAC;YACV,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACL,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/reporters/informers/file.d.ts b/build/src/reporters/informers/file.d.ts new file mode 100644 index 000000000..01c0534d5 --- /dev/null +++ b/build/src/reporters/informers/file.d.ts @@ -0,0 +1,14 @@ +/// +export = FileInformer; +declare class FileInformer extends BaseInformer { + constructor(opts: any); + _fileStream: fs.WriteStream; + _reporterType: any; + log(message: any): void; + warn(message: any): void; + error(message: any): void; + end(message: any): void; + _prepareMsg(msg: any): string; +} +import BaseInformer = require("./base"); +import fs = require("fs"); diff --git a/build/src/reporters/informers/file.js b/build/src/reporters/informers/file.js new file mode 100644 index 000000000..6601582fc --- /dev/null +++ b/build/src/reporters/informers/file.js @@ -0,0 +1,34 @@ +"use strict"; +const fs = require("fs"); +const stripAnsi = require("strip-ansi"); +const BaseInformer = require("./base"); +const logger = require("../../utils/logger"); +module.exports = class FileInformer extends BaseInformer { + constructor(opts) { + super(opts); + this._fileStream = fs.createWriteStream(opts.path); + this._reporterType = opts.type; + logger.log(`Information with test results for report: "${opts.type}" will be saved to a file: "${opts.path}"`); + } + log(message) { + this._fileStream.write(`${this._prepareMsg(message)}\n`); + } + warn(message) { + this.log(message); + } + error(message) { + this.log(message); + } + end(message) { + if (message) { + this._fileStream.end(`${this._prepareMsg(message)}\n`); + } + else { + this._fileStream.end(); + } + } + _prepareMsg(msg) { + return typeof msg === "object" ? JSON.stringify(msg) : stripAnsi(msg); + } +}; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/build/src/reporters/informers/file.js.map b/build/src/reporters/informers/file.js.map new file mode 100644 index 000000000..bf4cfd930 --- /dev/null +++ b/build/src/reporters/informers/file.js.map @@ -0,0 +1 @@ +{"version":3,"file":"file.js","sourceRoot":"","sources":["../../../../src/reporters/informers/file.js"],"names":[],"mappings":";AAAA,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AACzB,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;AAExC,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AACvC,MAAM,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAE7C,MAAM,CAAC,OAAO,GAAG,MAAM,YAAa,SAAQ,YAAY;IACpD,YAAY,IAAI;QACZ,KAAK,CAAC,IAAI,CAAC,CAAC;QAEZ,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC;QAE/B,MAAM,CAAC,GAAG,CAAC,8CAA8C,IAAI,CAAC,IAAI,+BAA+B,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;IACnH,CAAC;IAED,GAAG,CAAC,OAAO;QACP,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,CAAC,OAAO;QACR,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,OAAO;QACT,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACtB,CAAC;IAED,GAAG,CAAC,OAAO;QACP,IAAI,OAAO,EAAE,CAAC;YACV,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3D,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC;QAC3B,CAAC;IACL,CAAC;IAED,WAAW,CAAC,GAAG;QACX,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC1E,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/reporters/informers/index.d.ts b/build/src/reporters/informers/index.d.ts new file mode 100644 index 000000000..8dff6303e --- /dev/null +++ b/build/src/reporters/informers/index.d.ts @@ -0,0 +1 @@ +export function initInformer(opts: any): Promise; diff --git a/build/src/reporters/informers/index.js b/build/src/reporters/informers/index.js new file mode 100644 index 000000000..aaa2d3326 --- /dev/null +++ b/build/src/reporters/informers/index.js @@ -0,0 +1,11 @@ +"use strict"; +const path = require("path"); +const fs = require("fs-extra"); +exports.initInformer = async (opts) => { + if (opts.path) { + await fs.ensureDir(path.dirname(opts.path)); + } + const informerType = opts.path ? "file" : "console"; + return require(`./${informerType}`).create(opts); +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/reporters/informers/index.js.map b/build/src/reporters/informers/index.js.map new file mode 100644 index 000000000..1899b767f --- /dev/null +++ b/build/src/reporters/informers/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/reporters/informers/index.js"],"names":[],"mappings":";AAAA,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAC7B,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAE/B,OAAO,CAAC,YAAY,GAAG,KAAK,EAAC,IAAI,EAAC,EAAE;IAChC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAEpD,OAAO,OAAO,CAAC,KAAK,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACrD,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/reporters/jsonl.d.ts b/build/src/reporters/jsonl.d.ts new file mode 100644 index 000000000..00e9db23c --- /dev/null +++ b/build/src/reporters/jsonl.d.ts @@ -0,0 +1,8 @@ +export = JsonlReporter; +declare class JsonlReporter extends BaseReporter { + _onBeforeRunnerEnd(): void; + _onWarning(): void; + _onError(): void; + _onInfo(): void; +} +import BaseReporter = require("./base"); diff --git a/build/src/reporters/jsonl.js b/build/src/reporters/jsonl.js new file mode 100644 index 000000000..ee0a112e2 --- /dev/null +++ b/build/src/reporters/jsonl.js @@ -0,0 +1,32 @@ +"use strict"; +const BaseReporter = require("./base"); +const { extendTestInfo } = require("./utils/helpers"); +const { SUCCESS, FAIL, RETRY, SKIPPED } = require("../constants/test-statuses"); +module.exports = class JsonlReporter extends BaseReporter { + _onTestPass(test) { + const testInfo = extendTestInfo(test, { status: SUCCESS }); + this.informer.log(testInfo); + } + _onTestFail(test) { + this.informer.log(extendTestInfo(test, { status: FAIL })); + } + _onRetry(test) { + this.informer.log(extendTestInfo(test, { status: RETRY })); + } + _onTestPending(test) { + this.informer.log(extendTestInfo(test, { status: SKIPPED })); + } + _onBeforeRunnerEnd() { + // do nothing + } + _onWarning() { + // do nothing + } + _onError() { + // do nothing + } + _onInfo() { + // do nothing + } +}; +//# sourceMappingURL=jsonl.js.map \ No newline at end of file diff --git a/build/src/reporters/jsonl.js.map b/build/src/reporters/jsonl.js.map new file mode 100644 index 000000000..ef61fb5d6 --- /dev/null +++ b/build/src/reporters/jsonl.js.map @@ -0,0 +1 @@ +{"version":3,"file":"jsonl.js","sourceRoot":"","sources":["../../../src/reporters/jsonl.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AACvC,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AACtD,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;AAEhF,MAAM,CAAC,OAAO,GAAG,MAAM,aAAc,SAAQ,YAAY;IACrD,WAAW,CAAC,IAAI;QACZ,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3D,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED,WAAW,CAAC,IAAI;QACZ,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,QAAQ,CAAC,IAAI;QACT,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,cAAc,CAAC,IAAI;QACf,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,kBAAkB;QACd,aAAa;IACjB,CAAC;IAED,UAAU;QACN,aAAa;IACjB,CAAC;IAED,QAAQ;QACJ,aAAa;IACjB,CAAC;IAED,OAAO;QACH,aAAa;IACjB,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/reporters/plain.d.ts b/build/src/reporters/plain.d.ts new file mode 100644 index 000000000..a3b2121fc --- /dev/null +++ b/build/src/reporters/plain.d.ts @@ -0,0 +1,4 @@ +export = PlainReporter; +declare class PlainReporter extends BaseReporter { +} +import BaseReporter = require("./base"); diff --git a/build/src/reporters/plain.js b/build/src/reporters/plain.js new file mode 100644 index 000000000..bc8a6d978 --- /dev/null +++ b/build/src/reporters/plain.js @@ -0,0 +1,16 @@ +"use strict"; +const chalk = require("chalk"); +const BaseReporter = require("./base"); +const icons = require("./utils/icons"); +const helpers = require("./utils/helpers"); +module.exports = class PlainReporter extends BaseReporter { + _logTestInfo(test, icon) { + super._logTestInfo(test, icon); + if (icon === icons.RETRY || icon === icons.FAIL) { + const testInfo = helpers.getTestInfo(test); + this.informer.log(` in file ${testInfo.file}`); + this.informer.log(` ${chalk.red(testInfo.error)}`); + } + } +}; +//# sourceMappingURL=plain.js.map \ No newline at end of file diff --git a/build/src/reporters/plain.js.map b/build/src/reporters/plain.js.map new file mode 100644 index 000000000..746a05173 --- /dev/null +++ b/build/src/reporters/plain.js.map @@ -0,0 +1 @@ +{"version":3,"file":"plain.js","sourceRoot":"","sources":["../../../src/reporters/plain.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAE/B,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AACvC,MAAM,KAAK,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;AACvC,MAAM,OAAO,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAE3C,MAAM,CAAC,OAAO,GAAG,MAAM,aAAc,SAAQ,YAAY;IACrD,YAAY,CAAC,IAAI,EAAE,IAAI;QACnB,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAE/B,IAAI,IAAI,KAAK,KAAK,CAAC,KAAK,IAAI,IAAI,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;YAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAE3C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;YACjD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACzD,CAAC;IACL,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/reporters/utils/helpers.d.ts b/build/src/reporters/utils/helpers.d.ts new file mode 100644 index 000000000..030a56643 --- /dev/null +++ b/build/src/reporters/utils/helpers.d.ts @@ -0,0 +1,12 @@ +export function formatTestInfo(test: any): string; +export function getTestInfo(test: any): { + fullTitle: any; + browserId: any; + file: string | undefined; + sessionId: any; + duration: any; + startTime: any; + meta: any; +}; +export function extendTestInfo(test: any, opts: any): any; +export function formatFailedTests(tests: any): any[]; diff --git a/build/src/reporters/utils/helpers.js b/build/src/reporters/utils/helpers.js new file mode 100644 index 000000000..d2a7ac494 --- /dev/null +++ b/build/src/reporters/utils/helpers.js @@ -0,0 +1,56 @@ +"use strict"; +const path = require("path"); +const chalk = require("chalk"); +const _ = require("lodash"); +const getSkipReason = test => test && (getSkipReason(test.parent) || test.skipReason); +const getFilePath = test => (test && test.file) || (test.parent && getFilePath(test.parent)); +const getRelativeFilePath = file => (file ? path.relative(process.cwd(), file) : undefined); +const getTestError = test => { + let error = test.err ? test.err.stack || test.err.message || test.err : undefined; + if (test.err && test.err.seleniumStack) { + error = error.replace(/$/m, ` (${test.err.seleniumStack.orgStatusMessage})`); + } + return error; +}; +exports.formatTestInfo = test => { + const suiteName = test.fullTitle().replace(test.title, ""); + const sessionId = test.sessionId ? `:${test.sessionId}` : ""; + const reason = test.pending && ` reason: ${chalk.red(getSkipReason(test) || "no comment")}`; + return (` ${suiteName}${chalk.underline(test.title)} [${chalk.yellow(test.browserId)}` + + `${sessionId}] - ${chalk.cyan(test.duration || 0)}ms${reason || ""}`); +}; +exports.getTestInfo = test => { + const file = getFilePath(test); + const testInfo = { + fullTitle: test.fullTitle(), + browserId: test.browserId, + file: getRelativeFilePath(file), + sessionId: test.sessionId, + duration: test.duration, + startTime: test.startTime, + meta: test.meta, + }; + if (test.err) { + testInfo.error = getTestError(test); + } + if (test.pending) { + testInfo.reason = getSkipReason(test); + } + return testInfo; +}; +exports.extendTestInfo = (test, opts) => { + return _.extend(exports.getTestInfo(test), opts); +}; +exports.formatFailedTests = tests => { + const formattedTests = []; + tests.forEach(test => { + const testItem = _.pick(test, ["fullTitle", "file"]); + if (_.find(formattedTests, testItem)) { + return; + } + const browsers = _.filter(tests, testItem); + formattedTests.push(_.extend(testItem, { browsers })); + }); + return formattedTests; +}; +//# sourceMappingURL=helpers.js.map \ No newline at end of file diff --git a/build/src/reporters/utils/helpers.js.map b/build/src/reporters/utils/helpers.js.map new file mode 100644 index 000000000..08f54fdac --- /dev/null +++ b/build/src/reporters/utils/helpers.js.map @@ -0,0 +1 @@ +{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../../src/reporters/utils/helpers.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/reporters/utils/icons.d.ts b/build/src/reporters/utils/icons.d.ts new file mode 100644 index 000000000..b9762d077 --- /dev/null +++ b/build/src/reporters/utils/icons.d.ts @@ -0,0 +1,4 @@ +export let SUCCESS: any; +export let WARN: any; +export let FAIL: any; +export let RETRY: any; diff --git a/build/src/reporters/utils/icons.js b/build/src/reporters/utils/icons.js new file mode 100644 index 000000000..8475e903a --- /dev/null +++ b/build/src/reporters/utils/icons.js @@ -0,0 +1,9 @@ +"use strict"; +const chalk = require("chalk"); +module.exports = { + SUCCESS: chalk.green("\u2713"), + WARN: chalk.bold.yellow("!"), + FAIL: chalk.red("\u2718"), + RETRY: chalk.yellow("⟳"), +}; +//# sourceMappingURL=icons.js.map \ No newline at end of file diff --git a/build/src/reporters/utils/icons.js.map b/build/src/reporters/utils/icons.js.map new file mode 100644 index 000000000..a565bcce3 --- /dev/null +++ b/build/src/reporters/utils/icons.js.map @@ -0,0 +1 @@ +{"version":3,"file":"icons.js","sourceRoot":"","sources":["../../../../src/reporters/utils/icons.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAE/B,MAAM,CAAC,OAAO,GAAG;IACb,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC9B,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;IAC5B,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;CAC3B,CAAC"} \ No newline at end of file diff --git a/build/src/runner/browser-agent.d.ts b/build/src/runner/browser-agent.d.ts new file mode 100644 index 000000000..b6094eb47 --- /dev/null +++ b/build/src/runner/browser-agent.d.ts @@ -0,0 +1,15 @@ +export = BrowserAgent; +declare class BrowserAgent { + static create(opts?: {}): import("./browser-agent"); + constructor({ id, version, pool }: { + id: any; + version: any; + pool: any; + }); + browserId: any; + _version: any; + _pool: any; + _sessions: any[]; + getBrowser(opts?: {}): any; + freeBrowser(browser: any, opts?: {}): any; +} diff --git a/build/src/runner/browser-agent.js b/build/src/runner/browser-agent.js new file mode 100644 index 000000000..d8be7b986 --- /dev/null +++ b/build/src/runner/browser-agent.js @@ -0,0 +1,26 @@ +"use strict"; +module.exports = class BrowserAgent { + static create(opts = {}) { + return new this(opts); + } + constructor({ id, version, pool }) { + this.browserId = id; + this._version = version; + this._pool = pool; + this._sessions = []; + } + async getBrowser(opts = {}) { + const browser = await this._pool.getBrowser(this.browserId, { ...opts, version: this._version }); + if (!this._sessions.includes(browser.sessionId)) { + this._sessions.push(browser.sessionId); + return browser; + } + await this.freeBrowser(browser, { force: true }); + return this.getBrowser(opts); + } + freeBrowser(browser, opts = {}) { + const force = opts.force || browser.state.isBroken; + return this._pool.freeBrowser(browser, { force }); + } +}; +//# sourceMappingURL=browser-agent.js.map \ No newline at end of file diff --git a/build/src/runner/browser-agent.js.map b/build/src/runner/browser-agent.js.map new file mode 100644 index 000000000..95e449033 --- /dev/null +++ b/build/src/runner/browser-agent.js.map @@ -0,0 +1 @@ +{"version":3,"file":"browser-agent.js","sourceRoot":"","sources":["../../../src/runner/browser-agent.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,OAAO,GAAG,MAAM,YAAY;IAC/B,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,EAAE;QACnB,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,YAAY,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QAC7B,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QAEpB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,IAAI,GAAG,EAAE;QACtB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACvC,OAAO,OAAO,CAAC;QACnB,CAAC;QAED,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAEjD,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,WAAW,CAAC,OAAO,EAAE,IAAI,GAAG,EAAE;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC;QAEnD,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACtD,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/runner/browser-runner.d.ts b/build/src/runner/browser-runner.d.ts new file mode 100644 index 000000000..ee3e9f75a --- /dev/null +++ b/build/src/runner/browser-runner.d.ts @@ -0,0 +1,26 @@ +import { Runner } from "./runner"; +import { InterceptedEvent } from "../events"; +import { Config } from "../config"; +import { BrowserPool } from "../browser-pool"; +import { Workers } from "./index"; +import type { Test } from "../types"; +import { TestCollection } from "../test-collection"; +export interface BrowserRunner { + on(event: InterceptedEvent, handler: (test: Test) => void): this; +} +export declare class BrowserRunner extends Runner { + private _browserId; + private config; + private browserPool; + private suiteMonitor; + private activeTestRunners; + private workers; + private running; + constructor(browserId: string, config: Config, browserPool: BrowserPool, workers: Workers); + get browserId(): string; + run(testCollection: TestCollection): Promise; + addTestToRun(test: Test): boolean; + private _runTest; + cancel(): void; + private passthroughEvents; +} diff --git a/build/src/runner/browser-runner.js b/build/src/runner/browser-runner.js new file mode 100644 index 000000000..f7e757929 --- /dev/null +++ b/build/src/runner/browser-runner.js @@ -0,0 +1,97 @@ +"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.BrowserRunner = void 0; +const lodash_1 = __importDefault(require("lodash")); +const runner_1 = require("./runner"); +const TestRunner = __importStar(require("./test-runner")); +const events_1 = require("../events"); +const suite_monitor_1 = __importDefault(require("./suite-monitor")); +const browser_agent_1 = __importDefault(require("./browser-agent")); +const promise_group_1 = __importDefault(require("./promise-group")); +class BrowserRunner extends runner_1.Runner { + constructor(browserId, config, browserPool, workers) { + super(); + this._browserId = browserId; + this.config = config; + this.browserPool = browserPool; + this.suiteMonitor = suite_monitor_1.default.create(); + this.passthroughEvents(this.suiteMonitor, [events_1.MasterEvents.SUITE_BEGIN, events_1.MasterEvents.SUITE_END]); + this.activeTestRunners = new Set(); + this.workers = workers; + this.running = new promise_group_1.default(); + } + get browserId() { + return this._browserId; + } + async run(testCollection) { + testCollection.eachTestByVersions(this._browserId, (test) => { + this.running.add(this._runTest(test)); + }); + await this.running.done(); + } + addTestToRun(test) { + if (this.running.isFulfilled()) { + return false; + } + this.running.add(this._runTest(test)); + return true; + } + async _runTest(test) { + const browserAgent = browser_agent_1.default.create({ + id: this._browserId, + version: test.browserVersion, + pool: this.browserPool, + }); + const runner = TestRunner.create(test, this.config, browserAgent); + runner.on(events_1.MasterEvents.TEST_BEGIN, (test) => this.suiteMonitor.testBegin(test)); + this.passthroughEvents(runner, [ + events_1.MasterEvents.TEST_BEGIN, + events_1.MasterEvents.TEST_END, + events_1.MasterEvents.TEST_PASS, + events_1.MasterEvents.TEST_FAIL, + events_1.MasterEvents.TEST_PENDING, + events_1.MasterEvents.RETRY, + ]); + runner.on(events_1.MasterEvents.TEST_END, (test) => this.suiteMonitor.testEnd(test)); + runner.on(events_1.MasterEvents.RETRY, (test) => this.suiteMonitor.testRetry(test)); + this.activeTestRunners.add(runner); + await runner.run(this.workers); + this.activeTestRunners.delete(runner); + } + cancel() { + this.activeTestRunners.forEach(runner => runner.cancel()); + } + passthroughEvents(runner, events) { + events.forEach(event => { + runner.on(event, (data) => this.emit(event, lodash_1.default.extend(data, { browserId: this._browserId }))); + }); + } +} +exports.BrowserRunner = BrowserRunner; +//# sourceMappingURL=browser-runner.js.map \ No newline at end of file diff --git a/build/src/runner/browser-runner.js.map b/build/src/runner/browser-runner.js.map new file mode 100644 index 000000000..ff91ef587 --- /dev/null +++ b/build/src/runner/browser-runner.js.map @@ -0,0 +1 @@ +{"version":3,"file":"browser-runner.js","sourceRoot":"","sources":["../../../src/runner/browser-runner.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/runner/index.d.ts b/build/src/runner/index.d.ts new file mode 100644 index 000000000..5ec93c20c --- /dev/null +++ b/build/src/runner/index.d.ts @@ -0,0 +1,47 @@ +/// +import * as pool from "../browser-pool"; +import { BrowserRunner } from "./browser-runner"; +import { InterceptedEvent, RunnerSyncEvent, Interceptor, InterceptData } from "../events"; +import { Runner } from "./runner"; +import WorkersRegistry from "../utils/workers-registry"; +import PromiseGroup from "./promise-group"; +import { TestCollection } from "../test-collection"; +import { Config } from "../config"; +import type { runTest } from "../worker"; +import type { Stats as RunnerStats } from "../stats"; +import EventEmitter from "events"; +import { Test } from "../types"; +interface WorkerMethods { + runTest: typeof runTest; +} +export interface Workers extends EventEmitter, WorkerMethods { +} +type MapOfMethods> = { + [K in T[number]]: (...args: Array) => Promise | unknown; +}; +type RegisterWorkers> = EventEmitter & MapOfMethods; +export declare class MainRunner extends Runner { + protected config: Config; + protected interceptors: Interceptor[]; + protected browserPool: pool.BrowserPool | null; + protected activeBrowserRunners: Map; + protected running: PromiseGroup; + protected runned: boolean; + protected cancelled: boolean; + protected workersRegistry: WorkersRegistry; + protected workers: Workers | null; + constructor(config: Config, interceptors: Interceptor[]); + init(): void; + _isRunning(): boolean; + run(testCollection: TestCollection, stats: RunnerStats): Promise; + addTestToRun(test: Test, browserId: string): boolean; + protected _runTests(testCollection: TestCollection): Promise; + protected _runTestsInBrowser(testCollection: TestCollection, browserId: string): Promise; + protected getEventsToPassthrough(): RunnerSyncEvent[]; + protected getEventsToIntercept(): InterceptedEvent[]; + protected interceptEvents(runner: BrowserRunner, events: InterceptedEvent[]): void; + protected applyInterceptors({ event, data }: Partial | undefined, interceptors: Interceptor[]): Partial; + cancel(): void; + registerWorkers>(workerFilepath: string, exportedMethods: T): RegisterWorkers; +} +export {}; diff --git a/build/src/runner/index.js b/build/src/runner/index.js new file mode 100644 index 000000000..3c79c91e9 --- /dev/null +++ b/build/src/runner/index.js @@ -0,0 +1,144 @@ +"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.MainRunner = void 0; +const lodash_1 = __importDefault(require("lodash")); +const eventsUtils = __importStar(require("../events/utils")); +const temp = __importStar(require("../temp")); +const pool = __importStar(require("../browser-pool")); +const browser_runner_1 = require("./browser-runner"); +const events_1 = require("../events"); +const runner_1 = require("./runner"); +const runtime_config_1 = __importDefault(require("../config/runtime-config")); +const workers_registry_1 = __importDefault(require("../utils/workers-registry")); +const promise_group_1 = __importDefault(require("./promise-group")); +const test_collection_1 = require("../test-collection"); +const logger = __importStar(require("../utils/logger")); +class MainRunner extends runner_1.Runner { + constructor(config, interceptors) { + super(); + this.config = config; + this.interceptors = interceptors; + this.browserPool = null; + this.activeBrowserRunners = new Map(); + this.running = new promise_group_1.default(); + this.runned = false; + this.cancelled = false; + this.workersRegistry = workers_registry_1.default.create(this.config); + this.workers = null; + eventsUtils.passthroughEvent(this.workersRegistry, this, [events_1.MasterEvents.NEW_WORKER_PROCESS, events_1.MasterEvents.ERROR]); + temp.init(this.config.system.tempDir); + runtime_config_1.default.getInstance().extend({ tempOpts: temp.serialize() }); + } + init() { + if (this.workers) { + return; + } + this.workersRegistry.init(); + this.workers = this.workersRegistry.register(require.resolve("../worker"), ["runTest"]); + this.browserPool = pool.create(this.config, this); + } + _isRunning() { + return this.runned && !this.workersRegistry.isEnded() && !this.cancelled; + } + async run(testCollection, stats) { + this.runned = true; + try { + await this.emitAndWait(events_1.MasterEvents.RUNNER_START, this); + this.emit(events_1.MasterEvents.BEGIN); + !this.cancelled && (await this._runTests(testCollection)); + } + finally { + this.emit(events_1.MasterEvents.END); + await this.emitAndWait(events_1.MasterEvents.RUNNER_END, stats.getResult()).catch(logger.warn); + await this.workersRegistry.end(); + } + } + addTestToRun(test, browserId) { + if (!this._isRunning() || this.running.isFulfilled()) { + return false; + } + const runner = this.activeBrowserRunners.get(browserId); + if (runner && runner.addTestToRun(test)) { + return true; + } + const collection = test_collection_1.TestCollection.create({ [browserId]: [test] }); + this.running.add(this._runTestsInBrowser(collection, browserId)); + return true; + } + async _runTests(testCollection) { + testCollection.getBrowsers().forEach((browserId) => { + this.running.add(this._runTestsInBrowser(testCollection, browserId)); + }); + return this.running.done(); + } + async _runTestsInBrowser(testCollection, browserId) { + const runner = browser_runner_1.BrowserRunner.create(browserId, this.config, this.browserPool, this.workers); + eventsUtils.passthroughEvent(runner, this, this.getEventsToPassthrough()); + this.interceptEvents(runner, this.getEventsToIntercept()); + this.activeBrowserRunners.set(browserId, runner); + await runner.run(testCollection); + this.activeBrowserRunners.delete(browserId); + } + getEventsToPassthrough() { + return (0, lodash_1.default)(events_1.RunnerSyncEvents).values().difference(this.getEventsToIntercept()).value(); + } + getEventsToIntercept() { + return (0, lodash_1.default)(this.interceptors).map("event").uniq().value(); + } + interceptEvents(runner, events) { + events.forEach((event) => { + runner.on(event, data => { + try { + const toEmit = this.applyInterceptors({ event, data }, this.interceptors); + toEmit && toEmit.event && this.emit(toEmit.event, toEmit.data); + } + catch (e) { + this.emit(events_1.MasterEvents.ERROR, e); + } + }); + }); + } + applyInterceptors({ event, data } = {}, interceptors) { + const interceptor = lodash_1.default.find(interceptors, { event }); + if (!interceptor) { + return { event, data }; + } + return this.applyInterceptors(interceptor.handler({ event, data }) || { event, data }, lodash_1.default.without(interceptors, interceptor)); + } + cancel() { + this.cancelled = true; + this.browserPool?.cancel(); + this.activeBrowserRunners.forEach(runner => runner.cancel()); + } + registerWorkers(workerFilepath, exportedMethods) { + return this.workersRegistry.register(workerFilepath, exportedMethods); + } +} +exports.MainRunner = MainRunner; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/runner/index.js.map b/build/src/runner/index.js.map new file mode 100644 index 000000000..ff05943c7 --- /dev/null +++ b/build/src/runner/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runner/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/runner/promise-group.d.ts b/build/src/runner/promise-group.d.ts new file mode 100644 index 000000000..d5145bc0b --- /dev/null +++ b/build/src/runner/promise-group.d.ts @@ -0,0 +1,11 @@ +export = PromiseGroup; +declare class PromiseGroup { + _count: number; + _fulfilledCount: number; + _promise: Promise; + _resolve: (value: any) => void; + _reject: (reason?: any) => void; + add(promise: any): any; + isFulfilled(): boolean; + done(): Promise; +} diff --git a/build/src/runner/promise-group.js b/build/src/runner/promise-group.js new file mode 100644 index 000000000..13be44659 --- /dev/null +++ b/build/src/runner/promise-group.js @@ -0,0 +1,32 @@ +"use strict"; +module.exports = class PromiseGroup { + constructor() { + this._count = 0; + this._fulfilledCount = 0; + this._promise = new Promise((resolve, reject) => { + this._resolve = resolve; + this._reject = reject; + }); + } + add(promise) { + if (this.isFulfilled()) { + throw new Error("Can not add promise to a fulfilled group"); + } + this._count += 1; + return promise + .then(() => { + this._fulfilledCount += 1; + if (this._count === this._fulfilledCount) { + this._resolve(); + } + }) + .catch(this._reject); + } + isFulfilled() { + return this._count > 0 && this._count === this._fulfilledCount; + } + done() { + return this._count > 0 ? this._promise : Promise.resolve(); + } +}; +//# sourceMappingURL=promise-group.js.map \ No newline at end of file diff --git a/build/src/runner/promise-group.js.map b/build/src/runner/promise-group.js.map new file mode 100644 index 000000000..b2e2d3591 --- /dev/null +++ b/build/src/runner/promise-group.js.map @@ -0,0 +1 @@ +{"version":3,"file":"promise-group.js","sourceRoot":"","sources":["../../../src/runner/promise-group.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,OAAO,GAAG,MAAM,YAAY;IAC/B;QACI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAChB,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC;QAEzB,IAAI,CAAC,QAAQ,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC5C,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;YACxB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QAC1B,CAAC,CAAC,CAAC;IACP,CAAC;IAED,GAAG,CAAC,OAAO;QACP,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;QAEjB,OAAO,OAAO;aACT,IAAI,CAAC,GAAG,EAAE;YACP,IAAI,CAAC,eAAe,IAAI,CAAC,CAAC;YAE1B,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,eAAe,EAAE,CAAC;gBACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpB,CAAC;QACL,CAAC,CAAC;aACD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED,WAAW;QACP,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,eAAe,CAAC;IACnE,CAAC;IAED,IAAI;QACA,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IAC/D,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/runner/runner.d.ts b/build/src/runner/runner.d.ts new file mode 100644 index 000000000..22c42e3d2 --- /dev/null +++ b/build/src/runner/runner.d.ts @@ -0,0 +1,7 @@ +import { Constructor } from "type-fest"; +import { AsyncEmitter } from "../events"; +export declare abstract class Runner extends AsyncEmitter { + static create(this: Constructor, ...args: unknown[]): T; + abstract run(...args: unknown[]): Promise; + abstract cancel(): void; +} diff --git a/build/src/runner/runner.js b/build/src/runner/runner.js new file mode 100644 index 000000000..488803392 --- /dev/null +++ b/build/src/runner/runner.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Runner = void 0; +const events_1 = require("../events"); +class Runner extends events_1.AsyncEmitter { + static create(...args) { + return new this(...args); + } +} +exports.Runner = Runner; +//# sourceMappingURL=runner.js.map \ No newline at end of file diff --git a/build/src/runner/runner.js.map b/build/src/runner/runner.js.map new file mode 100644 index 000000000..48347a8ce --- /dev/null +++ b/build/src/runner/runner.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/runner/runner.ts"],"names":[],"mappings":";;;AACA,sCAAyC;AAEzC,MAAsB,MAAO,SAAQ,qBAAY;IAC7C,MAAM,CAAC,MAAM,CAA0B,GAAG,IAAe;QACrD,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,CAAC;CAKJ;AARD,wBAQC"} \ No newline at end of file diff --git a/build/src/runner/suite-monitor.d.ts b/build/src/runner/suite-monitor.d.ts new file mode 100644 index 000000000..bba2920a7 --- /dev/null +++ b/build/src/runner/suite-monitor.d.ts @@ -0,0 +1,13 @@ +export = SuiteMonitor; +declare class SuiteMonitor extends EventEmitter { + static create(): import("./suite-monitor"); + constructor(); + _suites: Map; + testBegin(test: any): void; + _addTest(suite: any): void; + testEnd(test: any): void; + _rmTest(suite: any): void; + testRetry(test: any): void; + _addRetry(suite: any): void; +} +import { EventEmitter } from "events"; diff --git a/build/src/runner/suite-monitor.js b/build/src/runner/suite-monitor.js new file mode 100644 index 000000000..e3c060ccc --- /dev/null +++ b/build/src/runner/suite-monitor.js @@ -0,0 +1,57 @@ +"use strict"; +const { EventEmitter } = require("events"); +const { MasterEvents } = require("../events"); +module.exports = class SuiteMonitor extends EventEmitter { + static create() { + return new SuiteMonitor(); + } + constructor() { + super(); + this._suites = new Map(); + } + testBegin(test) { + this._addTest(test.parent); + } + _addTest(suite) { + if (suite.root) { + return; + } + this._addTest(suite.parent); + if (!this._suites.has(suite)) { + this.emit(MasterEvents.SUITE_BEGIN, suite); + this._suites.set(suite, { runningTests: 1, retries: 0 }); + } + else { + const suiteInfo = this._suites.get(suite); + ++suiteInfo.runningTests; + if (suiteInfo.retries > 0) { + --suiteInfo.retries; + } + } + } + testEnd(test) { + this._rmTest(test.parent); + } + _rmTest(suite) { + if (suite.root) { + return; + } + const suiteInfo = this._suites.get(suite); + if (--suiteInfo.runningTests === 0 && suiteInfo.retries === 0) { + this._suites.delete(suite); + this.emit(MasterEvents.SUITE_END, suite); + } + this._rmTest(suite.parent); + } + testRetry(test) { + this._addRetry(test.parent); + } + _addRetry(suite) { + if (suite.root) { + return; + } + ++this._suites.get(suite).retries; + this._addRetry(suite.parent); + } +}; +//# sourceMappingURL=suite-monitor.js.map \ No newline at end of file diff --git a/build/src/runner/suite-monitor.js.map b/build/src/runner/suite-monitor.js.map new file mode 100644 index 000000000..1e5ac2a0b --- /dev/null +++ b/build/src/runner/suite-monitor.js.map @@ -0,0 +1 @@ +{"version":3,"file":"suite-monitor.js","sourceRoot":"","sources":["../../../src/runner/suite-monitor.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC3C,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;AAE9C,MAAM,CAAC,OAAO,GAAG,MAAM,YAAa,SAAQ,YAAY;IACpD,MAAM,CAAC,MAAM;QACT,OAAO,IAAI,YAAY,EAAE,CAAC;IAC9B,CAAC;IAED;QACI,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;IAC7B,CAAC;IAED,SAAS,CAAC,IAAI;QACV,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,QAAQ,CAAC,KAAK;QACV,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACb,OAAO;QACX,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAE5B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;YAC3C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;aAAM,CAAC;YACJ,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC1C,EAAE,SAAS,CAAC,YAAY,CAAC;YACzB,IAAI,SAAS,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;gBACxB,EAAE,SAAS,CAAC,OAAO,CAAC;YACxB,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO,CAAC,IAAI;QACR,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO,CAAC,KAAK;QACT,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACb,OAAO;QACX,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,EAAE,SAAS,CAAC,YAAY,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YAC5D,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC7C,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,SAAS,CAAC,IAAI;QACV,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IAED,SAAS,CAAC,KAAK;QACX,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACb,OAAO;QACX,CAAC;QAED,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC;QAElC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/runner/test-runner/high-priority-browser-agent.d.ts b/build/src/runner/test-runner/high-priority-browser-agent.d.ts new file mode 100644 index 000000000..9f3a2467d --- /dev/null +++ b/build/src/runner/test-runner/high-priority-browser-agent.d.ts @@ -0,0 +1,8 @@ +export = HighPriorityBrowserAgent; +declare class HighPriorityBrowserAgent { + static create(...args: any[]): import("./high-priority-browser-agent"); + constructor(browserAgent: any); + _browserAgent: any; + getBrowser(opts?: {}): any; + freeBrowser(...args: any[]): any; +} diff --git a/build/src/runner/test-runner/high-priority-browser-agent.js b/build/src/runner/test-runner/high-priority-browser-agent.js new file mode 100644 index 000000000..11fba9d28 --- /dev/null +++ b/build/src/runner/test-runner/high-priority-browser-agent.js @@ -0,0 +1,16 @@ +"use strict"; +module.exports = class HighPriorityBrowserAgent { + static create(...args) { + return new this(...args); + } + constructor(browserAgent) { + this._browserAgent = browserAgent; + } + getBrowser(opts = {}) { + return this._browserAgent.getBrowser({ ...opts, highPriority: true }); + } + freeBrowser(...args) { + return this._browserAgent.freeBrowser(...args); + } +}; +//# sourceMappingURL=high-priority-browser-agent.js.map \ No newline at end of file diff --git a/build/src/runner/test-runner/high-priority-browser-agent.js.map b/build/src/runner/test-runner/high-priority-browser-agent.js.map new file mode 100644 index 000000000..3f5423aef --- /dev/null +++ b/build/src/runner/test-runner/high-priority-browser-agent.js.map @@ -0,0 +1 @@ +{"version":3,"file":"high-priority-browser-agent.js","sourceRoot":"","sources":["../../../../src/runner/test-runner/high-priority-browser-agent.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,OAAO,GAAG,MAAM,wBAAwB;IAC3C,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI;QACjB,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,YAAY,YAAY;QACpB,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;IACtC,CAAC;IAED,UAAU,CAAC,IAAI,GAAG,EAAE;QAChB,OAAO,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,WAAW,CAAC,GAAG,IAAI;QACf,OAAO,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC;IACnD,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/runner/test-runner/index.d.ts b/build/src/runner/test-runner/index.d.ts new file mode 100644 index 000000000..e616b77a3 --- /dev/null +++ b/build/src/runner/test-runner/index.d.ts @@ -0,0 +1,7 @@ +import SkippedTestRunner from "./skipped-test-runner"; +import InsistantTestRunner from "./insistant-test-runner"; +import { Config } from "../../config"; +import type { Test } from "../../types"; +import type BrowserAgent from "../browser-agent"; +export type TestRunner = SkippedTestRunner | InsistantTestRunner; +export declare const create: (test: Test, config: Config, browserAgent: BrowserAgent) => TestRunner; diff --git a/build/src/runner/test-runner/index.js b/build/src/runner/test-runner/index.js new file mode 100644 index 000000000..37ad1e993 --- /dev/null +++ b/build/src/runner/test-runner/index.js @@ -0,0 +1,15 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.create = void 0; +const skipped_test_runner_1 = __importDefault(require("./skipped-test-runner")); +const insistant_test_runner_1 = __importDefault(require("./insistant-test-runner")); +const create = function (test, config, browserAgent) { + return test.pending || test.disabled + ? skipped_test_runner_1.default.create(test) + : insistant_test_runner_1.default.create(test, config, browserAgent); +}; +exports.create = create; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/runner/test-runner/index.js.map b/build/src/runner/test-runner/index.js.map new file mode 100644 index 000000000..14cd1e46c --- /dev/null +++ b/build/src/runner/test-runner/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/runner/test-runner/index.ts"],"names":[],"mappings":";;;;;;AAAA,gFAAsD;AACtD,oFAA0D;AAOnD,MAAM,MAAM,GAAG,UAAU,IAAU,EAAE,MAAc,EAAE,YAA0B;IAClF,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ;QAChC,CAAC,CAAC,6BAAiB,CAAC,MAAM,CAAC,IAAI,CAAC;QAChC,CAAC,CAAC,+BAAmB,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;AACjE,CAAC,CAAC;AAJW,QAAA,MAAM,UAIjB"} \ No newline at end of file diff --git a/build/src/runner/test-runner/insistant-test-runner.d.ts b/build/src/runner/test-runner/insistant-test-runner.d.ts new file mode 100644 index 000000000..34c2039c3 --- /dev/null +++ b/build/src/runner/test-runner/insistant-test-runner.d.ts @@ -0,0 +1,14 @@ +export = InsistantTestRunner; +declare class InsistantTestRunner extends Runner { + constructor(test: any, config: any, browserAgent: any); + _test: any; + _config: any; + _browserConfig: any; + _browserAgent: any; + _retriesPerformed: number; + _cancelled: boolean; + run(workers: any): Promise; + _shouldRetry(test: any): boolean; + get _retriesLeft(): number; +} +import { Runner } from "../runner"; diff --git a/build/src/runner/test-runner/insistant-test-runner.js b/build/src/runner/test-runner/insistant-test-runner.js new file mode 100644 index 000000000..0bb35d19e --- /dev/null +++ b/build/src/runner/test-runner/insistant-test-runner.js @@ -0,0 +1,62 @@ +"use strict"; +const _ = require("lodash"); +const { Runner } = require("../runner"); +const RegularTestRunner = require("./regular-test-runner"); +const HighPriorityBrowserAgent = require("./high-priority-browser-agent"); +const { MasterEvents } = require("../../events"); +const { passthroughEvent } = require("../../events/utils"); +const { NoRefImageError } = require("../../browser/commands/assert-view/errors/no-ref-image-error"); +module.exports = class InsistantTestRunner extends Runner { + constructor(test, config, browserAgent) { + super(); + this._test = test; + this._config = config; + this._browserConfig = config.forBrowser(browserAgent.browserId); + this._browserAgent = browserAgent; + this._retriesPerformed = 0; + this._cancelled = false; + } + async run(workers) { + let retry = false; + const browserAgent = this._retriesPerformed > 0 ? HighPriorityBrowserAgent.create(this._browserAgent) : this._browserAgent; + const runner = RegularTestRunner.create(this._test, browserAgent).on(MasterEvents.TEST_FAIL, data => { + if (this._shouldRetry(data)) { + this.emit(MasterEvents.RETRY, _.extend(data, { retriesLeft: this._retriesLeft })); + retry = true; + } + else { + this.emit(MasterEvents.TEST_FAIL, data); + } + }); + passthroughEvent(runner, this, [MasterEvents.TEST_BEGIN, MasterEvents.TEST_PASS, MasterEvents.TEST_END]); + await runner.run(workers); + if (retry) { + ++this._retriesPerformed; + await this.run(workers); + } + } + _shouldRetry(test) { + if (this._cancelled) { + return false; + } + if (typeof this._browserConfig.shouldRetry === "function") { + return Boolean(this._browserConfig.shouldRetry({ + ctx: test, + retriesLeft: this._retriesLeft, + })); + } + // TODO: replace with `instanceof AssertViewError` check + // when errors will be correctly restored after transfer from workers + if (test.err.name === "AssertViewError" && test.assertViewResults.some(e => e instanceof NoRefImageError)) { + return false; + } + return this._retriesLeft > 0; + } + get _retriesLeft() { + return this._browserConfig.retry - this._retriesPerformed; + } + cancel() { + this._cancelled = true; + } +}; +//# sourceMappingURL=insistant-test-runner.js.map \ No newline at end of file diff --git a/build/src/runner/test-runner/insistant-test-runner.js.map b/build/src/runner/test-runner/insistant-test-runner.js.map new file mode 100644 index 000000000..d39f8d77b --- /dev/null +++ b/build/src/runner/test-runner/insistant-test-runner.js.map @@ -0,0 +1 @@ +{"version":3,"file":"insistant-test-runner.js","sourceRoot":"","sources":["../../../../src/runner/test-runner/insistant-test-runner.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/runner/test-runner/regular-test-runner.d.ts b/build/src/runner/test-runner/regular-test-runner.d.ts new file mode 100644 index 000000000..74322767b --- /dev/null +++ b/build/src/runner/test-runner/regular-test-runner.d.ts @@ -0,0 +1,18 @@ +export = RegularTestRunner; +declare class RegularTestRunner extends Runner { + constructor(test: any, browserAgent: any); + _test: any; + _browserAgent: any; + _browser: any; + run(workers: any): Promise; + _emit(event: any): void; + _runTest(workers: any): Promise; + _applyTestResults({ meta, hermioneCtx, history }: { + meta: any; + hermioneCtx?: {} | undefined; + history?: any[] | undefined; + }): void; + _getBrowser(): Promise; + _freeBrowser(browserState?: {}): Promise; +} +import { Runner } from "../runner"; diff --git a/build/src/runner/test-runner/regular-test-runner.js b/build/src/runner/test-runner/regular-test-runner.js new file mode 100644 index 000000000..77022b843 --- /dev/null +++ b/build/src/runner/test-runner/regular-test-runner.js @@ -0,0 +1,88 @@ +"use strict"; +const crypto = require("crypto"); +const _ = require("lodash"); +const { Runner } = require("../runner"); +const logger = require("../../utils/logger"); +const { MasterEvents } = require("../../events"); +const AssertViewResults = require("../../browser/commands/assert-view/assert-view-results"); +module.exports = class RegularTestRunner extends Runner { + constructor(test, browserAgent) { + super(); + this._test = test.clone(); + this._browserAgent = browserAgent; + this._browser = null; + } + async run(workers) { + let freeBrowserPromise; + try { + const browser = await this._getBrowser(); + if (browser) { + workers.once(`worker.${browser.sessionId}.freeBrowser`, browserState => { + freeBrowserPromise = this._freeBrowser(browserState); + }); + } + this._emit(MasterEvents.TEST_BEGIN); + this._test.startTime = Date.now(); + const results = await this._runTest(workers); + this._applyTestResults(results); + this._emit(MasterEvents.TEST_PASS); + } + catch (error) { + this._test.err = error; + this._applyTestResults(error); + this._emit(MasterEvents.TEST_FAIL); + } + this._emit(MasterEvents.TEST_END); + await (freeBrowserPromise || this._freeBrowser()); + } + _emit(event) { + this.emit(event, this._test); + } + async _runTest(workers) { + if (!this._browser) { + throw this._test.err; + } + return await workers.runTest(this._test.fullTitle(), { + browserId: this._browser.id, + browserVersion: this._browser.version, + sessionId: this._browser.sessionId, + sessionCaps: this._browser.capabilities, + sessionOpts: this._browser.publicAPI.options, + file: this._test.file, + testXReqId: this._browser.testXReqId, + }); + } + _applyTestResults({ meta, hermioneCtx = {}, history = [] }) { + hermioneCtx.assertViewResults = AssertViewResults.fromRawObject(hermioneCtx.assertViewResults || []); + this._test.assertViewResults = hermioneCtx.assertViewResults.get(); + this._test.meta = _.extend(this._test.meta, meta); + this._test.hermioneCtx = hermioneCtx; + this._test.history = history; + this._test.duration = Date.now() - this._test.startTime; + } + async _getBrowser() { + try { + this._browser = await this._browserAgent.getBrowser({ testXReqId: crypto.randomUUID() }); + this._test.sessionId = this._browser.sessionId; + return this._browser; + } + catch (error) { + this._test.err = error; + } + } + async _freeBrowser(browserState = {}) { + if (!this._browser) { + return; + } + const browser = this._browser; + this._browser = null; + browser.applyState(browserState); + try { + await this._browserAgent.freeBrowser(browser); + } + catch (error) { + logger.warn(`WARNING: can not release browser: ${error}`); + } + } +}; +//# sourceMappingURL=regular-test-runner.js.map \ No newline at end of file diff --git a/build/src/runner/test-runner/regular-test-runner.js.map b/build/src/runner/test-runner/regular-test-runner.js.map new file mode 100644 index 000000000..7d3644700 --- /dev/null +++ b/build/src/runner/test-runner/regular-test-runner.js.map @@ -0,0 +1 @@ +{"version":3,"file":"regular-test-runner.js","sourceRoot":"","sources":["../../../../src/runner/test-runner/regular-test-runner.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/runner/test-runner/skipped-test-runner.d.ts b/build/src/runner/test-runner/skipped-test-runner.d.ts new file mode 100644 index 000000000..afdd633b0 --- /dev/null +++ b/build/src/runner/test-runner/skipped-test-runner.d.ts @@ -0,0 +1,11 @@ +export = SkippedTestRunner; +declare class SkippedTestRunner extends Runner { + constructor(test: any); + _test: any; + run(): void; + _isSilentlySkipped({ silentSkip, parent }: { + silentSkip: any; + parent: any; + }): any; +} +import { Runner } from "../runner"; diff --git a/build/src/runner/test-runner/skipped-test-runner.js b/build/src/runner/test-runner/skipped-test-runner.js new file mode 100644 index 000000000..06e9eef51 --- /dev/null +++ b/build/src/runner/test-runner/skipped-test-runner.js @@ -0,0 +1,21 @@ +"use strict"; +const { Runner } = require("../runner"); +const { MasterEvents } = require("../../events"); +module.exports = class SkippedTestRunner extends Runner { + constructor(test) { + super(); + this._test = test.clone(); + } + run() { + if (this._test.disabled || this._isSilentlySkipped(this._test)) { + return; + } + this.emit(MasterEvents.TEST_BEGIN, this._test); + this.emit(MasterEvents.TEST_PENDING, this._test); + this.emit(MasterEvents.TEST_END, this._test); + } + _isSilentlySkipped({ silentSkip, parent }) { + return silentSkip || (parent && this._isSilentlySkipped(parent)); + } +}; +//# sourceMappingURL=skipped-test-runner.js.map \ No newline at end of file diff --git a/build/src/runner/test-runner/skipped-test-runner.js.map b/build/src/runner/test-runner/skipped-test-runner.js.map new file mode 100644 index 000000000..4c8604350 --- /dev/null +++ b/build/src/runner/test-runner/skipped-test-runner.js.map @@ -0,0 +1 @@ +{"version":3,"file":"skipped-test-runner.js","sourceRoot":"","sources":["../../../../src/runner/test-runner/skipped-test-runner.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;AACxC,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAEjD,MAAM,CAAC,OAAO,GAAG,MAAM,iBAAkB,SAAQ,MAAM;IACnD,YAAY,IAAI;QACZ,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;IAC9B,CAAC;IAED,GAAG;QACC,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7D,OAAO;QACX,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC;IAED,kBAAkB,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE;QACrC,OAAO,UAAU,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;IACrE,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/signal-handler.d.ts b/build/src/signal-handler.d.ts new file mode 100644 index 000000000..fc200f4fc --- /dev/null +++ b/build/src/signal-handler.d.ts @@ -0,0 +1,3 @@ +export = signalHandler; +declare const signalHandler: AsyncEmitter; +import { AsyncEmitter } from "./events/async-emitter"; diff --git a/build/src/signal-handler.js b/build/src/signal-handler.js new file mode 100644 index 000000000..0e5239c00 --- /dev/null +++ b/build/src/signal-handler.js @@ -0,0 +1,23 @@ +"use strict"; +const { AsyncEmitter } = require("./events/async-emitter"); +const { log } = require("./utils/logger"); +const signalHandler = new AsyncEmitter(); +signalHandler.setMaxListeners(0); +module.exports = signalHandler; +process.on("SIGHUP", notifyAndExit(1)); +process.on("SIGINT", notifyAndExit(2)); +process.on("SIGTERM", notifyAndExit(15)); +let callCount = 0; +function notifyAndExit(signalNo) { + const exitCode = 128 + signalNo; + return function () { + if (callCount++ > 0) { + log("Force quit."); + process.exit(exitCode); + } + signalHandler.emitAndWait("exit").then(function () { + process.exit(exitCode); + }); + }; +} +//# sourceMappingURL=signal-handler.js.map \ No newline at end of file diff --git a/build/src/signal-handler.js.map b/build/src/signal-handler.js.map new file mode 100644 index 000000000..4d1b36ae3 --- /dev/null +++ b/build/src/signal-handler.js.map @@ -0,0 +1 @@ +{"version":3,"file":"signal-handler.js","sourceRoot":"","sources":["../../src/signal-handler.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;AAC3D,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAC1C,MAAM,aAAa,GAAG,IAAI,YAAY,EAAE,CAAC;AAEzC,aAAa,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AAEjC,MAAM,CAAC,OAAO,GAAG,aAAa,CAAC;AAE/B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACvC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACvC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC;AAEzC,IAAI,SAAS,GAAG,CAAC,CAAC;AAElB,SAAS,aAAa,CAAC,QAAQ;IAC3B,MAAM,QAAQ,GAAG,GAAG,GAAG,QAAQ,CAAC;IAEhC,OAAO;QACH,IAAI,SAAS,EAAE,GAAG,CAAC,EAAE,CAAC;YAClB,GAAG,CAAC,aAAa,CAAC,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;QAED,aAAa,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;YACnC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;AACN,CAAC"} \ No newline at end of file diff --git a/build/src/stats.d.ts b/build/src/stats.d.ts new file mode 100644 index 000000000..55b4703bc --- /dev/null +++ b/build/src/stats.d.ts @@ -0,0 +1,15 @@ +import { Hermione } from "./hermione"; +export interface StatsResult { + total: number; + passed: number; + failed: number; + retries: number; + skipped: number; + perBrowser: Record>; +} +export declare class Stats { + private events; + static create(this: new (runner?: Hermione) => T, runner?: Hermione): T; + constructor(runner?: Hermione); + getResult(): StatsResult; +} diff --git a/build/src/stats.js b/build/src/stats.js new file mode 100644 index 000000000..1f5a5cd17 --- /dev/null +++ b/build/src/stats.js @@ -0,0 +1,44 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Stats = void 0; +const lodash_1 = __importDefault(require("lodash")); +const events_1 = require("./events"); +class Stats { + static create(runner) { + return new this(runner); + } + constructor(runner) { + this.events = []; + const pushEvent_ = (group) => ({ id, browserId }) => { + this.events.push({ group, id, browserId }); + }; + if (runner) { + runner + .on(events_1.MasterEvents.TEST_PASS, pushEvent_("passed")) + .on(events_1.MasterEvents.TEST_FAIL, pushEvent_("failed")) + .on(events_1.MasterEvents.RETRY, pushEvent_("retries")) + .on(events_1.MasterEvents.TEST_PENDING, pushEvent_("skipped")); + } + } + getResult() { + const emptyStat = { passed: 0, failed: 0, retries: 0, skipped: 0, total: 0 }; + const statsByBrowser = (0, lodash_1.default)(this.events) + .groupBy("browserId") + .mapValues(events => { + const stats = (0, lodash_1.default)(events).groupBy("group").mapValues("length").value(); + return { + ...emptyStat, + ...stats, + total: lodash_1.default.uniqBy(events, "id").length, + }; + }) + .value(); + const overall = lodash_1.default.mergeWith(emptyStat, ...Object.values(statsByBrowser), (a, b) => a + b); + return { ...overall, perBrowser: statsByBrowser }; + } +} +exports.Stats = Stats; +//# sourceMappingURL=stats.js.map \ No newline at end of file diff --git a/build/src/stats.js.map b/build/src/stats.js.map new file mode 100644 index 000000000..78656def2 --- /dev/null +++ b/build/src/stats.js.map @@ -0,0 +1 @@ +{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/stats.ts"],"names":[],"mappings":";;;;;;AAAA,oDAAuB;AACvB,qCAAwC;AAsBxC,MAAa,KAAK;IAGd,MAAM,CAAC,MAAM,CAAsD,MAAiB;QAChF,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED,YAAY,MAAiB;QANrB,WAAM,GAAgB,EAAE,CAAC;QAO7B,MAAM,UAAU,GACZ,CAAC,KAAgB,EAAE,EAAE,CACrB,CAAC,EAAE,EAAE,EAAE,SAAS,EAAQ,EAAQ,EAAE;YAC9B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/C,CAAC,CAAC;QAEN,IAAI,MAAM,EAAE,CAAC;YACT,MAAM;iBACD,EAAE,CAAC,qBAAY,CAAC,SAAS,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;iBAChD,EAAE,CAAC,qBAAY,CAAC,SAAS,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;iBAChD,EAAE,CAAC,qBAAY,CAAC,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;iBAC7C,EAAE,CAAC,qBAAY,CAAC,YAAY,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;QAC9D,CAAC;IACL,CAAC;IAED,SAAS;QACL,MAAM,SAAS,GAAyB,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QACnG,MAAM,cAAc,GAAG,IAAA,gBAAC,EAAC,IAAI,CAAC,MAAM,CAAC;aAChC,OAAO,CAAC,WAAW,CAAC;aACpB,SAAS,CAAC,MAAM,CAAC,EAAE;YAChB,MAAM,KAAK,GAAG,IAAA,gBAAC,EAAC,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;YAErE,OAAO;gBACH,GAAG,SAAS;gBACZ,GAAG,KAAK;gBACR,KAAK,EAAE,gBAAC,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM;aACvC,CAAC;QACN,CAAC,CAAC;aACD,KAAK,EAAE,CAAC;QAEb,MAAM,OAAO,GAAG,gBAAC,CAAC,SAAS,CAAC,SAAS,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAE1G,OAAO,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC;IACtD,CAAC;CACJ;AA1CD,sBA0CC"} \ No newline at end of file diff --git a/build/src/temp.d.ts b/build/src/temp.d.ts new file mode 100644 index 000000000..071e92d1c --- /dev/null +++ b/build/src/temp.d.ts @@ -0,0 +1,4 @@ +export function init(dir: any): void; +export function attach(serializedTemp: any): void; +export function path(opts: any): any; +export function serialize(): any; diff --git a/build/src/temp.js b/build/src/temp.js new file mode 100644 index 000000000..0aaa24dc1 --- /dev/null +++ b/build/src/temp.js @@ -0,0 +1,39 @@ +"use strict"; +const temp = require("temp"); +const path = require("path"); +const _ = require("lodash"); +temp.track(); +class Temp { + constructor(dir, opts = {}) { + this._tempDir = opts.attach + ? dir + : temp.mkdirSync({ + dir: dir && path.resolve(dir), + prefix: ".screenshots.tmp.", + }); + } + path(opts = {}) { + return temp.path(_.extend(opts, { + dir: this._tempDir, + })); + } + serialize() { + return { dir: this._tempDir }; + } +} +let tempInstance; +module.exports = { + init: dir => { + if (!tempInstance) { + tempInstance = new Temp(dir); + } + }, + attach: serializedTemp => { + if (!tempInstance) { + tempInstance = new Temp(serializedTemp.dir, { attach: true }); + } + }, + path: opts => tempInstance.path(opts), + serialize: () => tempInstance.serialize(), +}; +//# sourceMappingURL=temp.js.map \ No newline at end of file diff --git a/build/src/temp.js.map b/build/src/temp.js.map new file mode 100644 index 000000000..72ed6dfb2 --- /dev/null +++ b/build/src/temp.js.map @@ -0,0 +1 @@ +{"version":3,"file":"temp.js","sourceRoot":"","sources":["../../src/temp.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAC7B,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAC7B,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE5B,IAAI,CAAC,KAAK,EAAE,CAAC;AAEb,MAAM,IAAI;IACN,YAAY,GAAG,EAAE,IAAI,GAAG,EAAE;QACtB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM;YACvB,CAAC,CAAC,GAAG;YACL,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;gBACX,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;gBAC7B,MAAM,EAAE,mBAAmB;aAC9B,CAAC,CAAC;IACb,CAAC;IAED,IAAI,CAAC,IAAI,GAAG,EAAE;QACV,OAAO,IAAI,CAAC,IAAI,CACZ,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE;YACX,GAAG,EAAE,IAAI,CAAC,QAAQ;SACrB,CAAC,CACL,CAAC;IACN,CAAC;IAED,SAAS;QACL,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;IAClC,CAAC;CACJ;AAED,IAAI,YAAY,CAAC;AACjB,MAAM,CAAC,OAAO,GAAG;IACb,IAAI,EAAE,GAAG,CAAC,EAAE;QACR,IAAI,CAAC,YAAY,EAAE,CAAC;YAChB,YAAY,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QACjC,CAAC;IACL,CAAC;IAED,MAAM,EAAE,cAAc,CAAC,EAAE;QACrB,IAAI,CAAC,YAAY,EAAE,CAAC;YAChB,YAAY,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,CAAC;IACL,CAAC;IAED,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;IACrC,SAAS,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE;CAC5C,CAAC"} \ No newline at end of file diff --git a/build/src/test-collection.d.ts b/build/src/test-collection.d.ts new file mode 100644 index 000000000..71a078921 --- /dev/null +++ b/build/src/test-collection.d.ts @@ -0,0 +1,23 @@ +import type { RootSuite, Test } from "./types"; +type TestsCallback = (test: Test, browserId: string) => T; +type SortTestsCallback = (test1: Test, test2: Test) => number; +export declare class TestCollection { + #private; + static create(this: new (specs: Record) => T, specs: Record): T; + constructor(specs: Record); + getRootSuite(browserId: string): RootSuite; + eachRootSuite(cb: (root: RootSuite, browserId: string) => void): void; + getBrowsers(): string[]; + mapTests(cb: TestsCallback): T[]; + mapTests(browserId: string | undefined, cb: TestsCallback): T[]; + sortTests(callback: SortTestsCallback): this; + sortTests(browserId: string | undefined, callback: SortTestsCallback): this; + eachTest(callback: TestsCallback): void; + eachTest(browserId: string | undefined, callback: TestsCallback): void; + eachTestByVersions(browserId: string, cb: (test: Test, browserId: string, browserVersion: string) => void): void; + disableAll(browserId?: string): this; + disableTest(fullTitle: string, browserId?: string): this; + enableAll(browserId?: string): this; + enableTest(fullTitle: string, browserId?: string): this; +} +export {}; diff --git a/build/src/test-collection.js b/build/src/test-collection.js new file mode 100644 index 000000000..a6b522cbc --- /dev/null +++ b/build/src/test-collection.js @@ -0,0 +1,151 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _TestCollection_instances, _TestCollection_specs, _TestCollection_originalSpecs, _TestCollection_getRoot, _TestCollection_mkDisabledTest, _TestCollection_findTestIndex; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TestCollection = void 0; +const lodash_1 = __importDefault(require("lodash")); +class TestCollection { + static create(specs) { + return new this(specs); + } + constructor(specs) { + _TestCollection_instances.add(this); + _TestCollection_specs.set(this, void 0); + _TestCollection_originalSpecs.set(this, void 0); + __classPrivateFieldSet(this, _TestCollection_originalSpecs, specs, "f"); + __classPrivateFieldSet(this, _TestCollection_specs, lodash_1.default.mapValues(specs, lodash_1.default.clone), "f"); + } + getRootSuite(browserId) { + const test = __classPrivateFieldGet(this, _TestCollection_originalSpecs, "f")[browserId][0]; + return test && test.parent && __classPrivateFieldGet(this, _TestCollection_instances, "m", _TestCollection_getRoot).call(this, test.parent); + } + eachRootSuite(cb) { + lodash_1.default.forEach(__classPrivateFieldGet(this, _TestCollection_specs, "f"), (_, browserId) => { + const root = this.getRootSuite(browserId); + if (root) { + cb(root, browserId); + } + }); + } + getBrowsers() { + return Object.keys(__classPrivateFieldGet(this, _TestCollection_specs, "f")); + } + mapTests(browserId, cb) { + if (lodash_1.default.isFunction(browserId)) { + cb = browserId; + browserId = undefined; + } + const results = []; + this.eachTest(browserId, (test, browserId) => results.push(cb(test, browserId))); + return results; + } + sortTests(browserId, cb) { + if (lodash_1.default.isFunction(browserId)) { + cb = browserId; + browserId = undefined; + } + if (browserId) { + if (__classPrivateFieldGet(this, _TestCollection_specs, "f")[browserId]?.length && __classPrivateFieldGet(this, _TestCollection_originalSpecs, "f")[browserId]?.length) { + const pairs = lodash_1.default.zip(__classPrivateFieldGet(this, _TestCollection_specs, "f")[browserId], __classPrivateFieldGet(this, _TestCollection_originalSpecs, "f")[browserId]); + pairs.sort((p1, p2) => cb(p1[0], p2[0])); + [__classPrivateFieldGet(this, _TestCollection_specs, "f")[browserId], __classPrivateFieldGet(this, _TestCollection_originalSpecs, "f")[browserId]] = lodash_1.default.unzip(pairs); + } + } + else { + this.getBrowsers().forEach(browserId => this.sortTests(browserId, cb)); + } + return this; + } + eachTest(browserId, cb) { + if (lodash_1.default.isFunction(browserId)) { + cb = browserId; + browserId = undefined; + } + if (browserId) { + __classPrivateFieldGet(this, _TestCollection_specs, "f")[browserId].forEach(test => cb(test, browserId)); + } + else { + this.getBrowsers().forEach(browserId => this.eachTest(browserId, cb)); + } + } + eachTestByVersions(browserId, cb) { + const groups = lodash_1.default.groupBy(__classPrivateFieldGet(this, _TestCollection_specs, "f")[browserId], "browserVersion"); + const versions = Object.keys(groups); + const maxLength = (0, lodash_1.default)(groups) + .map(tests => tests.length) + .max() || 0; + for (let idx = 0; idx < maxLength; ++idx) { + for (const version of versions) { + const group = groups[version]; + const test = group[idx]; + if (test) { + cb(test, browserId, test.browserVersion); + } + } + } + } + disableAll(browserId) { + if (browserId) { + __classPrivateFieldGet(this, _TestCollection_specs, "f")[browserId] = __classPrivateFieldGet(this, _TestCollection_originalSpecs, "f")[browserId].map(test => __classPrivateFieldGet(this, _TestCollection_instances, "m", _TestCollection_mkDisabledTest).call(this, test)); + } + else { + this.getBrowsers().forEach(browserId => this.disableAll(browserId)); + } + return this; + } + disableTest(fullTitle, browserId) { + if (browserId) { + const idx = __classPrivateFieldGet(this, _TestCollection_instances, "m", _TestCollection_findTestIndex).call(this, fullTitle, browserId); + if (idx !== -1) { + __classPrivateFieldGet(this, _TestCollection_specs, "f")[browserId].splice(idx, 1, __classPrivateFieldGet(this, _TestCollection_instances, "m", _TestCollection_mkDisabledTest).call(this, __classPrivateFieldGet(this, _TestCollection_originalSpecs, "f")[browserId][idx])); + } + } + else { + this.getBrowsers().forEach(browserId => this.disableTest(fullTitle, browserId)); + } + return this; + } + enableAll(browserId) { + if (browserId) { + __classPrivateFieldGet(this, _TestCollection_specs, "f")[browserId] = lodash_1.default.clone(__classPrivateFieldGet(this, _TestCollection_originalSpecs, "f")[browserId]); + } + else { + this.getBrowsers().forEach(browserId => this.enableAll(browserId)); + } + return this; + } + enableTest(fullTitle, browserId) { + if (browserId) { + const idx = __classPrivateFieldGet(this, _TestCollection_instances, "m", _TestCollection_findTestIndex).call(this, fullTitle, browserId); + if (idx !== -1) { + __classPrivateFieldGet(this, _TestCollection_specs, "f")[browserId].splice(idx, 1, __classPrivateFieldGet(this, _TestCollection_originalSpecs, "f")[browserId][idx]); + } + } + else { + this.getBrowsers().forEach(browserId => this.enableTest(fullTitle, browserId)); + } + return this; + } +} +exports.TestCollection = TestCollection; +_TestCollection_specs = new WeakMap(), _TestCollection_originalSpecs = new WeakMap(), _TestCollection_instances = new WeakSet(), _TestCollection_getRoot = function _TestCollection_getRoot(suite) { + return suite.root ? suite : __classPrivateFieldGet(this, _TestCollection_instances, "m", _TestCollection_getRoot).call(this, suite.parent); +}, _TestCollection_mkDisabledTest = function _TestCollection_mkDisabledTest(test) { + return lodash_1.default.extend(test.clone(), { disabled: true }); +}, _TestCollection_findTestIndex = function _TestCollection_findTestIndex(fullTitle, browserId) { + return __classPrivateFieldGet(this, _TestCollection_specs, "f")[browserId].findIndex(test => test.fullTitle() === fullTitle); +}; +//# sourceMappingURL=test-collection.js.map \ No newline at end of file diff --git a/build/src/test-collection.js.map b/build/src/test-collection.js.map new file mode 100644 index 000000000..e28a9a29e --- /dev/null +++ b/build/src/test-collection.js.map @@ -0,0 +1 @@ +{"version":3,"file":"test-collection.js","sourceRoot":"","sources":["../../src/test-collection.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/test-reader/build-instructions.d.ts b/build/src/test-reader/build-instructions.d.ts new file mode 100644 index 000000000..f51cc1cae --- /dev/null +++ b/build/src/test-reader/build-instructions.d.ts @@ -0,0 +1,28 @@ +export class InstructionsList { + push(fn: any, file: any): this; + exec(files: any, ctx?: {}): void; + #private; +} +declare function extendWithBrowserId({ treeBuilder, browserId }: { + treeBuilder: any; + browserId: any; +}): void; +declare function extendWithBrowserVersion({ treeBuilder, config }: { + treeBuilder: any; + config: any; +}): void; +declare function extendWithTimeout({ treeBuilder, config }: { + treeBuilder: any; + config: any; +}): void; +declare function buildGlobalSkipInstruction(config: any): ({ treeBuilder, browserId }: { + treeBuilder: any; + browserId: any; +}) => void; +export declare namespace Instructions { + export { extendWithBrowserId }; + export { extendWithBrowserVersion }; + export { extendWithTimeout }; + export { buildGlobalSkipInstruction }; +} +export {}; diff --git a/build/src/test-reader/build-instructions.js b/build/src/test-reader/build-instructions.js new file mode 100644 index 000000000..369a16bbd --- /dev/null +++ b/build/src/test-reader/build-instructions.js @@ -0,0 +1,82 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _InstructionsList_commonInstructions, _InstructionsList_fileInstructions; +const _ = require("lodash"); +const validators = require("../validators"); +const env = require("../utils/env"); +class InstructionsList { + constructor() { + _InstructionsList_commonInstructions.set(this, void 0); + _InstructionsList_fileInstructions.set(this, void 0); + __classPrivateFieldSet(this, _InstructionsList_commonInstructions, [], "f"); + __classPrivateFieldSet(this, _InstructionsList_fileInstructions, new Map(), "f"); + } + push(fn, file) { + const instructions = file ? __classPrivateFieldGet(this, _InstructionsList_fileInstructions, "f").get(file) || [] : __classPrivateFieldGet(this, _InstructionsList_commonInstructions, "f"); + instructions.push(fn); + if (file && !__classPrivateFieldGet(this, _InstructionsList_fileInstructions, "f").has(file)) { + __classPrivateFieldGet(this, _InstructionsList_fileInstructions, "f").set(file, instructions); + } + return this; + } + exec(files, ctx = {}) { + __classPrivateFieldGet(this, _InstructionsList_commonInstructions, "f").forEach(fn => fn(ctx)); + files.forEach(file => { + const instructions = __classPrivateFieldGet(this, _InstructionsList_fileInstructions, "f").get(file) || []; + instructions.forEach(fn => fn(ctx)); + }); + } +} +_InstructionsList_commonInstructions = new WeakMap(), _InstructionsList_fileInstructions = new WeakMap(); +function extendWithBrowserId({ treeBuilder, browserId }) { + treeBuilder.addTrap(testObject => { + testObject.browserId = browserId; + }); +} +function extendWithBrowserVersion({ treeBuilder, config }) { + const { desiredCapabilities: { browserVersion, version }, } = config; + treeBuilder.addTrap(testObject => { + testObject.browserVersion = browserVersion || version; + }); +} +function extendWithTimeout({ treeBuilder, config }) { + const { testTimeout } = config; + if (!_.isNumber(testTimeout)) { + return; + } + treeBuilder.addTrap(testObject => { + testObject.timeout = testTimeout; + }); +} +function buildGlobalSkipInstruction(config) { + const skipBrowsers = env.parseCommaSeparatedValue("HERMIONE_SKIP_BROWSERS"); + validators.validateUnknownBrowsers(skipBrowsers, config.getBrowserIds()); + return ({ treeBuilder, browserId }) => { + if (!skipBrowsers.includes(browserId)) { + return; + } + treeBuilder.addTrap(testObject => { + testObject.skip({ reason: "The test was skipped by environment variable HERMIONE_SKIP_BROWSERS" }); + }); + }; +} +module.exports = { + InstructionsList, + Instructions: { + extendWithBrowserId, + extendWithBrowserVersion, + extendWithTimeout, + buildGlobalSkipInstruction, + }, +}; +//# sourceMappingURL=build-instructions.js.map \ No newline at end of file diff --git a/build/src/test-reader/build-instructions.js.map b/build/src/test-reader/build-instructions.js.map new file mode 100644 index 000000000..89d07e6f2 --- /dev/null +++ b/build/src/test-reader/build-instructions.js.map @@ -0,0 +1 @@ +{"version":3,"file":"build-instructions.js","sourceRoot":"","sources":["../../../src/test-reader/build-instructions.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/test-reader/controllers/browser-version-controller.d.ts b/build/src/test-reader/controllers/browser-version-controller.d.ts new file mode 100644 index 000000000..57d82eac8 --- /dev/null +++ b/build/src/test-reader/controllers/browser-version-controller.d.ts @@ -0,0 +1,9 @@ +/// +import { EventEmitter } from "events"; +export declare class BrowserVersionController { + #private; + static create(this: new (browserId: string, eventBug: EventEmitter) => T, browserId: string, eventBug: EventEmitter): T; + constructor(browserId: string, eventBus: EventEmitter); + version(browserVersion: string): this; +} +export declare function mkProvider(knownBrowsers: string[], eventBus: EventEmitter): (browserId: string) => BrowserVersionController; diff --git a/build/src/test-reader/controllers/browser-version-controller.js b/build/src/test-reader/controllers/browser-version-controller.js new file mode 100644 index 000000000..ec7f5ff5f --- /dev/null +++ b/build/src/test-reader/controllers/browser-version-controller.js @@ -0,0 +1,49 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _BrowserVersionController_browserId, _BrowserVersionController_eventBus; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.mkProvider = exports.BrowserVersionController = void 0; +const events_1 = require("../../events"); +class BrowserVersionController { + static create(browserId, eventBug) { + return new this(browserId, eventBug); + } + constructor(browserId, eventBus) { + _BrowserVersionController_browserId.set(this, void 0); + _BrowserVersionController_eventBus.set(this, void 0); + __classPrivateFieldSet(this, _BrowserVersionController_browserId, browserId, "f"); + __classPrivateFieldSet(this, _BrowserVersionController_eventBus, eventBus, "f"); + } + version(browserVersion) { + __classPrivateFieldGet(this, _BrowserVersionController_eventBus, "f").emit(events_1.TestReaderEvents.NEW_BUILD_INSTRUCTION, ({ treeBuilder }) => { + treeBuilder.addTrap(obj => { + if (obj.browserId === __classPrivateFieldGet(this, _BrowserVersionController_browserId, "f")) { + obj.browserVersion = browserVersion; + } + }); + }); + return this; + } +} +exports.BrowserVersionController = BrowserVersionController; +_BrowserVersionController_browserId = new WeakMap(), _BrowserVersionController_eventBus = new WeakMap(); +function mkProvider(knownBrowsers, eventBus) { + return browserId => { + if (!knownBrowsers.includes(browserId)) { + throw new Error(`browser "${browserId}" was not found in config file`); + } + return BrowserVersionController.create(browserId, eventBus); + }; +} +exports.mkProvider = mkProvider; +//# sourceMappingURL=browser-version-controller.js.map \ No newline at end of file diff --git a/build/src/test-reader/controllers/browser-version-controller.js.map b/build/src/test-reader/controllers/browser-version-controller.js.map new file mode 100644 index 000000000..b25b4cfb5 --- /dev/null +++ b/build/src/test-reader/controllers/browser-version-controller.js.map @@ -0,0 +1 @@ +{"version":3,"file":"browser-version-controller.js","sourceRoot":"","sources":["../../../../src/test-reader/controllers/browser-version-controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,yCAA8D;AAO9D,MAAa,wBAAwB;IAIjC,MAAM,CAAC,MAAM,CAET,SAAiB,EACjB,QAAsB;QAEtB,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACzC,CAAC;IAED,YAAY,SAAiB,EAAE,QAAsB;QAXrD,sDAAmB;QACnB,qDAAwB;QAWpB,uBAAA,IAAI,uCAAc,SAAS,MAAA,CAAC;QAC5B,uBAAA,IAAI,sCAAa,QAAQ,MAAA,CAAC;IAC9B,CAAC;IAED,OAAO,CAAC,cAAsB;QAC1B,uBAAA,IAAI,0CAAU,CAAC,IAAI,CAAC,yBAAU,CAAC,qBAAqB,EAAE,CAAC,EAAE,WAAW,EAAgC,EAAE,EAAE;YACpG,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;gBACtB,IAAI,GAAG,CAAC,SAAS,KAAK,uBAAA,IAAI,2CAAW,EAAE,CAAC;oBACpC,GAAG,CAAC,cAAc,GAAG,cAAc,CAAC;gBACxC,CAAC;YACL,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ;AA5BD,4DA4BC;;AAED,SAAgB,UAAU,CACtB,aAAuB,EACvB,QAAsB;IAEtB,OAAO,SAAS,CAAC,EAAE;QACf,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,YAAY,SAAS,gCAAgC,CAAC,CAAC;QAC3E,CAAC;QAED,OAAO,wBAAwB,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAChE,CAAC,CAAC;AACN,CAAC;AAXD,gCAWC"} \ No newline at end of file diff --git a/build/src/test-reader/controllers/config-controller.d.ts b/build/src/test-reader/controllers/config-controller.d.ts new file mode 100644 index 000000000..b1598718e --- /dev/null +++ b/build/src/test-reader/controllers/config-controller.d.ts @@ -0,0 +1,8 @@ +/// +import { EventEmitter } from "events"; +export declare class ConfigController { + #private; + static create(this: new (eventBus: EventEmitter) => T, eventBus: EventEmitter): T; + constructor(eventBus: EventEmitter); + testTimeout(timeout: number): this; +} diff --git a/build/src/test-reader/controllers/config-controller.js b/build/src/test-reader/controllers/config-controller.js new file mode 100644 index 000000000..b08e6c69c --- /dev/null +++ b/build/src/test-reader/controllers/config-controller.js @@ -0,0 +1,34 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _ConfigController_eventBus; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ConfigController = void 0; +const events_1 = require("../../events"); +class ConfigController { + static create(eventBus) { + return new this(eventBus); + } + constructor(eventBus) { + _ConfigController_eventBus.set(this, void 0); + __classPrivateFieldSet(this, _ConfigController_eventBus, eventBus, "f"); + } + testTimeout(timeout) { + __classPrivateFieldGet(this, _ConfigController_eventBus, "f").emit(events_1.TestReaderEvents.NEW_BUILD_INSTRUCTION, ({ treeBuilder }) => { + treeBuilder.addTrap(obj => (obj.timeout = timeout)); + }); + return this; + } +} +exports.ConfigController = ConfigController; +_ConfigController_eventBus = new WeakMap(); +//# sourceMappingURL=config-controller.js.map \ No newline at end of file diff --git a/build/src/test-reader/controllers/config-controller.js.map b/build/src/test-reader/controllers/config-controller.js.map new file mode 100644 index 000000000..44eab0098 --- /dev/null +++ b/build/src/test-reader/controllers/config-controller.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config-controller.js","sourceRoot":"","sources":["../../../../src/test-reader/controllers/config-controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,yCAA8D;AAO9D,MAAa,gBAAgB;IAGzB,MAAM,CAAC,MAAM,CAAsE,QAAsB;QACrG,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IAED,YAAY,QAAsB;QANlC,6CAAwB;QAOpB,uBAAA,IAAI,8BAAa,QAAQ,MAAA,CAAC;IAC9B,CAAC;IAED,WAAW,CAAC,OAAe;QACvB,uBAAA,IAAI,kCAAU,CAAC,IAAI,CAAC,yBAAU,CAAC,qBAAqB,EAAE,CAAC,EAAE,WAAW,EAAgC,EAAE,EAAE;YACpG,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ;AAlBD,4CAkBC"} \ No newline at end of file diff --git a/build/src/test-reader/controllers/only-controller.d.ts b/build/src/test-reader/controllers/only-controller.d.ts new file mode 100644 index 000000000..63d41b39f --- /dev/null +++ b/build/src/test-reader/controllers/only-controller.d.ts @@ -0,0 +1,9 @@ +/// +import { EventEmitter } from "events"; +export declare class OnlyController { + #private; + static create(this: new (eventBus: EventEmitter) => T, eventBus: EventEmitter): T; + constructor(eventBus: EventEmitter); + in(matchers: string | RegExp | Array): this; + notIn(matchers: string | RegExp | Array): this; +} diff --git a/build/src/test-reader/controllers/only-controller.js b/build/src/test-reader/controllers/only-controller.js new file mode 100644 index 000000000..896ec2b96 --- /dev/null +++ b/build/src/test-reader/controllers/only-controller.js @@ -0,0 +1,49 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _OnlyController_instances, _OnlyController_eventBus, _OnlyController_addTrap, _OnlyController_match; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.OnlyController = void 0; +const events_1 = require("../../events"); +class OnlyController { + static create(eventBus) { + return new this(eventBus); + } + constructor(eventBus) { + _OnlyController_instances.add(this); + _OnlyController_eventBus.set(this, void 0); + __classPrivateFieldSet(this, _OnlyController_eventBus, eventBus, "f"); + } + in(matchers) { + __classPrivateFieldGet(this, _OnlyController_instances, "m", _OnlyController_addTrap).call(this, browserId => __classPrivateFieldGet(this, _OnlyController_instances, "m", _OnlyController_match).call(this, browserId, matchers)); + return this; + } + notIn(matchers) { + __classPrivateFieldGet(this, _OnlyController_instances, "m", _OnlyController_addTrap).call(this, browserId => !__classPrivateFieldGet(this, _OnlyController_instances, "m", _OnlyController_match).call(this, browserId, matchers)); + return this; + } +} +exports.OnlyController = OnlyController; +_OnlyController_eventBus = new WeakMap(), _OnlyController_instances = new WeakSet(), _OnlyController_addTrap = function _OnlyController_addTrap(match) { + __classPrivateFieldGet(this, _OnlyController_eventBus, "f").emit(events_1.TestReaderEvents.NEW_BUILD_INSTRUCTION, ({ treeBuilder }) => { + treeBuilder.addTrap(obj => { + if (!match(obj.browserId)) { + obj.disable(); + } + }); + }); +}, _OnlyController_match = function _OnlyController_match(browserId, matchers) { + return [].concat(matchers).some(m => { + return m instanceof RegExp ? m.test(browserId) : m === browserId; + }); +}; +//# sourceMappingURL=only-controller.js.map \ No newline at end of file diff --git a/build/src/test-reader/controllers/only-controller.js.map b/build/src/test-reader/controllers/only-controller.js.map new file mode 100644 index 000000000..cc49b369e --- /dev/null +++ b/build/src/test-reader/controllers/only-controller.js.map @@ -0,0 +1 @@ +{"version":3,"file":"only-controller.js","sourceRoot":"","sources":["../../../../src/test-reader/controllers/only-controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,yCAA8D;AAO9D,MAAa,cAAc;IAGvB,MAAM,CAAC,MAAM,CAAoE,QAAsB;QACnG,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IAED,YAAY,QAAsB;;QANlC,2CAAwB;QAOpB,uBAAA,IAAI,4BAAa,QAAQ,MAAA,CAAC;IAC9B,CAAC;IAED,EAAE,CAAC,QAAkD;QACjD,uBAAA,IAAI,0DAAS,MAAb,IAAI,EAAU,SAAS,CAAC,EAAE,CAAC,uBAAA,IAAI,wDAAO,MAAX,IAAI,EAAQ,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;QAE7D,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,QAAkD;QACpD,uBAAA,IAAI,0DAAS,MAAb,IAAI,EAAU,SAAS,CAAC,EAAE,CAAC,CAAC,uBAAA,IAAI,wDAAO,MAAX,IAAI,EAAQ,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;QAE9D,OAAO,IAAI,CAAC;IAChB,CAAC;CAiBJ;AAtCD,wCAsCC;gJAfY,KAAqC;IAC1C,uBAAA,IAAI,gCAAU,CAAC,IAAI,CAAC,yBAAU,CAAC,qBAAqB,EAAE,CAAC,EAAE,WAAW,EAAgC,EAAE,EAAE;QACpG,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YACtB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBACxB,GAAG,CAAC,OAAO,EAAE,CAAC;YAClB,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,yDAEM,SAAiB,EAAE,QAAkD;IACxE,OAAQ,EAA6B,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;QAC5D,OAAO,CAAC,YAAY,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;IACrE,CAAC,CAAC,CAAC;AACP,CAAC"} \ No newline at end of file diff --git a/build/src/test-reader/controllers/skip-controller.d.ts b/build/src/test-reader/controllers/skip-controller.d.ts new file mode 100644 index 000000000..e64b5ae98 --- /dev/null +++ b/build/src/test-reader/controllers/skip-controller.d.ts @@ -0,0 +1,14 @@ +/// +import { EventEmitter } from "events"; +interface SkipOpts { + negate?: boolean; + silent?: boolean; +} +export declare class SkipController { + #private; + static create(this: new (eventBus: EventEmitter) => T, eventBus: EventEmitter): T; + constructor(eventBus: EventEmitter); + in(matchers: string | RegExp | Array, reason: string, { silent }?: SkipOpts): this; + notIn(matchers: string | RegExp | Array, reason: string, { silent }?: SkipOpts): this; +} +export {}; diff --git a/build/src/test-reader/controllers/skip-controller.js b/build/src/test-reader/controllers/skip-controller.js new file mode 100644 index 000000000..5c79f8c97 --- /dev/null +++ b/build/src/test-reader/controllers/skip-controller.js @@ -0,0 +1,55 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _SkipController_instances, _SkipController_eventBus, _SkipController_addTrap, _SkipController_match; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SkipController = void 0; +const events_1 = require("../../events"); +class SkipController { + static create(eventBus) { + return new this(eventBus); + } + constructor(eventBus) { + _SkipController_instances.add(this); + _SkipController_eventBus.set(this, void 0); + __classPrivateFieldSet(this, _SkipController_eventBus, eventBus, "f"); + } + in(matchers, reason, { silent } = {}) { + __classPrivateFieldGet(this, _SkipController_instances, "m", _SkipController_addTrap).call(this, browserId => __classPrivateFieldGet(this, _SkipController_instances, "m", _SkipController_match).call(this, matchers, browserId), reason, { silent }); + return this; + } + notIn(matchers, reason, { silent } = {}) { + __classPrivateFieldGet(this, _SkipController_instances, "m", _SkipController_addTrap).call(this, browserId => !__classPrivateFieldGet(this, _SkipController_instances, "m", _SkipController_match).call(this, matchers, browserId), reason, { silent }); + return this; + } +} +exports.SkipController = SkipController; +_SkipController_eventBus = new WeakMap(), _SkipController_instances = new WeakSet(), _SkipController_addTrap = function _SkipController_addTrap(match, reason, { silent } = {}) { + __classPrivateFieldGet(this, _SkipController_eventBus, "f").emit(events_1.TestReaderEvents.NEW_BUILD_INSTRUCTION, ({ treeBuilder }) => { + treeBuilder.addTrap(obj => { + if (!match(obj.browserId)) { + return; + } + if (silent) { + obj.disable(); + } + else { + obj.skip({ reason }); + } + }); + }); +}, _SkipController_match = function _SkipController_match(matchers, browserId) { + return [].concat(matchers).some(m => { + return m instanceof RegExp ? m.test(browserId) : m === browserId; + }); +}; +//# sourceMappingURL=skip-controller.js.map \ No newline at end of file diff --git a/build/src/test-reader/controllers/skip-controller.js.map b/build/src/test-reader/controllers/skip-controller.js.map new file mode 100644 index 000000000..0d97652a3 --- /dev/null +++ b/build/src/test-reader/controllers/skip-controller.js.map @@ -0,0 +1 @@ +{"version":3,"file":"skip-controller.js","sourceRoot":"","sources":["../../../../src/test-reader/controllers/skip-controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,yCAA8D;AAY9D,MAAa,cAAc;IAGvB,MAAM,CAAC,MAAM,CAAoE,QAAsB;QACnG,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IAED,YAAY,QAAsB;;QANlC,2CAAwB;QAOpB,uBAAA,IAAI,4BAAa,QAAQ,MAAA,CAAC;IAC9B,CAAC;IAED,EAAE,CAAC,QAAkD,EAAE,MAAc,EAAE,EAAE,MAAM,KAAe,EAAE;QAC5F,uBAAA,IAAI,0DAAS,MAAb,IAAI,EAAU,SAAS,CAAC,EAAE,CAAC,uBAAA,IAAI,wDAAO,MAAX,IAAI,EAAQ,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAEjF,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,QAAkD,EAAE,MAAc,EAAE,EAAE,MAAM,KAAe,EAAE;QAC/F,uBAAA,IAAI,0DAAS,MAAb,IAAI,EAAU,SAAS,CAAC,EAAE,CAAC,CAAC,uBAAA,IAAI,wDAAO,MAAX,IAAI,EAAQ,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAElF,OAAO,IAAI,CAAC;IAChB,CAAC;CAuBJ;AA5CD,wCA4CC;gJArBY,KAAqC,EAAE,MAAc,EAAE,EAAE,MAAM,KAAe,EAAE;IACrF,uBAAA,IAAI,gCAAU,CAAC,IAAI,CAAC,yBAAU,CAAC,qBAAqB,EAAE,CAAC,EAAE,WAAW,EAAgC,EAAE,EAAE;QACpG,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YACtB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBACxB,OAAO;YACX,CAAC;YAED,IAAI,MAAM,EAAE,CAAC;gBACT,GAAG,CAAC,OAAO,EAAE,CAAC;YAClB,CAAC;iBAAM,CAAC;gBACJ,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YACzB,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,yDAEM,QAAkD,EAAE,SAAiB;IACxE,OAAQ,EAA6B,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;QAC5D,OAAO,CAAC,YAAY,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;IACrE,CAAC,CAAC,CAAC;AACP,CAAC"} \ No newline at end of file diff --git a/build/src/test-reader/index.d.ts b/build/src/test-reader/index.d.ts new file mode 100644 index 000000000..f9568922f --- /dev/null +++ b/build/src/test-reader/index.d.ts @@ -0,0 +1,10 @@ +export = TestReader; +declare class TestReader extends EventEmitter { + static create(...args: any[]): import("."); + constructor(config: any); + read(options?: {}): Promise<{ + [x: string]: any; + }>; + #private; +} +import { EventEmitter } from "events"; diff --git a/build/src/test-reader/index.js b/build/src/test-reader/index.js new file mode 100644 index 000000000..683d57187 --- /dev/null +++ b/build/src/test-reader/index.js @@ -0,0 +1,85 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _TestReader_config, _a; +const _ = require("lodash"); +const { EventEmitter } = require("events"); +const { passthroughEvent } = require("../events/utils"); +const SetsBuilder = require("./sets-builder"); +const { TestParser } = require("./test-parser"); +const { MasterEvents } = require("../events"); +const env = require("../utils/env"); +module.exports = (_a = class TestReader extends EventEmitter { + static create(...args) { + return new this(...args); + } + constructor(config) { + super(); + _TestReader_config.set(this, void 0); + __classPrivateFieldSet(this, _TestReader_config, config, "f"); + } + async read(options = {}) { + const { paths, browsers, ignore, sets, grep } = options; + const { fileExtensions } = __classPrivateFieldGet(this, _TestReader_config, "f").system; + const setCollection = await SetsBuilder.create(__classPrivateFieldGet(this, _TestReader_config, "f").sets, { defaultDir: require("../../package").name }) + .useFiles(paths) + .useSets((sets || []).concat(env.parseCommaSeparatedValue("HERMIONE_SETS"))) + .useBrowsers(browsers) + .build(process.cwd(), { ignore }, fileExtensions); + const parser = new TestParser(); + passthroughEvent(parser, this, [MasterEvents.BEFORE_FILE_READ, MasterEvents.AFTER_FILE_READ]); + await parser.loadFiles(setCollection.getAllFiles(), __classPrivateFieldGet(this, _TestReader_config, "f")); + const filesByBro = setCollection.groupByBrowser(); + const testsByBro = _.mapValues(filesByBro, (files, browserId) => parser.parse(files, { browserId, config: __classPrivateFieldGet(this, _TestReader_config, "f").forBrowser(browserId), grep })); + validateTests(testsByBro, options); + return testsByBro; + } + }, + _TestReader_config = new WeakMap(), + _a); +function validateTests(testsByBro, options) { + const tests = _.flatten(Object.values(testsByBro)); + if (options.replMode?.enabled) { + const testsToRun = tests.filter(test => !test.disabled && !test.pending); + const browsersToRun = _.uniq(testsToRun.map(test => test.browserId)); + if (testsToRun.length !== 1) { + throw new Error(`In repl mode only 1 test in 1 browser should be run, but found ${testsToRun.length} tests` + + `${testsToRun.length === 0 ? ". " : ` that run in ${browsersToRun.join(", ")} browsers. `}` + + `Try to specify cli-options: "--grep" and "--browser" or use "hermione.only.in" in the test file.`); + } + } + if (!_.isEmpty(tests) && tests.some(test => !test.silentSkip)) { + return; + } + const stringifiedOpts = convertOptions(options); + if (_.isEmpty(stringifiedOpts)) { + throw new Error(`There are no tests found. Try to specify [${Object.keys(options).join(", ")}] options`); + } + else { + throw new Error(`There are no tests found by the specified options:\n${stringifiedOpts}`); + } +} +function convertOptions(obj) { + let result = ""; + for (let key of _.keys(obj)) { + if (!_.isEmpty(obj[key])) { + if (_.isArray(obj[key])) { + result += `- ${key}: ${obj[key].join(", ")}\n`; + } + else { + result += `- ${key}: ${obj[key]}\n`; + } + } + } + return result; +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/test-reader/index.js.map b/build/src/test-reader/index.js.map new file mode 100644 index 000000000..a9c92d2ce --- /dev/null +++ b/build/src/test-reader/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/test-reader/index.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/test-reader/mocha-reader/index.d.ts b/build/src/test-reader/mocha-reader/index.d.ts new file mode 100644 index 000000000..5e7d55bca --- /dev/null +++ b/build/src/test-reader/mocha-reader/index.d.ts @@ -0,0 +1,5 @@ +export function readFiles(files: any, { esmDecorator, config, eventBus }: { + esmDecorator: any; + config: any; + eventBus: any; +}): Promise; diff --git a/build/src/test-reader/mocha-reader/index.js b/build/src/test-reader/mocha-reader/index.js new file mode 100644 index 000000000..de631900e --- /dev/null +++ b/build/src/test-reader/mocha-reader/index.js @@ -0,0 +1,78 @@ +"use strict"; +const { MochaEventBus } = require("./mocha-event-bus"); +const { TreeBuilderDecorator } = require("./tree-builder-decorator"); +const { TestReaderEvents } = require("../../events"); +const { MasterEvents } = require("../../events"); +const Mocha = require("mocha"); +async function readFiles(files, { esmDecorator, config, eventBus }) { + const mocha = new Mocha(config); + mocha.fullTrace(); + initBuildContext(eventBus); + initEventListeners(mocha.suite, eventBus); + files.forEach(f => mocha.addFile(f)); + await mocha.loadFilesAsync({ esmDecorator }); + applyOnly(mocha.suite, eventBus); +} +function initBuildContext(outBus) { + outBus.emit(TestReaderEvents.NEW_BUILD_INSTRUCTION, ctx => { + ctx.treeBuilder = TreeBuilderDecorator.create(ctx.treeBuilder); + }); +} +function initEventListeners(rootSuite, outBus) { + const inBus = MochaEventBus.create(rootSuite); + forbidSuiteHooks(inBus); + passthroughFileEvents(inBus, outBus); + registerTestObjects(inBus, outBus); + inBus.emit(MochaEventBus.events.EVENT_SUITE_ADD_SUITE, rootSuite); +} +function forbidSuiteHooks(bus) { + [MochaEventBus.events.EVENT_SUITE_ADD_HOOK_BEFORE_ALL, MochaEventBus.events.EVENT_SUITE_ADD_HOOK_AFTER_ALL].forEach(event => { + bus.on(event, () => { + throw new Error('"before" and "after" hooks are forbidden, use "beforeEach" and "afterEach" hooks instead'); + }); + }); +} +function passthroughFileEvents(inBus, outBus) { + [ + [MochaEventBus.events.EVENT_FILE_PRE_REQUIRE, MasterEvents.BEFORE_FILE_READ], + [MochaEventBus.events.EVENT_FILE_POST_REQUIRE, MasterEvents.AFTER_FILE_READ], + ].forEach(([mochaEvent, ourEvent]) => { + inBus.on(mochaEvent, (ctx, file) => outBus.emit(ourEvent, { file })); + }); +} +function registerTestObjects(inBus, outBus) { + [ + [MochaEventBus.events.EVENT_SUITE_ADD_SUITE, (treeBuilder, suite) => treeBuilder.addSuite(suite)], + [MochaEventBus.events.EVENT_SUITE_ADD_TEST, (treeBuilder, test) => treeBuilder.addTest(test)], + [ + MochaEventBus.events.EVENT_SUITE_ADD_HOOK_BEFORE_EACH, + (treeBuilder, hook) => treeBuilder.addBeforeEachHook(hook), + ], + [ + MochaEventBus.events.EVENT_SUITE_ADD_HOOK_AFTER_EACH, + (treeBuilder, hook) => treeBuilder.addAfterEachHook(hook), + ], + ].forEach(([event, instruction]) => { + inBus.on(event, testObject => { + outBus.emit(TestReaderEvents.NEW_BUILD_INSTRUCTION, ({ treeBuilder }) => instruction(treeBuilder, testObject)); + }); + }); +} +function applyOnly(rootSuite, eventBus) { + if (!rootSuite.hasOnly()) { + return; + } + const titlesToRun = []; + // filterOnly modifies mocha tree removing links between test objects from top to bottom + // we are using links from bottom to top (i.e. parent property) + // so it is safe to use build instructions after modifying mocha tree + rootSuite.filterOnly(); + rootSuite.eachTest(mochaTest => titlesToRun.push(mochaTest.fullTitle())); + eventBus.emit(TestReaderEvents.NEW_BUILD_INSTRUCTION, ({ treeBuilder }) => { + treeBuilder.addTestFilter(test => titlesToRun.includes(test.fullTitle())); + }); +} +module.exports = { + readFiles, +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/test-reader/mocha-reader/index.js.map b/build/src/test-reader/mocha-reader/index.js.map new file mode 100644 index 000000000..fae994347 --- /dev/null +++ b/build/src/test-reader/mocha-reader/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/test-reader/mocha-reader/index.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/test-reader/mocha-reader/mocha-event-bus.d.ts b/build/src/test-reader/mocha-reader/mocha-event-bus.d.ts new file mode 100644 index 000000000..52fae87d2 --- /dev/null +++ b/build/src/test-reader/mocha-reader/mocha-event-bus.d.ts @@ -0,0 +1,8 @@ +export class MochaEventBus extends EventEmitter { + static events: Mocha.SuiteConstants; + static create(...args: any[]): MochaEventBus; + constructor(rootSuite: any); + #private; +} +import { EventEmitter } from "events"; +import Mocha = require("mocha"); diff --git a/build/src/test-reader/mocha-reader/mocha-event-bus.js b/build/src/test-reader/mocha-reader/mocha-event-bus.js new file mode 100644 index 000000000..2a3beeff6 --- /dev/null +++ b/build/src/test-reader/mocha-reader/mocha-event-bus.js @@ -0,0 +1,43 @@ +"use strict"; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _MochaEventBus_instances, _MochaEventBus_addRecursiveHandler; +const { EventEmitter } = require("events"); +const Mocha = require("mocha"); +const { EVENT_FILE_PRE_REQUIRE, EVENT_FILE_POST_REQUIRE, EVENT_SUITE_ADD_SUITE, EVENT_SUITE_ADD_TEST, EVENT_SUITE_ADD_HOOK_BEFORE_ALL, EVENT_SUITE_ADD_HOOK_AFTER_ALL, EVENT_SUITE_ADD_HOOK_BEFORE_EACH, EVENT_SUITE_ADD_HOOK_AFTER_EACH, } = Mocha.Suite.constants; +class MochaEventBus extends EventEmitter { + static create(...args) { + return new this(...args); + } + constructor(rootSuite) { + super(); + _MochaEventBus_instances.add(this); + rootSuite.setMaxListeners(0); + __classPrivateFieldGet(this, _MochaEventBus_instances, "m", _MochaEventBus_addRecursiveHandler).call(this, rootSuite, EVENT_SUITE_ADD_SUITE, suite => suite.setMaxListeners(0)); + [EVENT_FILE_PRE_REQUIRE, EVENT_FILE_POST_REQUIRE].forEach(event => { + rootSuite.on(event, (...args) => this.emit(event, ...args)); + }); + [ + EVENT_SUITE_ADD_SUITE, + EVENT_SUITE_ADD_TEST, + EVENT_SUITE_ADD_HOOK_BEFORE_ALL, + EVENT_SUITE_ADD_HOOK_AFTER_ALL, + EVENT_SUITE_ADD_HOOK_BEFORE_EACH, + EVENT_SUITE_ADD_HOOK_AFTER_EACH, + ].forEach(event => { + __classPrivateFieldGet(this, _MochaEventBus_instances, "m", _MochaEventBus_addRecursiveHandler).call(this, rootSuite, event, (...args) => this.emit(event, ...args)); + }); + } +} +_MochaEventBus_instances = new WeakSet(), _MochaEventBus_addRecursiveHandler = function _MochaEventBus_addRecursiveHandler(suite, event, cb) { + suite.on(EVENT_SUITE_ADD_SUITE, subSuite => __classPrivateFieldGet(this, _MochaEventBus_instances, "m", _MochaEventBus_addRecursiveHandler).call(this, subSuite, event, cb)); + suite.on(event, cb); +}; +MochaEventBus.events = Mocha.Suite.constants; +module.exports = { + MochaEventBus, +}; +//# sourceMappingURL=mocha-event-bus.js.map \ No newline at end of file diff --git a/build/src/test-reader/mocha-reader/mocha-event-bus.js.map b/build/src/test-reader/mocha-reader/mocha-event-bus.js.map new file mode 100644 index 000000000..ff934c68b --- /dev/null +++ b/build/src/test-reader/mocha-reader/mocha-event-bus.js.map @@ -0,0 +1 @@ +{"version":3,"file":"mocha-event-bus.js","sourceRoot":"","sources":["../../../../src/test-reader/mocha-reader/mocha-event-bus.js"],"names":[],"mappings":";;;;;;;AAAA,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAE/B,MAAM,EACF,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EACpB,+BAA+B,EAC/B,8BAA8B,EAC9B,gCAAgC,EAChC,+BAA+B,GAClC,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC;AAE1B,MAAM,aAAc,SAAQ,YAAY;IAGpC,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI;QACjB,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,YAAY,SAAS;QACjB,KAAK,EAAE,CAAC;;QAER,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC7B,uBAAA,IAAI,oEAAqB,MAAzB,IAAI,EAAsB,SAAS,EAAE,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QAE/F,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YAC9D,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;QAEH;YACI,qBAAqB;YACrB,oBAAoB;YACpB,+BAA+B;YAC/B,8BAA8B;YAC9B,gCAAgC;YAChC,+BAA+B;SAClC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACd,uBAAA,IAAI,oEAAqB,MAAzB,IAAI,EAAsB,SAAS,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;QACxF,CAAC,CAAC,CAAC;IACP,CAAC;;2HAEoB,KAAK,EAAE,KAAK,EAAE,EAAE;IACjC,KAAK,CAAC,EAAE,CAAC,qBAAqB,EAAE,QAAQ,CAAC,EAAE,CAAC,uBAAA,IAAI,oEAAqB,MAAzB,IAAI,EAAsB,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;IAC5F,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACxB,CAAC;AA/BM,oBAAM,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,AAAxB,CAAyB;AAkC1C,MAAM,CAAC,OAAO,GAAG;IACb,aAAa;CAChB,CAAC"} \ No newline at end of file diff --git a/build/src/test-reader/mocha-reader/tree-builder-decorator.d.ts b/build/src/test-reader/mocha-reader/tree-builder-decorator.d.ts new file mode 100644 index 000000000..17a1fda83 --- /dev/null +++ b/build/src/test-reader/mocha-reader/tree-builder-decorator.d.ts @@ -0,0 +1,13 @@ +export class TreeBuilderDecorator { + static create(...args: any[]): TreeBuilderDecorator; + constructor(treeBuilder: any); + addSuite(mochaSuite: any): this; + addTest(mochaTest: any): this; + addBeforeEachHook(mochaHook: any): this; + addAfterEachHook(mochaHook: any): this; + addTrap(fn: any): this; + addTestFilter(fn: any): this; + applyFilters(): this; + getRootSuite(): any; + #private; +} diff --git a/build/src/test-reader/mocha-reader/tree-builder-decorator.js b/build/src/test-reader/mocha-reader/tree-builder-decorator.js new file mode 100644 index 000000000..62868d07d --- /dev/null +++ b/build/src/test-reader/mocha-reader/tree-builder-decorator.js @@ -0,0 +1,98 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _TreeBuilderDecorator_instances, _TreeBuilderDecorator_treeBuilder, _TreeBuilderDecorator_suiteMap, _TreeBuilderDecorator_suiteCounter, _TreeBuilderDecorator_addHook, _TreeBuilderDecorator_mkTestObject, _TreeBuilderDecorator_applyConfig, _TreeBuilderDecorator_getParent; +const { Suite, Test, Hook } = require("../test-object"); +const crypto = require("../../utils/crypto"); +class TreeBuilderDecorator { + static create(...args) { + return new this(...args); + } + constructor(treeBuilder) { + _TreeBuilderDecorator_instances.add(this); + _TreeBuilderDecorator_treeBuilder.set(this, void 0); + _TreeBuilderDecorator_suiteMap.set(this, void 0); + _TreeBuilderDecorator_suiteCounter.set(this, void 0); + __classPrivateFieldSet(this, _TreeBuilderDecorator_treeBuilder, treeBuilder, "f"); + __classPrivateFieldSet(this, _TreeBuilderDecorator_suiteMap, new Map(), "f"); + __classPrivateFieldSet(this, _TreeBuilderDecorator_suiteCounter, new Map(), "f"); + } + addSuite(mochaSuite) { + const { id: mochaId, file } = mochaSuite; + const positionInFile = __classPrivateFieldGet(this, _TreeBuilderDecorator_suiteCounter, "f").get(file) || 0; + const id = mochaSuite.root ? mochaId : crypto.getShortMD5(file) + positionInFile; + const suite = __classPrivateFieldGet(this, _TreeBuilderDecorator_instances, "m", _TreeBuilderDecorator_mkTestObject).call(this, Suite, mochaSuite, { id }); + __classPrivateFieldGet(this, _TreeBuilderDecorator_instances, "m", _TreeBuilderDecorator_applyConfig).call(this, suite, mochaSuite); + __classPrivateFieldGet(this, _TreeBuilderDecorator_treeBuilder, "f").addSuite(suite, __classPrivateFieldGet(this, _TreeBuilderDecorator_instances, "m", _TreeBuilderDecorator_getParent).call(this, mochaSuite, null)); + __classPrivateFieldGet(this, _TreeBuilderDecorator_suiteMap, "f").set(mochaId, suite); + __classPrivateFieldGet(this, _TreeBuilderDecorator_suiteCounter, "f").set(file, positionInFile + 1); + return this; + } + addTest(mochaTest) { + const { fn } = mochaTest; + const id = crypto.getShortMD5(mochaTest.fullTitle()); + const test = __classPrivateFieldGet(this, _TreeBuilderDecorator_instances, "m", _TreeBuilderDecorator_mkTestObject).call(this, Test, mochaTest, { id, fn }); + __classPrivateFieldGet(this, _TreeBuilderDecorator_instances, "m", _TreeBuilderDecorator_applyConfig).call(this, test, mochaTest); + __classPrivateFieldGet(this, _TreeBuilderDecorator_treeBuilder, "f").addTest(test, __classPrivateFieldGet(this, _TreeBuilderDecorator_instances, "m", _TreeBuilderDecorator_getParent).call(this, mochaTest)); + return this; + } + addBeforeEachHook(mochaHook) { + return __classPrivateFieldGet(this, _TreeBuilderDecorator_instances, "m", _TreeBuilderDecorator_addHook).call(this, mochaHook, (hook, parent) => __classPrivateFieldGet(this, _TreeBuilderDecorator_treeBuilder, "f").addBeforeEachHook(hook, parent)); + } + addAfterEachHook(mochaHook) { + return __classPrivateFieldGet(this, _TreeBuilderDecorator_instances, "m", _TreeBuilderDecorator_addHook).call(this, mochaHook, (hook, parent) => __classPrivateFieldGet(this, _TreeBuilderDecorator_treeBuilder, "f").addAfterEachHook(hook, parent)); + } + addTrap(fn) { + __classPrivateFieldGet(this, _TreeBuilderDecorator_treeBuilder, "f").addTrap(fn); + return this; + } + addTestFilter(fn) { + __classPrivateFieldGet(this, _TreeBuilderDecorator_treeBuilder, "f").addTestFilter(fn); + return this; + } + applyFilters() { + __classPrivateFieldGet(this, _TreeBuilderDecorator_treeBuilder, "f").applyFilters(); + return this; + } + getRootSuite() { + return __classPrivateFieldGet(this, _TreeBuilderDecorator_treeBuilder, "f").getRootSuite(); + } +} +_TreeBuilderDecorator_treeBuilder = new WeakMap(), _TreeBuilderDecorator_suiteMap = new WeakMap(), _TreeBuilderDecorator_suiteCounter = new WeakMap(), _TreeBuilderDecorator_instances = new WeakSet(), _TreeBuilderDecorator_addHook = function _TreeBuilderDecorator_addHook(mochaHook, cb) { + const { fn, title } = mochaHook; + const hook = Hook.create({ fn, title }); + cb(hook, __classPrivateFieldGet(this, _TreeBuilderDecorator_instances, "m", _TreeBuilderDecorator_getParent).call(this, mochaHook)); + return this; +}, _TreeBuilderDecorator_mkTestObject = function _TreeBuilderDecorator_mkTestObject(Constructor, mochaObject, customOpts) { + const { title, file } = mochaObject; + return Constructor.create({ title, file, ...customOpts }); +}, _TreeBuilderDecorator_applyConfig = function _TreeBuilderDecorator_applyConfig(testObject, mochaObject) { + const { pending, parent } = mochaObject; + if (!parent || mochaObject.timeout() !== parent.timeout()) { + testObject.timeout = mochaObject.timeout(); + } + if (pending) { + testObject.skip({ reason: "Skipped by mocha interface" }); + } +}, _TreeBuilderDecorator_getParent = function _TreeBuilderDecorator_getParent({ parent }, defaultValue) { + if (!parent) { + if (defaultValue !== undefined) { + return defaultValue; + } + throw new Error("Parent not set"); + } + return __classPrivateFieldGet(this, _TreeBuilderDecorator_suiteMap, "f").get(parent.id); +}; +module.exports = { + TreeBuilderDecorator, +}; +//# sourceMappingURL=tree-builder-decorator.js.map \ No newline at end of file diff --git a/build/src/test-reader/mocha-reader/tree-builder-decorator.js.map b/build/src/test-reader/mocha-reader/tree-builder-decorator.js.map new file mode 100644 index 000000000..1d4272c99 --- /dev/null +++ b/build/src/test-reader/mocha-reader/tree-builder-decorator.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tree-builder-decorator.js","sourceRoot":"","sources":["../../../../src/test-reader/mocha-reader/tree-builder-decorator.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/test-reader/sets-builder/index.d.ts b/build/src/test-reader/sets-builder/index.d.ts new file mode 100644 index 000000000..b46ac48c9 --- /dev/null +++ b/build/src/test-reader/sets-builder/index.d.ts @@ -0,0 +1,12 @@ +export = SetsBuilder; +declare class SetsBuilder { + static create(sets: any, opts: any): import("."); + constructor(sets: any, opts: any); + useSets(setsToUse: any): this; + useFiles(files: any): this; + useBrowsers(browsers: any): this; + build(projectRoot: any, globOpts?: {}, fileExtensions?: string[]): Promise; + #private; +} +import SetCollection = require("./set-collection"); +import Promise = require("bluebird"); diff --git a/build/src/test-reader/sets-builder/index.js b/build/src/test-reader/sets-builder/index.js new file mode 100644 index 000000000..4c26480d6 --- /dev/null +++ b/build/src/test-reader/sets-builder/index.js @@ -0,0 +1,108 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _SetsBuilder_instances, _SetsBuilder_sets, _SetsBuilder_filesToUse, _SetsBuilder_validateUnknownSets, _SetsBuilder_transformDirsToMasks, _SetsBuilder_getSets, _SetsBuilder_resolvePaths, _SetsBuilder_validateFoundFiles, _SetsBuilder_useFiles, _SetsBuilder_expandFiles, _SetsBuilder_hasFiles, _a; +const path = require("path"); +const globExtra = require("glob-extra"); +const _ = require("lodash"); +const Promise = require("bluebird"); +const SetCollection = require("./set-collection"); +const TestSet = require("./test-set"); +const FILE_EXTENSIONS = [".js", ".mjs"]; +module.exports = (_a = class SetsBuilder { + static create(sets, opts) { + return new _a(sets, opts); + } + constructor(sets, opts) { + _SetsBuilder_instances.add(this); + _SetsBuilder_sets.set(this, void 0); + _SetsBuilder_filesToUse.set(this, void 0); + __classPrivateFieldSet(this, _SetsBuilder_sets, _.mapValues(sets, set => TestSet.create(set)), "f"); + __classPrivateFieldSet(this, _SetsBuilder_filesToUse, __classPrivateFieldGet(this, _SetsBuilder_instances, "m", _SetsBuilder_hasFiles).call(this) ? [] : [opts.defaultDir], "f"); + } + useSets(setsToUse) { + __classPrivateFieldGet(this, _SetsBuilder_instances, "m", _SetsBuilder_validateUnknownSets).call(this, setsToUse); + if (!_.isEmpty(setsToUse)) { + __classPrivateFieldSet(this, _SetsBuilder_sets, _.pick(__classPrivateFieldGet(this, _SetsBuilder_sets, "f"), setsToUse), "f"); + } + return this; + } + useFiles(files) { + if (!_.isEmpty(files)) { + __classPrivateFieldSet(this, _SetsBuilder_filesToUse, files, "f"); + } + return this; + } + useBrowsers(browsers) { + _.forEach(__classPrivateFieldGet(this, _SetsBuilder_sets, "f"), set => set.useBrowsers(browsers)); + return this; + } + build(projectRoot, globOpts = {}, fileExtensions = FILE_EXTENSIONS) { + const expandOpts = { formats: fileExtensions, root: projectRoot }; + if (globOpts.ignore) { + globOpts.ignore = [].concat(globOpts.ignore).map(ignorePattern => path.resolve(projectRoot, ignorePattern)); + } + return __classPrivateFieldGet(this, _SetsBuilder_instances, "m", _SetsBuilder_transformDirsToMasks).call(this) + .then(() => __classPrivateFieldGet(this, _SetsBuilder_instances, "m", _SetsBuilder_resolvePaths).call(this, projectRoot)) + .then(() => globExtra.expandPaths(__classPrivateFieldGet(this, _SetsBuilder_filesToUse, "f"), expandOpts, globOpts)) + .then(expandedFiles => { + __classPrivateFieldGet(this, _SetsBuilder_instances, "m", _SetsBuilder_validateFoundFiles).call(this, expandedFiles); + __classPrivateFieldGet(this, _SetsBuilder_instances, "m", _SetsBuilder_useFiles).call(this, expandedFiles); + }) + .then(() => __classPrivateFieldGet(this, _SetsBuilder_instances, "m", _SetsBuilder_expandFiles).call(this, expandOpts, globOpts)) + .then(() => SetCollection.create(__classPrivateFieldGet(this, _SetsBuilder_sets, "f"))); + } + }, + _SetsBuilder_sets = new WeakMap(), + _SetsBuilder_filesToUse = new WeakMap(), + _SetsBuilder_instances = new WeakSet(), + _SetsBuilder_validateUnknownSets = function _SetsBuilder_validateUnknownSets(setsToUse) { + const setsNames = _.keys(__classPrivateFieldGet(this, _SetsBuilder_sets, "f")); + const unknownSets = _.difference(setsToUse, setsNames); + if (_.isEmpty(unknownSets)) { + return; + } + let error = `No such sets: ${unknownSets.join(", ")}.`; + if (!_.isEmpty(setsNames)) { + error += ` Use one of the specified sets: ${setsNames.join(", ")}`; + } + throw new Error(error); + }, + _SetsBuilder_transformDirsToMasks = function _SetsBuilder_transformDirsToMasks() { + return Promise.map(__classPrivateFieldGet(this, _SetsBuilder_instances, "m", _SetsBuilder_getSets).call(this), set => set.transformDirsToMasks()); + }, + _SetsBuilder_getSets = function _SetsBuilder_getSets() { + return _.values(__classPrivateFieldGet(this, _SetsBuilder_sets, "f")); + }, + _SetsBuilder_resolvePaths = function _SetsBuilder_resolvePaths(projectRoot) { + _.forEach(__classPrivateFieldGet(this, _SetsBuilder_sets, "f"), set => set.resolveFiles(projectRoot)); + }, + _SetsBuilder_validateFoundFiles = function _SetsBuilder_validateFoundFiles(foundFiles) { + if (!_.isEmpty(__classPrivateFieldGet(this, _SetsBuilder_filesToUse, "f")) && _.isEmpty(foundFiles)) { + const paths = [].concat(__classPrivateFieldGet(this, _SetsBuilder_filesToUse, "f")).join(", "); + throw new Error(`Cannot find files by specified paths: ${paths}`); + } + }, + _SetsBuilder_useFiles = function _SetsBuilder_useFiles(filesToUse) { + _.forEach(__classPrivateFieldGet(this, _SetsBuilder_sets, "f"), set => set.useFiles(filesToUse)); + if (!__classPrivateFieldGet(this, _SetsBuilder_instances, "m", _SetsBuilder_hasFiles).call(this)) { + throw new Error("Cannot find files by masks in sets"); + } + }, + _SetsBuilder_expandFiles = function _SetsBuilder_expandFiles(expandOpts, globOpts) { + return Promise.map(__classPrivateFieldGet(this, _SetsBuilder_instances, "m", _SetsBuilder_getSets).call(this), set => set.expandFiles(expandOpts, globOpts)); + }, + _SetsBuilder_hasFiles = function _SetsBuilder_hasFiles() { + return _.some(__classPrivateFieldGet(this, _SetsBuilder_sets, "f"), set => !_.isEmpty(set.getFiles())); + }, + _a); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/test-reader/sets-builder/index.js.map b/build/src/test-reader/sets-builder/index.js.map new file mode 100644 index 000000000..202cb055c --- /dev/null +++ b/build/src/test-reader/sets-builder/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/test-reader/sets-builder/index.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/test-reader/sets-builder/set-collection.d.ts b/build/src/test-reader/sets-builder/set-collection.d.ts new file mode 100644 index 000000000..6be32013e --- /dev/null +++ b/build/src/test-reader/sets-builder/set-collection.d.ts @@ -0,0 +1,10 @@ +export = SetCollection; +declare class SetCollection { + static create(sets: any): import("./set-collection"); + constructor(sets: any); + groupByFile(): _.Dictionary; + getAllFiles(): any[]; + groupByBrowser(): _.Dictionary; + #private; +} +import _ = require("lodash"); diff --git a/build/src/test-reader/sets-builder/set-collection.js b/build/src/test-reader/sets-builder/set-collection.js new file mode 100644 index 000000000..da835a716 --- /dev/null +++ b/build/src/test-reader/sets-builder/set-collection.js @@ -0,0 +1,53 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _SetCollection_instances, _SetCollection_sets, _SetCollection_getBrowsersForFile, _SetCollection_getBrowsers, _SetCollection_getFilesForBrowser, _SetCollection_getFromSets, _a; +const _ = require("lodash"); +module.exports = (_a = class SetCollection { + static create(sets) { + return new _a(sets); + } + constructor(sets) { + _SetCollection_instances.add(this); + _SetCollection_sets.set(this, void 0); + __classPrivateFieldSet(this, _SetCollection_sets, sets, "f"); + } + groupByFile() { + const files = this.getAllFiles(); + const browsers = files.map(file => __classPrivateFieldGet(this, _SetCollection_instances, "m", _SetCollection_getBrowsersForFile).call(this, file)); + return _.zipObject(files, browsers); + } + getAllFiles() { + return _.uniq(__classPrivateFieldGet(this, _SetCollection_instances, "m", _SetCollection_getFromSets).call(this, set => set.getFiles())); + } + groupByBrowser() { + const browsers = __classPrivateFieldGet(this, _SetCollection_instances, "m", _SetCollection_getBrowsers).call(this); + const files = browsers.map(browser => __classPrivateFieldGet(this, _SetCollection_instances, "m", _SetCollection_getFilesForBrowser).call(this, browser)); + return _.zipObject(browsers, files); + } + }, + _SetCollection_sets = new WeakMap(), + _SetCollection_instances = new WeakSet(), + _SetCollection_getBrowsersForFile = function _SetCollection_getBrowsersForFile(path) { + return __classPrivateFieldGet(this, _SetCollection_instances, "m", _SetCollection_getFromSets).call(this, set => set.getBrowsersForFile(path)); + }, + _SetCollection_getBrowsers = function _SetCollection_getBrowsers() { + return __classPrivateFieldGet(this, _SetCollection_instances, "m", _SetCollection_getFromSets).call(this, set => set.getBrowsers()); + }, + _SetCollection_getFilesForBrowser = function _SetCollection_getFilesForBrowser(browser) { + return __classPrivateFieldGet(this, _SetCollection_instances, "m", _SetCollection_getFromSets).call(this, set => set.getFilesForBrowser(browser)); + }, + _SetCollection_getFromSets = function _SetCollection_getFromSets(cb) { + return _(__classPrivateFieldGet(this, _SetCollection_sets, "f")).map(cb).flatten().uniq().value(); + }, + _a); +//# sourceMappingURL=set-collection.js.map \ No newline at end of file diff --git a/build/src/test-reader/sets-builder/set-collection.js.map b/build/src/test-reader/sets-builder/set-collection.js.map new file mode 100644 index 000000000..bafadf9c4 --- /dev/null +++ b/build/src/test-reader/sets-builder/set-collection.js.map @@ -0,0 +1 @@ +{"version":3,"file":"set-collection.js","sourceRoot":"","sources":["../../../../src/test-reader/sets-builder/set-collection.js"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE5B,MAAM,CAAC,OAAO,SAAG,MAAM,aAAa;QAGhC,MAAM,CAAC,MAAM,CAAC,IAAI;YACd,OAAO,IAAI,EAAa,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;QAED,YAAY,IAAI;;YANhB,sCAAM;YAOF,uBAAA,IAAI,uBAAS,IAAI,MAAA,CAAC;QACtB,CAAC;QAED,WAAW;YACP,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,uBAAA,IAAI,mEAAoB,MAAxB,IAAI,EAAqB,IAAI,CAAC,CAAC,CAAC;YAEnE,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACxC,CAAC;QAED,WAAW;YACP,OAAO,CAAC,CAAC,IAAI,CAAC,uBAAA,IAAI,4DAAa,MAAjB,IAAI,EAAc,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC5D,CAAC;QAMD,cAAc;YACV,MAAM,QAAQ,GAAG,uBAAA,IAAI,4DAAa,MAAjB,IAAI,CAAe,CAAC;YACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,uBAAA,IAAI,mEAAoB,MAAxB,IAAI,EAAqB,OAAO,CAAC,CAAC,CAAC;YAEzE,OAAO,CAAC,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACxC,CAAC;KAaJ;;;mFAtBuB,IAAI;QACpB,OAAO,uBAAA,IAAI,4DAAa,MAAjB,IAAI,EAAc,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;IAClE,CAAC;;QAUG,OAAO,uBAAA,IAAI,4DAAa,MAAjB,IAAI,EAAc,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;IACvD,CAAC;mFAEmB,OAAO;QACvB,OAAO,uBAAA,IAAI,4DAAa,MAAjB,IAAI,EAAc,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,CAAC;qEAEY,EAAE;QACX,OAAO,CAAC,CAAC,uBAAA,IAAI,2BAAM,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;IAC1D,CAAC;OACJ,CAAC"} \ No newline at end of file diff --git a/build/src/test-reader/sets-builder/test-set.d.ts b/build/src/test-reader/sets-builder/test-set.d.ts new file mode 100644 index 000000000..82e75cdda --- /dev/null +++ b/build/src/test-reader/sets-builder/test-set.d.ts @@ -0,0 +1,16 @@ +export = TestSet; +declare class TestSet { + static create(set: any): import("./test-set"); + constructor(set: any); + expandFiles(expandOpts: any, globOpts?: {}): globalThis.Promise; + transformDirsToMasks(): Promise; + resolveFiles(projectRoot: any): void; + getFiles(): any; + getBrowsers(): any; + getFilesForBrowser(browser: any): any; + getBrowsersForFile(file: any): any; + useFiles(files: any): void; + useBrowsers(browsers: any): void; + #private; +} +import Promise = require("bluebird"); diff --git a/build/src/test-reader/sets-builder/test-set.js b/build/src/test-reader/sets-builder/test-set.js new file mode 100644 index 000000000..515ffc7f1 --- /dev/null +++ b/build/src/test-reader/sets-builder/test-set.js @@ -0,0 +1,74 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _TestSet_set, _a; +const globExtra = require("glob-extra"); +const _ = require("lodash"); +const mm = require("micromatch"); +const path = require("path"); +const Promise = require("bluebird"); +const fs = Promise.promisifyAll(require("fs")); +module.exports = (_a = class TestSet { + static create(set) { + return new _a(set); + } + constructor(set) { + _TestSet_set.set(this, void 0); + __classPrivateFieldSet(this, _TestSet_set, _.clone(set), "f"); + } + expandFiles(expandOpts, globOpts = {}) { + const { files, ignoreFiles = [] } = __classPrivateFieldGet(this, _TestSet_set, "f"); + globOpts = _.clone(globOpts); + globOpts.ignore = [].concat(globOpts.ignore || [], ignoreFiles).map(p => path.resolve(expandOpts.root, p)); + return globExtra + .expandPaths(files, expandOpts, globOpts) + .then(expandedFiles => (__classPrivateFieldSet(this, _TestSet_set, _.extend(__classPrivateFieldGet(this, _TestSet_set, "f"), { files: expandedFiles }), "f"))); + } + transformDirsToMasks() { + return Promise.map(__classPrivateFieldGet(this, _TestSet_set, "f").files, file => { + if (globExtra.isMask(file)) { + return file; + } + return fs + .statAsync(file) + .then(stat => (stat.isDirectory() ? path.join(file, "**") : file)) + .catch(() => Promise.reject(new Error(`Cannot read such file or directory: '${file}'`))); + }).then(files => (__classPrivateFieldGet(this, _TestSet_set, "f").files = files)); + } + resolveFiles(projectRoot) { + __classPrivateFieldGet(this, _TestSet_set, "f").files = __classPrivateFieldGet(this, _TestSet_set, "f").files.map(file => path.resolve(projectRoot, file)); + } + getFiles() { + return __classPrivateFieldGet(this, _TestSet_set, "f").files; + } + getBrowsers() { + return __classPrivateFieldGet(this, _TestSet_set, "f").browsers; + } + getFilesForBrowser(browser) { + return _.includes(__classPrivateFieldGet(this, _TestSet_set, "f").browsers, browser) ? __classPrivateFieldGet(this, _TestSet_set, "f").files : []; + } + getBrowsersForFile(file) { + return _.includes(__classPrivateFieldGet(this, _TestSet_set, "f").files, file) ? __classPrivateFieldGet(this, _TestSet_set, "f").browsers : []; + } + useFiles(files) { + if (_.isEmpty(files)) { + return; + } + __classPrivateFieldGet(this, _TestSet_set, "f").files = _.isEmpty(__classPrivateFieldGet(this, _TestSet_set, "f").files) ? files : mm(files, __classPrivateFieldGet(this, _TestSet_set, "f").files); + } + useBrowsers(browsers) { + __classPrivateFieldGet(this, _TestSet_set, "f").browsers = _.isEmpty(browsers) ? __classPrivateFieldGet(this, _TestSet_set, "f").browsers : _.intersection(__classPrivateFieldGet(this, _TestSet_set, "f").browsers, browsers); + } + }, + _TestSet_set = new WeakMap(), + _a); +//# sourceMappingURL=test-set.js.map \ No newline at end of file diff --git a/build/src/test-reader/sets-builder/test-set.js.map b/build/src/test-reader/sets-builder/test-set.js.map new file mode 100644 index 000000000..109411438 --- /dev/null +++ b/build/src/test-reader/sets-builder/test-set.js.map @@ -0,0 +1 @@ +{"version":3,"file":"test-set.js","sourceRoot":"","sources":["../../../../src/test-reader/sets-builder/test-set.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/test-reader/test-object/configurable-test-object.d.ts b/build/src/test-reader/test-object/configurable-test-object.d.ts new file mode 100644 index 000000000..83759cc67 --- /dev/null +++ b/build/src/test-reader/test-object/configurable-test-object.d.ts @@ -0,0 +1,30 @@ +export class ConfigurableTestObject extends TestObject { + constructor({ title, file, id }: { + title: any; + file: any; + id: any; + }); + skip({ reason }: { + reason: any; + }): void; + set pending(val: any); + get pending(): any; + set skipReason(reason: any); + get skipReason(): any; + disable(): void; + set disabled(val: any); + get disabled(): any; + set silentSkip(val: any); + get silentSkip(): any; + get id(): any; + get file(): any; + set timeout(timeout: any); + get timeout(): any; + set browserId(id: any); + get browserId(): any; + set browserVersion(version: any); + get browserVersion(): any; + get hasBrowserVersionOverwritten(): boolean; + #private; +} +import { TestObject } from "./test-object"; diff --git a/build/src/test-reader/test-object/configurable-test-object.js b/build/src/test-reader/test-object/configurable-test-object.js new file mode 100644 index 000000000..d7ad28c22 --- /dev/null +++ b/build/src/test-reader/test-object/configurable-test-object.js @@ -0,0 +1,93 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _ConfigurableTestObject_instances, _ConfigurableTestObject_data, _ConfigurableTestObject_getInheritedProperty; +const { TestObject } = require("./test-object"); +const _ = require("lodash"); +class ConfigurableTestObject extends TestObject { + constructor({ title, file, id }) { + super({ title }); + _ConfigurableTestObject_instances.add(this); + _ConfigurableTestObject_data.set(this, void 0); + __classPrivateFieldSet(this, _ConfigurableTestObject_data, { id, file }, "f"); + } + assign(src) { + __classPrivateFieldSet(this, _ConfigurableTestObject_data, { ...__classPrivateFieldGet(src, _ConfigurableTestObject_data, "f") }, "f"); + return super.assign(src); + } + skip({ reason }) { + this.pending = true; + this.skipReason = reason; + } + disable() { + this.disabled = true; + this.silentSkip = true; + } + get id() { + return __classPrivateFieldGet(this, _ConfigurableTestObject_data, "f").id; + } + get file() { + return __classPrivateFieldGet(this, _ConfigurableTestObject_data, "f").file; + } + set pending(val) { + __classPrivateFieldGet(this, _ConfigurableTestObject_data, "f").pending = val; + } + get pending() { + return __classPrivateFieldGet(this, _ConfigurableTestObject_instances, "m", _ConfigurableTestObject_getInheritedProperty).call(this, "pending", false); + } + set skipReason(reason) { + __classPrivateFieldGet(this, _ConfigurableTestObject_data, "f").skipReason = reason; + } + get skipReason() { + return __classPrivateFieldGet(this, _ConfigurableTestObject_instances, "m", _ConfigurableTestObject_getInheritedProperty).call(this, "skipReason", ""); + } + set disabled(val) { + __classPrivateFieldGet(this, _ConfigurableTestObject_data, "f").disabled = val; + } + get disabled() { + return __classPrivateFieldGet(this, _ConfigurableTestObject_instances, "m", _ConfigurableTestObject_getInheritedProperty).call(this, "disabled", false); + } + set silentSkip(val) { + __classPrivateFieldGet(this, _ConfigurableTestObject_data, "f").silentSkip = val; + } + get silentSkip() { + return __classPrivateFieldGet(this, _ConfigurableTestObject_instances, "m", _ConfigurableTestObject_getInheritedProperty).call(this, "silentSkip", false); + } + set timeout(timeout) { + __classPrivateFieldGet(this, _ConfigurableTestObject_data, "f").timeout = timeout; + } + get timeout() { + return __classPrivateFieldGet(this, _ConfigurableTestObject_instances, "m", _ConfigurableTestObject_getInheritedProperty).call(this, "timeout", 0); + } + set browserId(id) { + __classPrivateFieldGet(this, _ConfigurableTestObject_data, "f").browserId = id; + } + get browserId() { + return __classPrivateFieldGet(this, _ConfigurableTestObject_instances, "m", _ConfigurableTestObject_getInheritedProperty).call(this, "browserId", undefined); + } + set browserVersion(version) { + __classPrivateFieldGet(this, _ConfigurableTestObject_data, "f").browserVersion = version; + } + get browserVersion() { + return __classPrivateFieldGet(this, _ConfigurableTestObject_instances, "m", _ConfigurableTestObject_getInheritedProperty).call(this, "browserVersion", undefined); + } + get hasBrowserVersionOverwritten() { + return "browserVersion" in __classPrivateFieldGet(this, _ConfigurableTestObject_data, "f"); + } +} +_ConfigurableTestObject_data = new WeakMap(), _ConfigurableTestObject_instances = new WeakSet(), _ConfigurableTestObject_getInheritedProperty = function _ConfigurableTestObject_getInheritedProperty(name, defaultValue) { + return name in __classPrivateFieldGet(this, _ConfigurableTestObject_data, "f") ? __classPrivateFieldGet(this, _ConfigurableTestObject_data, "f")[name] : _.get(this.parent, name, defaultValue); +}; +module.exports = { + ConfigurableTestObject, +}; +//# sourceMappingURL=configurable-test-object.js.map \ No newline at end of file diff --git a/build/src/test-reader/test-object/configurable-test-object.js.map b/build/src/test-reader/test-object/configurable-test-object.js.map new file mode 100644 index 000000000..b63dfbcc7 --- /dev/null +++ b/build/src/test-reader/test-object/configurable-test-object.js.map @@ -0,0 +1 @@ +{"version":3,"file":"configurable-test-object.js","sourceRoot":"","sources":["../../../../src/test-reader/test-object/configurable-test-object.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/test-reader/test-object/hook.d.ts b/build/src/test-reader/test-object/hook.d.ts new file mode 100644 index 000000000..add5a52e9 --- /dev/null +++ b/build/src/test-reader/test-object/hook.d.ts @@ -0,0 +1,12 @@ +export class Hook extends TestObject { + constructor({ title, fn }: { + title: any; + fn: any; + }); + fn: any; + clone(): any; + get file(): any; + get timeout(): any; + get browserId(): any; +} +import { TestObject } from "./test-object"; diff --git a/build/src/test-reader/test-object/hook.js b/build/src/test-reader/test-object/hook.js new file mode 100644 index 000000000..8e44b2609 --- /dev/null +++ b/build/src/test-reader/test-object/hook.js @@ -0,0 +1,27 @@ +"use strict"; +const { TestObject } = require("./test-object"); +class Hook extends TestObject { + constructor({ title, fn }) { + super({ title }); + this.fn = fn; + } + clone() { + return new Hook({ + title: this.title, + fn: this.fn, + }).assign(this); + } + get file() { + return this.parent.file; + } + get timeout() { + return this.parent.timeout; + } + get browserId() { + return this.parent.browserId; + } +} +module.exports = { + Hook, +}; +//# sourceMappingURL=hook.js.map \ No newline at end of file diff --git a/build/src/test-reader/test-object/hook.js.map b/build/src/test-reader/test-object/hook.js.map new file mode 100644 index 000000000..7809621f4 --- /dev/null +++ b/build/src/test-reader/test-object/hook.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hook.js","sourceRoot":"","sources":["../../../../src/test-reader/test-object/hook.js"],"names":[],"mappings":";AAAA,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;AAEhD,MAAM,IAAK,SAAQ,UAAU;IACzB,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE;QACrB,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAEjB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACjB,CAAC;IAED,KAAK;QACD,OAAO,IAAI,IAAI,CAAC;YACZ,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,EAAE,EAAE,IAAI,CAAC,EAAE;SACd,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IAED,IAAI,IAAI;QACJ,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IAC5B,CAAC;IAED,IAAI,OAAO;QACP,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;IAC/B,CAAC;IAED,IAAI,SAAS;QACT,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;IACjC,CAAC;CACJ;AAED,MAAM,CAAC,OAAO,GAAG;IACb,IAAI;CACP,CAAC"} \ No newline at end of file diff --git a/build/src/test-reader/test-object/index.d.ts b/build/src/test-reader/test-object/index.d.ts new file mode 100644 index 000000000..073d78ec2 --- /dev/null +++ b/build/src/test-reader/test-object/index.d.ts @@ -0,0 +1,4 @@ +import { Suite } from "./suite"; +import { Test } from "./test"; +import { Hook } from "./hook"; +export { Suite, Test, Hook }; diff --git a/build/src/test-reader/test-object/index.js b/build/src/test-reader/test-object/index.js new file mode 100644 index 000000000..7231fe557 --- /dev/null +++ b/build/src/test-reader/test-object/index.js @@ -0,0 +1,10 @@ +"use strict"; +const { Suite } = require("./suite"); +const { Test } = require("./test"); +const { Hook } = require("./hook"); +module.exports = { + Suite, + Test, + Hook, +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/test-reader/test-object/index.js.map b/build/src/test-reader/test-object/index.js.map new file mode 100644 index 000000000..408efb5b4 --- /dev/null +++ b/build/src/test-reader/test-object/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/test-reader/test-object/index.js"],"names":[],"mappings":";AAAA,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AACrC,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AACnC,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEnC,MAAM,CAAC,OAAO,GAAG;IACb,KAAK;IACL,IAAI;IACJ,IAAI;CACP,CAAC"} \ No newline at end of file diff --git a/build/src/test-reader/test-object/suite.d.ts b/build/src/test-reader/test-object/suite.d.ts new file mode 100644 index 000000000..b207f0881 --- /dev/null +++ b/build/src/test-reader/test-object/suite.d.ts @@ -0,0 +1,23 @@ +export class Suite extends ConfigurableTestObject { + constructor({ title, file, id }?: { + title: any; + file: any; + id: any; + }); + addSuite(suite: any): this; + addTest(test: any): this; + addBeforeEachHook(hook: any): this; + addAfterEachHook(hook: any): this; + beforeEach(fn: any): this; + afterEach(fn: any): this; + eachTest(cb: any): void; + getTests(): any[]; + filterTests(cb: any): this; + get root(): boolean; + get suites(): any[]; + get tests(): any[]; + get beforeEachHooks(): any[]; + get afterEachHooks(): any[]; + #private; +} +import { ConfigurableTestObject } from "./configurable-test-object"; diff --git a/build/src/test-reader/test-object/suite.js b/build/src/test-reader/test-object/suite.js new file mode 100644 index 000000000..246396e71 --- /dev/null +++ b/build/src/test-reader/test-object/suite.js @@ -0,0 +1,86 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _Suite_instances, _Suite_suites, _Suite_tests, _Suite_beforeEachHooks, _Suite_afterEachHooks, _Suite_addChild; +const { ConfigurableTestObject } = require("./configurable-test-object"); +const { Hook } = require("./hook"); +const _ = require("lodash"); +class Suite extends ConfigurableTestObject { + constructor({ title, file, id } = {}) { + super({ title, file, id }); + _Suite_instances.add(this); + _Suite_suites.set(this, void 0); + _Suite_tests.set(this, void 0); + _Suite_beforeEachHooks.set(this, void 0); + _Suite_afterEachHooks.set(this, void 0); + __classPrivateFieldSet(this, _Suite_suites, [], "f"); + __classPrivateFieldSet(this, _Suite_tests, [], "f"); + __classPrivateFieldSet(this, _Suite_beforeEachHooks, [], "f"); + __classPrivateFieldSet(this, _Suite_afterEachHooks, [], "f"); + } + addSuite(suite) { + return __classPrivateFieldGet(this, _Suite_instances, "m", _Suite_addChild).call(this, suite, __classPrivateFieldGet(this, _Suite_suites, "f")); + } + addTest(test) { + return __classPrivateFieldGet(this, _Suite_instances, "m", _Suite_addChild).call(this, test, __classPrivateFieldGet(this, _Suite_tests, "f")); + } + addBeforeEachHook(hook) { + return __classPrivateFieldGet(this, _Suite_instances, "m", _Suite_addChild).call(this, hook, __classPrivateFieldGet(this, _Suite_beforeEachHooks, "f")); + } + addAfterEachHook(hook) { + return __classPrivateFieldGet(this, _Suite_instances, "m", _Suite_addChild).call(this, hook, __classPrivateFieldGet(this, _Suite_afterEachHooks, "f")); + } + beforeEach(fn) { + return this.addBeforeEachHook(Hook.create({ title: '"before each" hook', fn })); + } + afterEach(fn) { + return this.addAfterEachHook(Hook.create({ title: '"after each" hook', fn })); + } + eachTest(cb) { + __classPrivateFieldGet(this, _Suite_tests, "f").forEach(t => cb(t)); + __classPrivateFieldGet(this, _Suite_suites, "f").forEach(s => s.eachTest(cb)); + } + getTests() { + return __classPrivateFieldGet(this, _Suite_tests, "f").concat(_.flatten(__classPrivateFieldGet(this, _Suite_suites, "f").map(s => s.getTests()))); + } + // Modifies tree + filterTests(cb) { + __classPrivateFieldSet(this, _Suite_tests, __classPrivateFieldGet(this, _Suite_tests, "f").filter(cb), "f"); + __classPrivateFieldGet(this, _Suite_suites, "f").forEach(s => s.filterTests(cb)); + __classPrivateFieldSet(this, _Suite_suites, __classPrivateFieldGet(this, _Suite_suites, "f").filter(s => s.getTests().length !== 0), "f"); + return this; + } + get root() { + return this.parent === null; + } + get suites() { + return __classPrivateFieldGet(this, _Suite_suites, "f"); + } + get tests() { + return __classPrivateFieldGet(this, _Suite_tests, "f"); + } + get beforeEachHooks() { + return __classPrivateFieldGet(this, _Suite_beforeEachHooks, "f"); + } + get afterEachHooks() { + return __classPrivateFieldGet(this, _Suite_afterEachHooks, "f"); + } +} +_Suite_suites = new WeakMap(), _Suite_tests = new WeakMap(), _Suite_beforeEachHooks = new WeakMap(), _Suite_afterEachHooks = new WeakMap(), _Suite_instances = new WeakSet(), _Suite_addChild = function _Suite_addChild(child, storage) { + child.parent = this; + storage.push(child); + return this; +}; +module.exports = { + Suite, +}; +//# sourceMappingURL=suite.js.map \ No newline at end of file diff --git a/build/src/test-reader/test-object/suite.js.map b/build/src/test-reader/test-object/suite.js.map new file mode 100644 index 000000000..b624c2188 --- /dev/null +++ b/build/src/test-reader/test-object/suite.js.map @@ -0,0 +1 @@ +{"version":3,"file":"suite.js","sourceRoot":"","sources":["../../../../src/test-reader/test-object/suite.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/test-reader/test-object/test-object.d.ts b/build/src/test-reader/test-object/test-object.d.ts new file mode 100644 index 000000000..ed18e1c3a --- /dev/null +++ b/build/src/test-reader/test-object/test-object.d.ts @@ -0,0 +1,11 @@ +export class TestObject { + static create(...args: any[]): TestObject; + constructor({ title }: { + title: any; + }); + parent: any; + assign(src: any): any; + get title(): any; + fullTitle(): string; + #private; +} diff --git a/build/src/test-reader/test-object/test-object.js b/build/src/test-reader/test-object/test-object.js new file mode 100644 index 000000000..465346bba --- /dev/null +++ b/build/src/test-reader/test-object/test-object.js @@ -0,0 +1,37 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _TestObject_title; +class TestObject { + static create(...args) { + return new this(...args); + } + constructor({ title }) { + _TestObject_title.set(this, void 0); + this.parent = null; + __classPrivateFieldSet(this, _TestObject_title, title, "f"); + } + assign(src) { + return Object.assign(this, src); + } + get title() { + return __classPrivateFieldGet(this, _TestObject_title, "f"); + } + fullTitle() { + return `${(this.parent && this.parent.fullTitle()) || ""} ${this.title || ""}`.trim(); + } +} +_TestObject_title = new WeakMap(); +module.exports = { + TestObject, +}; +//# sourceMappingURL=test-object.js.map \ No newline at end of file diff --git a/build/src/test-reader/test-object/test-object.js.map b/build/src/test-reader/test-object/test-object.js.map new file mode 100644 index 000000000..4f6c2e951 --- /dev/null +++ b/build/src/test-reader/test-object/test-object.js.map @@ -0,0 +1 @@ +{"version":3,"file":"test-object.js","sourceRoot":"","sources":["../../../../src/test-reader/test-object/test-object.js"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,MAAM,UAAU;IAGZ,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI;QACjB,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,YAAY,EAAE,KAAK,EAAE;QANrB,oCAAO;QAOH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAEnB,uBAAA,IAAI,qBAAU,KAAK,MAAA,CAAC;IACxB,CAAC;IAED,MAAM,CAAC,GAAG;QACN,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,KAAK;QACL,OAAO,uBAAA,IAAI,yBAAO,CAAC;IACvB,CAAC;IAED,SAAS;QACL,OAAO,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;IAC1F,CAAC;CACJ;;AAED,MAAM,CAAC,OAAO,GAAG;IACb,UAAU;CACb,CAAC"} \ No newline at end of file diff --git a/build/src/test-reader/test-object/test.d.ts b/build/src/test-reader/test-object/test.d.ts new file mode 100644 index 000000000..0d63c44f8 --- /dev/null +++ b/build/src/test-reader/test-object/test.d.ts @@ -0,0 +1,11 @@ +export class Test extends ConfigurableTestObject { + constructor({ title, file, id, fn }: { + title: any; + file: any; + id: any; + fn: any; + }); + fn: any; + clone(): any; +} +import { ConfigurableTestObject } from "./configurable-test-object"; diff --git a/build/src/test-reader/test-object/test.js b/build/src/test-reader/test-object/test.js new file mode 100644 index 000000000..a0d72030e --- /dev/null +++ b/build/src/test-reader/test-object/test.js @@ -0,0 +1,20 @@ +"use strict"; +const { ConfigurableTestObject } = require("./configurable-test-object"); +class Test extends ConfigurableTestObject { + constructor({ title, file, id, fn }) { + super({ title, file, id }); + this.fn = fn; + } + clone() { + return new Test({ + title: this.title, + file: this.file, + id: this.id, + fn: this.fn, + }).assign(this); + } +} +module.exports = { + Test, +}; +//# sourceMappingURL=test.js.map \ No newline at end of file diff --git a/build/src/test-reader/test-object/test.js.map b/build/src/test-reader/test-object/test.js.map new file mode 100644 index 000000000..b0ec462bb --- /dev/null +++ b/build/src/test-reader/test-object/test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"test.js","sourceRoot":"","sources":["../../../../src/test-reader/test-object/test.js"],"names":[],"mappings":";AAAA,MAAM,EAAE,sBAAsB,EAAE,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;AAEzE,MAAM,IAAK,SAAQ,sBAAsB;IACrC,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE;QAC/B,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAE3B,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACjB,CAAC;IAED,KAAK;QACD,OAAO,IAAI,IAAI,CAAC;YACZ,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,EAAE,EAAE,IAAI,CAAC,EAAE;SACd,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;CACJ;AAED,MAAM,CAAC,OAAO,GAAG;IACb,IAAI;CACP,CAAC"} \ No newline at end of file diff --git a/build/src/test-reader/test-parser-api.d.ts b/build/src/test-reader/test-parser-api.d.ts new file mode 100644 index 000000000..7595b30b6 --- /dev/null +++ b/build/src/test-reader/test-parser-api.d.ts @@ -0,0 +1,12 @@ +/// +import { EventEmitter } from "events"; +import { GlobalHelper } from "../types"; +type Context = GlobalHelper & Record>; +type Methods = Record unknown>; +export declare class TestParserAPI { + #private; + static create(this: new (ctx: Context, eventBus: EventEmitter) => T, ctx: Context, eventBus: EventEmitter): T; + constructor(ctx: Context, eventBus: EventEmitter); + setController(namespace: string, methods: Methods): void; +} +export {}; diff --git a/build/src/test-reader/test-parser-api.js b/build/src/test-reader/test-parser-api.js new file mode 100644 index 000000000..bb0ab8531 --- /dev/null +++ b/build/src/test-reader/test-parser-api.js @@ -0,0 +1,41 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _TestParserAPI_ctx, _TestParserAPI_eventBus; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TestParserAPI = void 0; +const events_1 = require("../events"); +class TestParserAPI { + static create(ctx, eventBus) { + return new this(ctx, eventBus); + } + constructor(ctx, eventBus) { + _TestParserAPI_ctx.set(this, void 0); + _TestParserAPI_eventBus.set(this, void 0); + __classPrivateFieldSet(this, _TestParserAPI_ctx, ctx, "f"); + __classPrivateFieldSet(this, _TestParserAPI_eventBus, eventBus, "f"); + } + setController(namespace, methods) { + __classPrivateFieldGet(this, _TestParserAPI_ctx, "f")[namespace] = {}; + Object.entries(methods).forEach(([cbName, cb]) => { + __classPrivateFieldGet(this, _TestParserAPI_ctx, "f")[namespace][cbName] = (...args) => { + __classPrivateFieldGet(this, _TestParserAPI_eventBus, "f").emit(events_1.TestReaderEvents.NEW_BUILD_INSTRUCTION, ({ treeBuilder }) => { + treeBuilder.addTrap((obj) => cb.call(obj, ...args)); + }); + return __classPrivateFieldGet(this, _TestParserAPI_ctx, "f")[namespace]; + }; + }); + } +} +exports.TestParserAPI = TestParserAPI; +_TestParserAPI_ctx = new WeakMap(), _TestParserAPI_eventBus = new WeakMap(); +//# sourceMappingURL=test-parser-api.js.map \ No newline at end of file diff --git a/build/src/test-reader/test-parser-api.js.map b/build/src/test-reader/test-parser-api.js.map new file mode 100644 index 000000000..16e2ed254 --- /dev/null +++ b/build/src/test-reader/test-parser-api.js.map @@ -0,0 +1 @@ +{"version":3,"file":"test-parser-api.js","sourceRoot":"","sources":["../../../src/test-reader/test-parser-api.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,sCAA6C;AAY7C,MAAa,aAAa;IAItB,MAAM,CAAC,MAAM,CAET,GAAY,EACZ,QAAsB;QAEtB,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED,YAAY,GAAY,EAAE,QAAsB;QAXhD,qCAAc;QACd,0CAAwB;QAWpB,uBAAA,IAAI,sBAAQ,GAAG,MAAA,CAAC;QAChB,uBAAA,IAAI,2BAAa,QAAQ,MAAA,CAAC;IAC9B,CAAC;IAED,aAAa,CAAC,SAAiB,EAAE,OAAgB;QAC7C,uBAAA,IAAI,0BAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;QAE1B,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE;YAC7C,uBAAA,IAAI,0BAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAe,EAA2B,EAAE;gBAC3E,uBAAA,IAAI,+BAAU,CAAC,IAAI,CAAC,yBAAgB,CAAC,qBAAqB,EAAE,CAAC,EAAE,WAAW,EAAqB,EAAE,EAAE;oBAC/F,WAAW,CAAC,OAAO,CAAC,CAAC,GAAY,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;gBACjE,CAAC,CAAC,CAAC;gBAEH,OAAO,uBAAA,IAAI,0BAAK,CAAC,SAAS,CAAC,CAAC;YAChC,CAAC,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC;CACJ;AA9BD,sCA8BC"} \ No newline at end of file diff --git a/build/src/test-reader/test-parser.d.ts b/build/src/test-reader/test-parser.d.ts new file mode 100644 index 000000000..3910a3a89 --- /dev/null +++ b/build/src/test-reader/test-parser.d.ts @@ -0,0 +1,11 @@ +export class TestParser extends EventEmitter { + constructor(); + loadFiles(files: any, config: any): Promise; + parse(files: any, { browserId, config, grep }: { + browserId: any; + config: any; + grep: any; + }): any; + #private; +} +import { EventEmitter } from "events"; diff --git a/build/src/test-reader/test-parser.js b/build/src/test-reader/test-parser.js new file mode 100644 index 000000000..77fd5286e --- /dev/null +++ b/build/src/test-reader/test-parser.js @@ -0,0 +1,112 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _TestParser_instances, _TestParser_buildInstructions, _TestParser_applyInstructionsEvents, _TestParser_passthroughFileEvents, _TestParser_clearRequireCache, _TestParser_validateUniqTitles; +const { EventEmitter } = require("events"); +const { InstructionsList, Instructions } = require("./build-instructions"); +const { SkipController } = require("./controllers/skip-controller"); +const { OnlyController } = require("./controllers/only-controller"); +const { ConfigController } = require("./controllers/config-controller"); +const browserVersionController = require("./controllers/browser-version-controller"); +const { TreeBuilder } = require("./tree-builder"); +const { readFiles } = require("./mocha-reader"); +const { TestReaderEvents } = require("../events"); +const { TestParserAPI } = require("./test-parser-api"); +const { MasterEvents } = require("../events"); +const _ = require("lodash"); +const clearRequire = require("clear-require"); +const path = require("path"); +class TestParser extends EventEmitter { + constructor() { + super(); + _TestParser_instances.add(this); + _TestParser_buildInstructions.set(this, void 0); + __classPrivateFieldSet(this, _TestParser_buildInstructions, new InstructionsList(), "f"); + } + async loadFiles(files, config) { + const eventBus = new EventEmitter(); + const { system: { ctx, mochaOpts }, } = config; + global.hermione = { + browser: browserVersionController.mkProvider(config.getBrowserIds(), eventBus), + config: ConfigController.create(eventBus), + ctx: _.clone(ctx), + only: OnlyController.create(eventBus), + skip: SkipController.create(eventBus), + }; + __classPrivateFieldGet(this, _TestParser_buildInstructions, "f") + .push(Instructions.extendWithBrowserId) + .push(Instructions.extendWithBrowserVersion) + .push(Instructions.extendWithTimeout) + .push(Instructions.buildGlobalSkipInstruction(config)); + __classPrivateFieldGet(this, _TestParser_instances, "m", _TestParser_applyInstructionsEvents).call(this, eventBus); + __classPrivateFieldGet(this, _TestParser_instances, "m", _TestParser_passthroughFileEvents).call(this, eventBus, global.hermione); + __classPrivateFieldGet(this, _TestParser_instances, "m", _TestParser_clearRequireCache).call(this, files); + const rand = Math.random(); + const esmDecorator = f => f + `?rand=${rand}`; + await readFiles(files, { esmDecorator, config: mochaOpts, eventBus }); + } + parse(files, { browserId, config, grep }) { + const treeBuilder = new TreeBuilder(); + __classPrivateFieldGet(this, _TestParser_buildInstructions, "f").exec(files, { treeBuilder, browserId, config }); + if (grep) { + treeBuilder.addTestFilter(test => grep.test(test.fullTitle())); + } + const rootSuite = treeBuilder.applyFilters().getRootSuite(); + const tests = rootSuite.getTests(); + __classPrivateFieldGet(this, _TestParser_instances, "m", _TestParser_validateUniqTitles).call(this, tests); + return tests; + } +} +_TestParser_buildInstructions = new WeakMap(), _TestParser_instances = new WeakSet(), _TestParser_applyInstructionsEvents = function _TestParser_applyInstructionsEvents(eventBus) { + let currentFile; + eventBus + .on(MasterEvents.BEFORE_FILE_READ, ({ file }) => (currentFile = file)) + .on(MasterEvents.AFTER_FILE_READ, () => (currentFile = undefined)) + .on(TestReaderEvents.NEW_BUILD_INSTRUCTION, instruction => __classPrivateFieldGet(this, _TestParser_buildInstructions, "f").push(instruction, currentFile)); +}, _TestParser_passthroughFileEvents = function _TestParser_passthroughFileEvents(eventBus, hermione) { + const passthroughEvent_ = (event, customOpts = {}) => { + eventBus.on(event, data => this.emit(event, { + ...data, + hermione, + ...customOpts, + })); + }; + passthroughEvent_(MasterEvents.BEFORE_FILE_READ, { testParser: TestParserAPI.create(hermione, eventBus) }); + passthroughEvent_(MasterEvents.AFTER_FILE_READ); +}, _TestParser_clearRequireCache = function _TestParser_clearRequireCache(files) { + files.forEach(filename => { + if (path.extname(filename) !== ".mjs") { + clearRequire(path.resolve(filename)); + } + }); +}, _TestParser_validateUniqTitles = function _TestParser_validateUniqTitles(tests) { + const titles = {}; + tests.forEach(test => { + const fullTitle = test.fullTitle(); + const relatePath = path.relative(process.cwd(), test.file); + if (!titles[fullTitle]) { + titles[fullTitle] = relatePath; + return; + } + if (titles[fullTitle] === relatePath) { + throw new Error(`Tests with the same title '${fullTitle}'` + ` in file '${titles[fullTitle]}' can't be used`); + } + else { + throw new Error(`Tests with the same title '${fullTitle}'` + + ` in files '${titles[fullTitle]}' and '${relatePath}' can't be used`); + } + }); +}; +module.exports = { + TestParser, +}; +//# sourceMappingURL=test-parser.js.map \ No newline at end of file diff --git a/build/src/test-reader/test-parser.js.map b/build/src/test-reader/test-parser.js.map new file mode 100644 index 000000000..f4e1e2f4c --- /dev/null +++ b/build/src/test-reader/test-parser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"test-parser.js","sourceRoot":"","sources":["../../../src/test-reader/test-parser.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/test-reader/tree-builder.d.ts b/build/src/test-reader/tree-builder.d.ts new file mode 100644 index 000000000..db294099a --- /dev/null +++ b/build/src/test-reader/tree-builder.d.ts @@ -0,0 +1,11 @@ +export class TreeBuilder { + addSuite(suite: any, parent?: null): this; + addTest(test: any, parent: any): this; + addBeforeEachHook(hook: any, parent: any): this; + addAfterEachHook(hook: any, parent: any): this; + addTrap(fn: any): this; + addTestFilter(fn: any): this; + applyFilters(): this; + getRootSuite(): any; + #private; +} diff --git a/build/src/test-reader/tree-builder.js b/build/src/test-reader/tree-builder.js new file mode 100644 index 000000000..ccd5d1fc7 --- /dev/null +++ b/build/src/test-reader/tree-builder.js @@ -0,0 +1,74 @@ +"use strict"; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _TreeBuilder_instances, _TreeBuilder_traps, _TreeBuilder_filters, _TreeBuilder_rootSuite, _TreeBuilder_applyTraps; +class TreeBuilder { + constructor() { + _TreeBuilder_instances.add(this); + _TreeBuilder_traps.set(this, void 0); + _TreeBuilder_filters.set(this, void 0); + _TreeBuilder_rootSuite.set(this, void 0); + __classPrivateFieldSet(this, _TreeBuilder_traps, [], "f"); + __classPrivateFieldSet(this, _TreeBuilder_filters, [], "f"); + __classPrivateFieldSet(this, _TreeBuilder_rootSuite, null, "f"); + } + addSuite(suite, parent = null) { + if (!__classPrivateFieldGet(this, _TreeBuilder_rootSuite, "f")) { + __classPrivateFieldSet(this, _TreeBuilder_rootSuite, suite, "f"); + } + if (parent) { + parent.addSuite(suite); + } + __classPrivateFieldGet(this, _TreeBuilder_instances, "m", _TreeBuilder_applyTraps).call(this, suite); + return this; + } + addTest(test, parent) { + parent.addTest(test); + __classPrivateFieldGet(this, _TreeBuilder_instances, "m", _TreeBuilder_applyTraps).call(this, test); + return this; + } + addBeforeEachHook(hook, parent) { + parent.addBeforeEachHook(hook); + return this; + } + addAfterEachHook(hook, parent) { + parent.addAfterEachHook(hook); + return this; + } + addTrap(fn) { + __classPrivateFieldGet(this, _TreeBuilder_traps, "f").push(fn); + return this; + } + addTestFilter(fn) { + __classPrivateFieldGet(this, _TreeBuilder_filters, "f").push(fn); + return this; + } + applyFilters() { + if (__classPrivateFieldGet(this, _TreeBuilder_rootSuite, "f") && __classPrivateFieldGet(this, _TreeBuilder_filters, "f").length !== 0) { + __classPrivateFieldGet(this, _TreeBuilder_rootSuite, "f").filterTests(test => { + return __classPrivateFieldGet(this, _TreeBuilder_filters, "f").every(f => f(test)); + }); + } + return this; + } + getRootSuite() { + return __classPrivateFieldGet(this, _TreeBuilder_rootSuite, "f"); + } +} +_TreeBuilder_traps = new WeakMap(), _TreeBuilder_filters = new WeakMap(), _TreeBuilder_rootSuite = new WeakMap(), _TreeBuilder_instances = new WeakSet(), _TreeBuilder_applyTraps = function _TreeBuilder_applyTraps(obj) { + __classPrivateFieldGet(this, _TreeBuilder_traps, "f").forEach(trap => trap(obj)); + __classPrivateFieldSet(this, _TreeBuilder_traps, [], "f"); +}; +module.exports = { + TreeBuilder, +}; +//# sourceMappingURL=tree-builder.js.map \ No newline at end of file diff --git a/build/src/test-reader/tree-builder.js.map b/build/src/test-reader/tree-builder.js.map new file mode 100644 index 000000000..2838a4eb4 --- /dev/null +++ b/build/src/test-reader/tree-builder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tree-builder.js","sourceRoot":"","sources":["../../../src/test-reader/tree-builder.js"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,MAAM,WAAW;IAKb;;QAJA,qCAAO;QACP,uCAAS;QACT,yCAAW;QAGP,uBAAA,IAAI,sBAAU,EAAE,MAAA,CAAC;QACjB,uBAAA,IAAI,wBAAY,EAAE,MAAA,CAAC;QAEnB,uBAAA,IAAI,0BAAc,IAAI,MAAA,CAAC;IAC3B,CAAC;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;QACzB,IAAI,CAAC,uBAAA,IAAI,8BAAW,EAAE,CAAC;YACnB,uBAAA,IAAI,0BAAc,KAAK,MAAA,CAAC;QAC5B,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACT,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QAED,uBAAA,IAAI,uDAAY,MAAhB,IAAI,EAAa,KAAK,CAAC,CAAC;QAExB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,OAAO,CAAC,IAAI,EAAE,MAAM;QAChB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACrB,uBAAA,IAAI,uDAAY,MAAhB,IAAI,EAAa,IAAI,CAAC,CAAC;QAEvB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,iBAAiB,CAAC,IAAI,EAAE,MAAM;QAC1B,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAE/B,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,gBAAgB,CAAC,IAAI,EAAE,MAAM;QACzB,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE9B,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,OAAO,CAAC,EAAE;QACN,uBAAA,IAAI,0BAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAErB,OAAO,IAAI,CAAC;IAChB,CAAC;IAOD,aAAa,CAAC,EAAE;QACZ,uBAAA,IAAI,4BAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEvB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,YAAY;QACR,IAAI,uBAAA,IAAI,8BAAW,IAAI,uBAAA,IAAI,4BAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChD,uBAAA,IAAI,8BAAW,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE;gBAC/B,OAAO,uBAAA,IAAI,4BAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7C,CAAC,CAAC,CAAC;QACP,CAAC;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,YAAY;QACR,OAAO,uBAAA,IAAI,8BAAW,CAAC;IAC3B,CAAC;CACJ;qNAxBe,GAAG;IACX,uBAAA,IAAI,0BAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACvC,uBAAA,IAAI,sBAAU,EAAE,MAAA,CAAC;AACrB,CAAC;AAuBL,MAAM,CAAC,OAAO,GAAG;IACb,WAAW;CACd,CAAC"} \ No newline at end of file diff --git a/build/src/types/index.d.ts b/build/src/types/index.d.ts new file mode 100644 index 000000000..7a5b1d1e2 --- /dev/null +++ b/build/src/types/index.d.ts @@ -0,0 +1,173 @@ +/// +import type { Browser } from "webdriverio"; +import { Events } from "../events"; +import { MainRunner } from "../runner"; +import { TestCollection } from "../test-collection"; +import type { Test } from "../test-reader/test-object/test"; +import type { Suite } from "../test-reader/test-object/suite"; +import type { TestParserAPI } from "../test-reader/test-parser-api"; +import { StatsResult } from "../stats"; +import { ConfigController } from "../test-reader/controllers/config-controller"; +import { OnlyController } from "../test-reader/controllers/only-controller"; +import { SkipController } from "../test-reader/controllers/skip-controller"; +import { BrowserVersionController } from "../test-reader/controllers/browser-version-controller"; +import { WorkerProcess } from "../utils/worker-process"; +import { BaseHermione } from "../base-hermione"; +import { CoordBounds, LooksSameOptions } from "looks-same"; +export { Suite as RunnerSuite, Test as RunnerTest, Hook as RunnerHook } from "mocha"; +export type { Browser as WdioBrowser } from "webdriverio"; +export type { Test } from "../test-reader/test-object/test"; +export type { Suite } from "../test-reader/test-object/suite"; +export interface RootSuite extends Suite { + root: true; +} +export interface BrowserInfo { + browserId: string; + sessionId: string; +} +export type AsyncSessionEventCallback = (browser: Browser, browserInfo: BrowserInfo) => Promise | void; +export interface ImageSize { + width: number; + height: number; +} +export interface ImageBase64 { + base64: string; + size: ImageSize; +} +export interface ErrorDetails { + title: string; + data?: unknown; + filePath: string; +} +export interface TestError extends Error { + screenshot?: ImageBase64; + details: ErrorDetails; +} +export interface ImageInfo { + path: string; + size: ImageSize; +} +export interface AssertViewResultSuccess { + refImg: ImageInfo; + stateName: string; +} +export interface DiffOptions extends LooksSameOptions { + current: string; + reference: string; + diffColor: string; +} +export interface AssertViewResultDiff { + currImg: ImageInfo; + diffBuffer?: ArrayBuffer; + diffClusters: CoordBounds[]; + diffOpts: DiffOptions; + message: string; + name: "ImageDiffError"; + refImg: ImageInfo; + stack: string; + stateName: string; +} +export interface AssertViewResultNoRefImage { + currImg: ImageInfo; + message: string; + name: "NoRefImageError"; + refImg: ImageInfo; + stack: string; + stateName: string; +} +export type AssertViewResult = AssertViewResultSuccess | AssertViewResultDiff | AssertViewResultNoRefImage; +export interface CommandHistory { + /** Name: command name */ + n: string; + /** Arguments: array of passed arguments */ + a: unknown[]; + /** Time start */ + ts: number; + /** Time end */ + te: number; + /** Duration */ + d: number; + /** Scope: scope of execution (browser or element) */ + s: "b" | "e"; + /** Children: array of children commands */ + c: CommandHistory[]; +} +export interface TestResult extends Test { + assertViewResults: Array; + description?: string; + duration: number; + err?: TestError; + hermioneCtx: { + assertViewResults: Array; + }; + history: CommandHistory; + meta: { + [name: string]: unknown; + }; + sessionId: string; + startTime: number; +} +export interface TestResultWithRetries extends TestResult { + retriesLeft: number; +} +export interface GlobalHelper { + ctx: Record; + skip: SkipController; + only: OnlyController; + browser: (browserName: string) => BrowserVersionController; + config: ConfigController; +} +export interface AfterFileReadData { + hermione: GlobalHelper; + browser: string; + file: string; +} +export interface BeforeFileReadData extends AfterFileReadData { + testParser: TestParserAPI; +} +export type SyncSessionEventCallback = (browser: Browser, browserInfo: { + browserId: string; + browserVersion: string; +}) => void; +export type MasterEventHandler = { + (event: Events["INIT"], callback: () => Promise | void): T; + (event: Events["RUNNER_START"], callback: (runner: MainRunner) => Promise | void): T; + (event: Events["RUNNER_END"], callback: (result: StatsResult) => Promise | void): T; + (event: Events["SESSION_START"], callback: AsyncSessionEventCallback): T; + (event: Events["SESSION_END"], callback: AsyncSessionEventCallback): T; + (event: Events["EXIT"], callback: () => Promise | void): T; + (event: Events["NEW_WORKER_PROCESS"], callback: (suite: WorkerProcess) => void): T; + (event: Events["SUITE_BEGIN"], callback: (suite: Suite) => void): T; + (event: Events["SUITE_END"], callback: (suite: Suite) => void): T; + (event: Events["TEST_BEGIN"], callback: (test: Test) => void): T; + (event: Events["TEST_END"], callback: (test: TestResult) => void): T; + (event: Events["TEST_PASS"], callback: (test: TestResult) => void): T; + (event: Events["TEST_FAIL"], callback: (test: TestResult) => void): T; + (event: Events["TEST_PENDING"], callback: (test: Test) => void): T; + (event: Events["RETRY"], callback: (test: TestResultWithRetries) => void): T; + (event: Events["CLI"], callback: (commander: commander.CommanderStatic) => void): T; + (event: Events["BEGIN"], callback: () => void): T; + (event: Events["END"], callback: () => void): T; + (event: Events["BEFORE_FILE_READ"], callback: (data: BeforeFileReadData) => void): T; + (event: Events["AFTER_FILE_READ"], callback: (data: AfterFileReadData) => void): T; + (event: Events["AFTER_TESTS_READ"], callback: (collection: TestCollection) => void): T; + (event: Events["INFO"], callback: () => void): T; + (event: Events["WARNING"], callback: () => void): T; + (event: Events["ERROR"], callback: (err: Error) => void): T; + (event: Events["UPDATE_REFERENCE"], callback: (data: { + state: string; + refImg: ImageInfo; + }) => void): T; + (event: Events["NEW_BROWSER"], callback: SyncSessionEventCallback): T; +}; +export type WorkerEventHandler = { + (event: Events["INIT"], callback: () => Promise | void): T; + (event: Events["BEFORE_FILE_READ"], callback: (data: BeforeFileReadData) => void): T; + (event: Events["AFTER_FILE_READ"], callback: (data: AfterFileReadData) => void): T; + (event: Events["AFTER_TESTS_READ"], callback: (collection: TestCollection) => void): T; + (event: Events["UPDATE_REFERENCE"], callback: (data: { + state: string; + refImg: ImageInfo; + }) => void): T; + (event: Events["NEW_BROWSER"], callback: SyncSessionEventCallback): T; +}; diff --git a/build/src/types/index.js b/build/src/types/index.js new file mode 100644 index 000000000..8b41bf31a --- /dev/null +++ b/build/src/types/index.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RunnerHook = exports.RunnerTest = exports.RunnerSuite = void 0; +var mocha_1 = require("mocha"); +Object.defineProperty(exports, "RunnerSuite", { enumerable: true, get: function () { return mocha_1.Suite; } }); +Object.defineProperty(exports, "RunnerTest", { enumerable: true, get: function () { return mocha_1.Test; } }); +Object.defineProperty(exports, "RunnerHook", { enumerable: true, get: function () { return mocha_1.Hook; } }); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/types/index.js.map b/build/src/types/index.js.map new file mode 100644 index 000000000..aa11d5d25 --- /dev/null +++ b/build/src/types/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":";;;AAgBA,+BAAqF;AAA5E,oGAAA,KAAK,OAAe;AAAE,mGAAA,IAAI,OAAc;AAAE,mGAAA,IAAI,OAAc"} \ No newline at end of file diff --git a/build/src/utils/browser.d.ts b/build/src/utils/browser.d.ts new file mode 100644 index 000000000..1f26285a0 --- /dev/null +++ b/build/src/utils/browser.d.ts @@ -0,0 +1 @@ +export declare const isSupportIsolation: (browserName: string, browserVersion?: string) => boolean; diff --git a/build/src/utils/browser.js b/build/src/utils/browser.js new file mode 100644 index 000000000..291a8162e --- /dev/null +++ b/build/src/utils/browser.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isSupportIsolation = void 0; +const browser_1 = require("../constants/browser"); +const isSupportIsolation = (browserName, browserVersion = "") => { + const browserVersionMajor = browserVersion.split(".")[0]; + return browserName === "chrome" && Number(browserVersionMajor) >= browser_1.MIN_CHROME_VERSION_SUPPORT_ISOLATION; +}; +exports.isSupportIsolation = isSupportIsolation; +//# sourceMappingURL=browser.js.map \ No newline at end of file diff --git a/build/src/utils/browser.js.map b/build/src/utils/browser.js.map new file mode 100644 index 000000000..4a2a12e45 --- /dev/null +++ b/build/src/utils/browser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../../src/utils/browser.ts"],"names":[],"mappings":";;;AAAA,kDAA4E;AAErE,MAAM,kBAAkB,GAAG,CAAC,WAAmB,EAAE,cAAc,GAAG,EAAE,EAAW,EAAE;IACpF,MAAM,mBAAmB,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzD,OAAO,WAAW,KAAK,QAAQ,IAAI,MAAM,CAAC,mBAAmB,CAAC,IAAI,8CAAoC,CAAC;AAC3G,CAAC,CAAC;AAJW,QAAA,kBAAkB,sBAI7B"} \ No newline at end of file diff --git a/build/src/utils/crypto.d.ts b/build/src/utils/crypto.d.ts new file mode 100644 index 000000000..36398d5f3 --- /dev/null +++ b/build/src/utils/crypto.d.ts @@ -0,0 +1 @@ +export function getShortMD5(str: any): string; diff --git a/build/src/utils/crypto.js b/build/src/utils/crypto.js new file mode 100644 index 000000000..2ced3ac1d --- /dev/null +++ b/build/src/utils/crypto.js @@ -0,0 +1,4 @@ +"use strict"; +const crypto = require("crypto"); +exports.getShortMD5 = str => crypto.createHash("md5").update(str, "ascii").digest("hex").substr(0, 7); +//# sourceMappingURL=crypto.js.map \ No newline at end of file diff --git a/build/src/utils/crypto.js.map b/build/src/utils/crypto.js.map new file mode 100644 index 000000000..a87bdcbdb --- /dev/null +++ b/build/src/utils/crypto.js.map @@ -0,0 +1 @@ +{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../../src/utils/crypto.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEjC,OAAO,CAAC,WAAW,GAAG,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/utils/env.d.ts b/build/src/utils/env.d.ts new file mode 100644 index 000000000..fe3543c99 --- /dev/null +++ b/build/src/utils/env.d.ts @@ -0,0 +1 @@ +export function parseCommaSeparatedValue(name: any): string[]; diff --git a/build/src/utils/env.js b/build/src/utils/env.js new file mode 100644 index 000000000..b875a16af --- /dev/null +++ b/build/src/utils/env.js @@ -0,0 +1,6 @@ +"use strict"; +exports.parseCommaSeparatedValue = name => { + const value = process.env[name]; + return value ? value.split(/, */) : []; +}; +//# sourceMappingURL=env.js.map \ No newline at end of file diff --git a/build/src/utils/env.js.map b/build/src/utils/env.js.map new file mode 100644 index 000000000..fd6e43273 --- /dev/null +++ b/build/src/utils/env.js.map @@ -0,0 +1 @@ +{"version":3,"file":"env.js","sourceRoot":"","sources":["../../../src/utils/env.js"],"names":[],"mappings":";AAAA,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC,EAAE;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAEhC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3C,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/utils/fs.d.ts b/build/src/utils/fs.d.ts new file mode 100644 index 000000000..904448990 --- /dev/null +++ b/build/src/utils/fs.d.ts @@ -0,0 +1 @@ +export declare const exists: (path: string) => Promise; diff --git a/build/src/utils/fs.js b/build/src/utils/fs.js new file mode 100644 index 000000000..254599a08 --- /dev/null +++ b/build/src/utils/fs.js @@ -0,0 +1,18 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.exists = void 0; +const fs_1 = __importDefault(require("fs")); +const exists = async (path) => { + try { + await fs_1.default.promises.access(path); + return true; + } + catch (_) { + return false; + } +}; +exports.exists = exists; +//# sourceMappingURL=fs.js.map \ No newline at end of file diff --git a/build/src/utils/fs.js.map b/build/src/utils/fs.js.map new file mode 100644 index 000000000..e5b5a16fc --- /dev/null +++ b/build/src/utils/fs.js.map @@ -0,0 +1 @@ +{"version":3,"file":"fs.js","sourceRoot":"","sources":["../../../src/utils/fs.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AAEb,MAAM,MAAM,GAAG,KAAK,EAAE,IAAY,EAAoB,EAAE;IAC3D,IAAI,CAAC;QACD,MAAM,YAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/B,OAAO,IAAI,CAAC;IAChB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC,CAAC;AAPW,QAAA,MAAM,UAOjB"} \ No newline at end of file diff --git a/build/src/utils/ipc.d.ts b/build/src/utils/ipc.d.ts new file mode 100644 index 000000000..b03eb9966 --- /dev/null +++ b/build/src/utils/ipc.d.ts @@ -0,0 +1,2 @@ +export function emit(event: any, data?: {}): boolean; +export function on(event: any, baseHandler: any): void; diff --git a/build/src/utils/ipc.js b/build/src/utils/ipc.js new file mode 100644 index 000000000..f80b1c281 --- /dev/null +++ b/build/src/utils/ipc.js @@ -0,0 +1,14 @@ +"use strict"; +const _ = require("lodash"); +module.exports = { + emit: (event, data = {}) => process.send({ event, ...data }), + on: (event, baseHandler) => { + process.on("message", (...args) => { + if (event !== _.get(args[0], "event")) { + return; + } + baseHandler(...args); + }); + }, +}; +//# sourceMappingURL=ipc.js.map \ No newline at end of file diff --git a/build/src/utils/ipc.js.map b/build/src/utils/ipc.js.map new file mode 100644 index 000000000..235032d99 --- /dev/null +++ b/build/src/utils/ipc.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ipc.js","sourceRoot":"","sources":["../../../src/utils/ipc.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE5B,MAAM,CAAC,OAAO,GAAG;IACb,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,CAAC;IAC5D,EAAE,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;QACvB,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE;YAC9B,IAAI,KAAK,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC;gBACpC,OAAO;YACX,CAAC;YAED,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACP,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/utils/logger.d.ts b/build/src/utils/logger.d.ts new file mode 100644 index 000000000..62259c317 --- /dev/null +++ b/build/src/utils/logger.d.ts @@ -0,0 +1,3 @@ +export function log(...args: any[]): void; +export function warn(...args: any[]): void; +export function error(...args: any[]): void; diff --git a/build/src/utils/logger.js b/build/src/utils/logger.js new file mode 100644 index 000000000..23a34883f --- /dev/null +++ b/build/src/utils/logger.js @@ -0,0 +1,12 @@ +"use strict"; +const { format } = require("date-fns"); +const withTimestampPrefix = logFnName => (...args) => { + const timestamp = format(new Date(), "HH:mm:ss OO"); + console[logFnName](`[${timestamp}]`, ...args); +}; +module.exports = { + log: withTimestampPrefix("log"), + warn: withTimestampPrefix("warn"), + error: withTimestampPrefix("error"), +}; +//# sourceMappingURL=logger.js.map \ No newline at end of file diff --git a/build/src/utils/logger.js.map b/build/src/utils/logger.js.map new file mode 100644 index 000000000..dc81ec6dc --- /dev/null +++ b/build/src/utils/logger.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/utils/logger.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEvC,MAAM,mBAAmB,GACrB,SAAS,CAAC,EAAE,CACZ,CAAC,GAAG,IAAI,EAAE,EAAE;IACR,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE,aAAa,CAAC,CAAC;IACpD,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,SAAS,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;AAClD,CAAC,CAAC;AAEN,MAAM,CAAC,OAAO,GAAG;IACb,GAAG,EAAE,mBAAmB,CAAC,KAAK,CAAC;IAC/B,IAAI,EAAE,mBAAmB,CAAC,MAAM,CAAC;IACjC,KAAK,EAAE,mBAAmB,CAAC,OAAO,CAAC;CACtC,CAAC"} \ No newline at end of file diff --git a/build/src/utils/module.d.ts b/build/src/utils/module.d.ts new file mode 100644 index 000000000..20dc3d902 --- /dev/null +++ b/build/src/utils/module.d.ts @@ -0,0 +1 @@ +export declare const requireModule: (modulePath: string) => Promise; diff --git a/build/src/utils/module.js b/build/src/utils/module.js new file mode 100644 index 000000000..72a796cc2 --- /dev/null +++ b/build/src/utils/module.js @@ -0,0 +1,14 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.requireModule = void 0; +const path_1 = __importDefault(require("path")); +const fs_1 = require("./fs"); +const requireModule = async (modulePath) => { + const isModuleLocal = await (0, fs_1.exists)(modulePath); + return require(isModuleLocal ? path_1.default.resolve(modulePath) : modulePath); +}; +exports.requireModule = requireModule; +//# sourceMappingURL=module.js.map \ No newline at end of file diff --git a/build/src/utils/module.js.map b/build/src/utils/module.js.map new file mode 100644 index 000000000..b8faf325a --- /dev/null +++ b/build/src/utils/module.js.map @@ -0,0 +1 @@ +{"version":3,"file":"module.js","sourceRoot":"","sources":["../../../src/utils/module.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,6BAA8B;AAEvB,MAAM,aAAa,GAAG,KAAK,EAAe,UAAkB,EAAc,EAAE;IAC/E,MAAM,aAAa,GAAG,MAAM,IAAA,WAAM,EAAC,UAAU,CAAC,CAAC;IAE/C,OAAO,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,cAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;AAC1E,CAAC,CAAC;AAJW,QAAA,aAAa,iBAIxB"} \ No newline at end of file diff --git a/build/src/utils/page-loader.d.ts b/build/src/utils/page-loader.d.ts new file mode 100644 index 000000000..2a7f73d25 --- /dev/null +++ b/build/src/utils/page-loader.d.ts @@ -0,0 +1,29 @@ +/// +import EventEmitter from "events"; +export interface PageLoaderOpts { + selectors: string[]; + predicate?: () => boolean | Promise; + timeout: number; + waitNetworkIdle: boolean; + waitNetworkIdleTimeout: number; +} +export default class PageLoader extends EventEmitter { + private session; + private mock?; + private selectors; + private predicate?; + private timeout; + private waitNetworkIdle; + private waitNetworkIdleTimeout; + private totalRequests; + private networkResolved; + constructor(session: WebdriverIO.Browser, { selectors, predicate, timeout, waitNetworkIdle, waitNetworkIdleTimeout }: PageLoaderOpts); + load(goToPage: () => Promise): Promise; + unsubscribe(): Promise | undefined; + private startAwaitingSelectorsWithTimeout; + private startAwaitingPredicateWithTimeout; + private startAwaitingNetworkIdleWithTimeout; + private initMock; + private isMatchError; + private markNetworkIdle; +} diff --git a/build/src/utils/page-loader.js b/build/src/utils/page-loader.js new file mode 100644 index 000000000..c25b63802 --- /dev/null +++ b/build/src/utils/page-loader.js @@ -0,0 +1,120 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const events_1 = __importDefault(require("events")); +const logger_1 = __importDefault(require("./logger")); +class PageLoader extends events_1.default { + constructor(session, { selectors, predicate, timeout, waitNetworkIdle, waitNetworkIdleTimeout }) { + super(); + this.totalRequests = 0; + this.networkResolved = false; + this.session = session; + this.selectors = selectors; + this.predicate = predicate; + this.timeout = timeout; + this.waitNetworkIdle = waitNetworkIdle; + this.waitNetworkIdleTimeout = waitNetworkIdleTimeout; + } + async load(goToPage) { + await this.initMock(); + await goToPage().catch(err => { + this.emit("pageLoadError", err); + }); + this.startAwaitingSelectorsWithTimeout(); + this.startAwaitingPredicateWithTimeout(); + this.startAwaitingNetworkIdleWithTimeout(); + } + unsubscribe() { + return this.mock?.restore().catch(() => { + logger_1.default.warn("PageLoader: Got error while unsubscribing"); + }); + } + startAwaitingSelectorsWithTimeout() { + const selectorPromises = this.selectors.map(async (selector) => { + const element = await this.session.$(selector); + await element.waitForExist({ timeout: this.timeout }); + }); + Promise.all(selectorPromises) + .then(() => { + this.emit("selectorsExist"); + }) + .catch(err => { + this.emit("selectorsError", err); + }); + } + startAwaitingPredicateWithTimeout() { + if (!this.predicate) { + return; + } + this.session + .waitUntil(this.predicate, { timeout: this.timeout }) + .then(() => { + this.emit("predicateResolved"); + }) + .catch(() => { + this.emit("predicateError", new Error(`predicate was never truthy in ${this.timeout}ms`)); + }); + } + startAwaitingNetworkIdleWithTimeout() { + if (!this.waitNetworkIdle) { + return; + } + setTimeout(() => { + const markSuccess = this.markNetworkIdle(); + if (markSuccess) { + logger_1.default.warn(`PageLoader: Network idle timeout`); + } + }, this.timeout); + setTimeout(() => { + if (!this.totalRequests) { + this.markNetworkIdle(); + } + }, this.waitNetworkIdleTimeout); + } + async initMock() { + if (!this.waitNetworkIdle) { + return; + } + this.mock = await this.session.mock("**").catch(() => { + logger_1.default.warn(`PageLoader: Could not create CDP interceptor`); + return null; + }); + if (!this.mock) { + this.markNetworkIdle(); + return; + } + let pendingRequests = 0; + let pendingIdleTimeout; + this.mock.on("request", () => { + this.totalRequests++; + pendingRequests++; + clearTimeout(pendingIdleTimeout); + }); + this.mock.on("continue", () => { + pendingRequests--; + if (!pendingRequests) { + pendingIdleTimeout = setTimeout(() => this.markNetworkIdle(), this.waitNetworkIdleTimeout); + } + }); + this.mock.on("match", (match) => { + if (this.isMatchError(match)) { + this.emit("networkError", match); + } + }); + } + isMatchError(match) { + return match.statusCode >= 400 && match.statusCode < 600; + } + markNetworkIdle() { + if (this.networkResolved) { + return false; + } + this.networkResolved = true; + this.emit("networkResolved"); + return true; + } +} +exports.default = PageLoader; +//# sourceMappingURL=page-loader.js.map \ No newline at end of file diff --git a/build/src/utils/page-loader.js.map b/build/src/utils/page-loader.js.map new file mode 100644 index 000000000..3f292edc0 --- /dev/null +++ b/build/src/utils/page-loader.js.map @@ -0,0 +1 @@ +{"version":3,"file":"page-loader.js","sourceRoot":"","sources":["../../../src/utils/page-loader.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/utils/processor.d.ts b/build/src/utils/processor.d.ts new file mode 100644 index 000000000..7526fb2a2 --- /dev/null +++ b/build/src/utils/processor.d.ts @@ -0,0 +1,2 @@ +declare function _exports(module: any, methodName: any, args: any, cb: any): Promise; +export = _exports; diff --git a/build/src/utils/processor.js b/build/src/utils/processor.js new file mode 100644 index 000000000..128bcfaae --- /dev/null +++ b/build/src/utils/processor.js @@ -0,0 +1,45 @@ +"use strict"; +const _ = require("lodash"); +const { WORKER_UNHANDLED_REJECTION } = require("../constants/process-messages"); +const logger = require("./logger"); +const ipc = require("./ipc"); +process.on("unhandledRejection", (reason, p) => { + if (reason && reason.name === "ProtocolError") { + logger.warn(`Unhandled Rejection "${reason}" in hermione:worker:${process.pid} was ignored`); + return; + } + const error = [ + `Unhandled Rejection in hermione:worker:${process.pid}:`, + `Promise: ${JSON.stringify(p)}`, + `Reason: ${_.get(reason, "stack", reason)}`, + ].join("\n"); + ipc.emit(WORKER_UNHANDLED_REJECTION, { error }); +}); +module.exports = async (module, methodName, args, cb) => { + try { + const result = await require(module)[methodName](...args); + cb(null, result); + } + catch (err) { + sendError(err, cb); + } +}; +function sendError(err, cb) { + try { + cb(err); + } + catch { + const shortenedErr = _.pick(err, [ + "message", + "stack", + "code", + "screenshot", + // TODO: use fields from worker test-runner after rewrite on TS + "hermioneCtx", + "meta", + "history", + ]); + cb(shortenedErr); + } +} +//# sourceMappingURL=processor.js.map \ No newline at end of file diff --git a/build/src/utils/processor.js.map b/build/src/utils/processor.js.map new file mode 100644 index 000000000..05a8bf53e --- /dev/null +++ b/build/src/utils/processor.js.map @@ -0,0 +1 @@ +{"version":3,"file":"processor.js","sourceRoot":"","sources":["../../../src/utils/processor.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC5B,MAAM,EAAE,0BAA0B,EAAE,GAAG,OAAO,CAAC,+BAA+B,CAAC,CAAC;AAChF,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACnC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAE7B,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;IAC3C,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,wBAAwB,MAAM,wBAAwB,OAAO,CAAC,GAAG,cAAc,CAAC,CAAC;QAC7F,OAAO;IACX,CAAC;IAED,MAAM,KAAK,GAAG;QACV,0CAA0C,OAAO,CAAC,GAAG,GAAG;QACxD,YAAY,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;QAC/B,WAAW,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE;KAC9C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,GAAG,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,OAAO,GAAG,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;IACpD,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC1D,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,SAAS,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACvB,CAAC;AACL,CAAC,CAAC;AAEF,SAAS,SAAS,CAAC,GAAG,EAAE,EAAE;IACtB,IAAI,CAAC;QACD,EAAE,CAAC,GAAG,CAAC,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACL,MAAM,YAAY,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YAC7B,SAAS;YACT,OAAO;YACP,MAAM;YACN,YAAY;YACZ,+DAA+D;YAC/D,aAAa;YACb,MAAM;YACN,SAAS;SACZ,CAAC,CAAC;QAEH,EAAE,CAAC,YAAY,CAAC,CAAC;IACrB,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/build/src/utils/typescript.d.ts b/build/src/utils/typescript.d.ts new file mode 100644 index 000000000..113e9ec74 --- /dev/null +++ b/build/src/utils/typescript.d.ts @@ -0,0 +1 @@ +export declare const tryToRegisterTsNode: () => void; diff --git a/build/src/utils/typescript.js b/build/src/utils/typescript.js new file mode 100644 index 000000000..a5289daeb --- /dev/null +++ b/build/src/utils/typescript.js @@ -0,0 +1,41 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.tryToRegisterTsNode = void 0; +const lodash_1 = __importDefault(require("lodash")); +const tryToRegisterTsNode = () => { + try { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { REGISTER_INSTANCE } = require("ts-node"); + if (lodash_1.default.get(process, REGISTER_INSTANCE)) { + return; + } + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { register } = require("ts-node"); + let swc = false; + try { + require("@swc/core"); + swc = true; + } + catch { } // eslint-disable-line no-empty + const skipProjectRaw = process.env.TS_NODE_SKIP_PROJECT ?? "true"; + const transpileOnlyRaw = process.env.TS_NODE_TRANSPILE_ONLY ?? "true"; + const swcRaw = process.env.TS_NODE_SWC ?? swc.toString(); + try { + register({ + skipProject: JSON.parse(skipProjectRaw), + transpileOnly: JSON.parse(transpileOnlyRaw), + swc: JSON.parse(swcRaw), + }); + } + catch (err) { + const params = `swc: "${swcRaw}", transpileOnly: "${transpileOnlyRaw}", skipProject: "${skipProjectRaw}"`; + console.error(`hermione: an error occured while trying to register ts-node (${params}):`, err); + } + } + catch { } // eslint-disable-line no-empty +}; +exports.tryToRegisterTsNode = tryToRegisterTsNode; +//# sourceMappingURL=typescript.js.map \ No newline at end of file diff --git a/build/src/utils/typescript.js.map b/build/src/utils/typescript.js.map new file mode 100644 index 000000000..87ae797bf --- /dev/null +++ b/build/src/utils/typescript.js.map @@ -0,0 +1 @@ +{"version":3,"file":"typescript.js","sourceRoot":"","sources":["../../../src/utils/typescript.ts"],"names":[],"mappings":";;;;;;AAAA,oDAAuB;AAEhB,MAAM,mBAAmB,GAAG,GAAS,EAAE;IAC1C,IAAI,CAAC;QACD,8DAA8D;QAC9D,MAAM,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;QAEjD,IAAI,gBAAC,CAAC,GAAG,CAAC,OAAO,EAAE,iBAAiB,CAAC,EAAE,CAAC;YACpC,OAAO;QACX,CAAC;QAED,8DAA8D;QAC9D,MAAM,EAAE,QAAQ,EAAE,GAA6B,OAAO,CAAC,SAAS,CAAC,CAAC;QAClE,IAAI,GAAG,GAAG,KAAK,CAAC;QAEhB,IAAI,CAAC;YACD,OAAO,CAAC,WAAW,CAAC,CAAC;YACrB,GAAG,GAAG,IAAI,CAAC;QACf,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC,CAAC,+BAA+B;QAE1C,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,MAAM,CAAC;QAClE,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,MAAM,CAAC;QACtE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QAEzD,IAAI,CAAC;YACD,QAAQ,CAAC;gBACL,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC;gBACvC,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC;gBAC3C,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;aAC1B,CAAC,CAAC;QACP,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,MAAM,MAAM,GAAG,SAAS,MAAM,sBAAsB,gBAAgB,oBAAoB,cAAc,GAAG,CAAC;YAC1G,OAAO,CAAC,KAAK,CAAC,gEAAgE,MAAM,IAAI,EAAE,GAAG,CAAC,CAAC;QACnG,CAAC;IACL,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC,CAAC,+BAA+B;AAC9C,CAAC,CAAC;AAjCW,QAAA,mBAAmB,uBAiC9B"} \ No newline at end of file diff --git a/build/src/utils/worker-process.d.ts b/build/src/utils/worker-process.d.ts new file mode 100644 index 000000000..e5dedc6ce --- /dev/null +++ b/build/src/utils/worker-process.d.ts @@ -0,0 +1,10 @@ +/// +import { ChildProcess } from "child_process"; +type Serializable = string | object | number | boolean | bigint; +export declare class WorkerProcess { + protected process: ChildProcess; + static create(this: new (process: ChildProcess) => T, process: ChildProcess): T; + constructor(process: ChildProcess); + send(message: Serializable): boolean; +} +export {}; diff --git a/build/src/utils/worker-process.js b/build/src/utils/worker-process.js new file mode 100644 index 000000000..08db35f5f --- /dev/null +++ b/build/src/utils/worker-process.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.WorkerProcess = void 0; +class WorkerProcess { + static create(process) { + return new this(process); + } + constructor(process) { + this.process = process; + } + send(message) { + if (!this.process.connected) { + return false; + } + this.process.send(message); + return true; + } +} +exports.WorkerProcess = WorkerProcess; +//# sourceMappingURL=worker-process.js.map \ No newline at end of file diff --git a/build/src/utils/worker-process.js.map b/build/src/utils/worker-process.js.map new file mode 100644 index 000000000..66a6d4865 --- /dev/null +++ b/build/src/utils/worker-process.js.map @@ -0,0 +1 @@ +{"version":3,"file":"worker-process.js","sourceRoot":"","sources":["../../../src/utils/worker-process.ts"],"names":[],"mappings":";;;AAIA,MAAa,aAAa;IAGtB,MAAM,CAAC,MAAM,CAAkE,OAAqB;QAChG,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED,YAAY,OAAqB;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IAED,IAAI,CAAC,OAAqB;QACtB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YAC1B,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE3B,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ;AApBD,sCAoBC"} \ No newline at end of file diff --git a/build/src/utils/workers-registry.d.ts b/build/src/utils/workers-registry.d.ts new file mode 100644 index 000000000..52aab5570 --- /dev/null +++ b/build/src/utils/workers-registry.d.ts @@ -0,0 +1,24 @@ +export = WorkersRegistry; +declare class WorkersRegistry extends EventEmitter { + static create(...args: any[]): import("./workers-registry"); + constructor(config: any); + _config: any; + _ended: boolean; + _workerFarm: workerFarm.Workers | null; + _registeredWorkers: any[]; + init(): void; + end(): globalThis.Promise; + isEnded(): boolean; + register(workerFilepath: any, exportedMethods: any): EventEmitter; + _createWorkerFarm(): workerFarm.Workers; + _inspectParams(): { + workerOptions: { + execArgv: string[]; + }; + maxConcurrentWorkers: number; + maxCallsPerWorker: number; + } | undefined; + _initChild(child: any): void; +} +import { EventEmitter } from "events"; +import workerFarm = require("worker-farm"); diff --git a/build/src/utils/workers-registry.js b/build/src/utils/workers-registry.js new file mode 100644 index 000000000..dbeb18ed0 --- /dev/null +++ b/build/src/utils/workers-registry.js @@ -0,0 +1,114 @@ +"use strict"; +const { EventEmitter } = require("events"); +const workerFarm = require("worker-farm"); +const Promise = require("bluebird"); +const _ = require("lodash"); +const { MasterEvents } = require("../events"); +const RuntimeConfig = require("../config/runtime-config"); +const { WorkerProcess } = require("./worker-process"); +const logger = require("../utils/logger"); +const { MASTER_INIT, MASTER_SYNC_CONFIG, WORKER_INIT, WORKER_SYNC_CONFIG, WORKER_UNHANDLED_REJECTION, } = require("../constants/process-messages"); +module.exports = class WorkersRegistry extends EventEmitter { + static create(...args) { + return new WorkersRegistry(...args); + } + constructor(config) { + super(); + this._config = config; + this._ended = false; + this._workerFarm = null; + this._registeredWorkers = []; + } + init() { + if (this._workerFarm) { + return; + } + this._workerFarm = this._createWorkerFarm(); + } + async end() { + this._ended = true; + await Promise.promisify(workerFarm.end)(this._workerFarm); + } + isEnded() { + return this._ended; + } + register(workerFilepath, exportedMethods) { + const workers = new EventEmitter(); + this._registeredWorkers.push(workers); + for (const methodName of exportedMethods) { + workers[methodName] = (...args) => { + if (this._ended) { + return Promise.reject(new Error(`Can't execute method '${methodName}' because worker farm ended.`)); + } + return Promise.promisify(this._workerFarm)(workerFilepath, methodName, args); + }; + } + return workers; + } + _createWorkerFarm() { + const workerFilepath = require.resolve("./processor"); + const params = { + maxConcurrentWorkers: this._config.system.workers, + maxCallsPerWorker: this._config.system.testsPerWorker, + maxConcurrentCallsPerWorker: Infinity, + autoStart: true, + maxRetries: 0, + onChild: child => this._initChild(child), + ...this._inspectParams(), + }; + return workerFarm(params, workerFilepath); + } + _inspectParams() { + const runtimeConfig = RuntimeConfig.getInstance(); + if (!runtimeConfig || !runtimeConfig.inspectMode) { + return; + } + const { inspect, inspectBrk } = runtimeConfig.inspectMode; + const inspectName = inspectBrk ? "inspect-brk" : "inspect"; + let inspectValue = inspectBrk ? inspectBrk : inspect; + inspectValue = typeof inspectValue === "string" ? `=${inspectValue}` : ""; + return { + workerOptions: { execArgv: [`--${inspectName}${inspectValue}`] }, + maxConcurrentWorkers: 1, + maxCallsPerWorker: Infinity, + }; + } + _initChild(child) { + child.once("exit", (code, signal) => { + if (code === 0) { + return; + } + const errMsg = code === null ? `signal: ${signal}` : `exit code: ${code}`; + logger.error(`hermione:worker:${child.pid} terminated unexpectedly with ${errMsg}`); + }); + child.on("message", (data = {}) => { + switch (data.event) { + case WORKER_INIT: + child.send({ + event: MASTER_INIT, + configPath: this._config.configPath, + runtimeConfig: RuntimeConfig.getInstance(), + }); + break; + case WORKER_SYNC_CONFIG: + child.send({ + event: MASTER_SYNC_CONFIG, + config: this._config.serialize(), + }); + break; + case WORKER_UNHANDLED_REJECTION: + if (data.error) { + this.emit(MasterEvents.ERROR, data.error); + } + break; + default: + if (data.event) { + this._registeredWorkers.forEach(workers => workers.emit(data.event, _.omit(data, "event"))); + } + break; + } + }); + this.emit(MasterEvents.NEW_WORKER_PROCESS, WorkerProcess.create(child)); + } +}; +//# sourceMappingURL=workers-registry.js.map \ No newline at end of file diff --git a/build/src/utils/workers-registry.js.map b/build/src/utils/workers-registry.js.map new file mode 100644 index 000000000..ea3d5aaae --- /dev/null +++ b/build/src/utils/workers-registry.js.map @@ -0,0 +1 @@ +{"version":3,"file":"workers-registry.js","sourceRoot":"","sources":["../../../src/utils/workers-registry.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/validators.d.ts b/build/src/validators.d.ts new file mode 100644 index 000000000..9abd1ee71 --- /dev/null +++ b/build/src/validators.d.ts @@ -0,0 +1 @@ +export function validateUnknownBrowsers(browsers: any, configBrowsers: any): void; diff --git a/build/src/validators.js b/build/src/validators.js new file mode 100644 index 000000000..e8d48bd8b --- /dev/null +++ b/build/src/validators.js @@ -0,0 +1,16 @@ +"use strict"; +const format = require("util").format; +const chalk = require("chalk"); +const _ = require("lodash"); +const logger = require("./utils/logger"); +exports.validateUnknownBrowsers = (browsers, configBrowsers) => { + const unknownBrowsers = getUnknownBrowsers(browsers, configBrowsers); + if (_.isEmpty(unknownBrowsers)) { + return; + } + logger.warn(format("%s Unknown browser ids: %s. Use one of the browser ids specified in the config file: %s", chalk.yellow("WARNING:"), unknownBrowsers.join(", "), configBrowsers.join(", "))); +}; +function getUnknownBrowsers(browsers, configBrowsers) { + return _(browsers).compact().uniq().difference(configBrowsers).value(); +} +//# sourceMappingURL=validators.js.map \ No newline at end of file diff --git a/build/src/validators.js.map b/build/src/validators.js.map new file mode 100644 index 000000000..a17380730 --- /dev/null +++ b/build/src/validators.js.map @@ -0,0 +1 @@ +{"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/validators.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;AACtC,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAC/B,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC5B,MAAM,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAEzC,OAAO,CAAC,uBAAuB,GAAG,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAE;IAC3D,MAAM,eAAe,GAAG,kBAAkB,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IAErE,IAAI,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;QAC7B,OAAO;IACX,CAAC;IAED,MAAM,CAAC,IAAI,CACP,MAAM,CACF,yFAAyF,EACzF,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,EACxB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAC1B,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAC5B,CACJ,CAAC;AACN,CAAC,CAAC;AAEF,SAAS,kBAAkB,CAAC,QAAQ,EAAE,cAAc;IAChD,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,KAAK,EAAE,CAAC;AAC3E,CAAC"} \ No newline at end of file diff --git a/build/src/worker/hermione-facade.d.ts b/build/src/worker/hermione-facade.d.ts new file mode 100644 index 000000000..f09362dff --- /dev/null +++ b/build/src/worker/hermione-facade.d.ts @@ -0,0 +1,12 @@ +export = HermioneFacade; +declare class HermioneFacade { + static create(): import("./hermione-facade"); + promise: Promise; + _hermione: any; + init(): Promise; + syncConfig(): Promise; + runTest(...args: any[]): Promise; + _init(): Promise; + _syncConfig(): Promise; +} +import Promise = require("bluebird"); diff --git a/build/src/worker/hermione-facade.js b/build/src/worker/hermione-facade.js new file mode 100644 index 000000000..b8c93ecf6 --- /dev/null +++ b/build/src/worker/hermione-facade.js @@ -0,0 +1,71 @@ +"use strict"; +const { Hermione } = require("./hermione"); +const RuntimeConfig = require("../config/runtime-config"); +const Promise = require("bluebird"); +const debug = require("debug")(`hermione:worker:${process.pid}`); +const ipc = require("../utils/ipc"); +const { MASTER_INIT, MASTER_SYNC_CONFIG, WORKER_INIT, WORKER_SYNC_CONFIG } = require("../constants/process-messages"); +const { requireModule } = require("../utils/module"); +module.exports = class HermioneFacade { + static create() { + return new HermioneFacade(); + } + constructor() { + this.promise = Promise.resolve(); + this._hermione = null; + } + init() { + this.init = () => this.promise; + this.promise = this._init() + .then(hermione => (this._hermione = hermione)) + .then(() => this._hermione.init()); + return this.promise; + } + syncConfig() { + this.syncConfig = () => this.promise; + this.promise = this.init().then(() => this._syncConfig()); + return this.promise; + } + runTest(...args) { + return this.syncConfig().then(() => this._hermione.runTest(...args)); + } + _init() { + return new Promise((resolve, reject) => { + debug("init worker"); + ipc.on(MASTER_INIT, ({ configPath, runtimeConfig } = {}) => { + try { + const promise = Promise.resolve(); + if (runtimeConfig.requireModules) { + runtimeConfig.requireModules.forEach(modulePath => { + promise.then(requireModule(modulePath)); + }); + } + RuntimeConfig.getInstance().extend(runtimeConfig); + const hermione = Hermione.create(configPath); + promise.then(() => { + debug("worker initialized"); + resolve(hermione); + }); + } + catch (e) { + debug("worker initialization failed"); + reject(e); + } + }); + ipc.emit(WORKER_INIT); + }); + } + _syncConfig() { + return new Promise(resolve => { + debug("sync config"); + ipc.on(MASTER_SYNC_CONFIG, ({ config } = {}) => { + delete config.system.mochaOpts.grep; // grep affects only master + this._hermione.config.mergeWith(config); + debug("config synced"); + resolve(); + }); + ipc.emit(WORKER_SYNC_CONFIG); + }); + } +}; +//# sourceMappingURL=hermione-facade.js.map \ No newline at end of file diff --git a/build/src/worker/hermione-facade.js.map b/build/src/worker/hermione-facade.js.map new file mode 100644 index 000000000..815b15eec --- /dev/null +++ b/build/src/worker/hermione-facade.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hermione-facade.js","sourceRoot":"","sources":["../../../src/worker/hermione-facade.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/worker/hermione.d.ts b/build/src/worker/hermione.d.ts new file mode 100644 index 000000000..2085db69b --- /dev/null +++ b/build/src/worker/hermione.d.ts @@ -0,0 +1,34 @@ +import Runner from "./runner"; +import { BaseHermione } from "../base-hermione"; +import { ImageInfo, WdioBrowser, WorkerEventHandler } from "../types"; +export interface WorkerRunTestOpts { + browserId: string; + browserVersion: string; + file: string; + sessionId: string; + sessionCaps: WdioBrowser["capabilities"]; + sessionOpts: WdioBrowser["options"]; + testXReqId: string; +} +export interface AssertViewResultsSuccess { + stateName: string; + refImg: ImageInfo; +} +export interface WorkerRunTestHermioneCtx { + assertViewResults: Array; +} +export interface WorkerRunTestResult { + meta: Record; + hermioneCtx: WorkerRunTestHermioneCtx; +} +export interface Hermione { + on: WorkerEventHandler; + once: WorkerEventHandler; +} +export declare class Hermione extends BaseHermione { + protected runner: Runner; + constructor(configPath: string); + init(): Promise; + runTest(fullTitle: string, options: WorkerRunTestOpts): Promise; + isWorker(): boolean; +} diff --git a/build/src/worker/hermione.js b/build/src/worker/hermione.js new file mode 100644 index 000000000..5b01e590c --- /dev/null +++ b/build/src/worker/hermione.js @@ -0,0 +1,39 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Hermione = void 0; +const utils_1 = require("../events/utils"); +const events_1 = require("../events"); +const runner_1 = __importDefault(require("./runner")); +const base_hermione_1 = require("../base-hermione"); +class Hermione extends base_hermione_1.BaseHermione { + constructor(configPath) { + super(configPath); + this.runner = runner_1.default.create(this._config); + (0, utils_1.passthroughEvent)(this.runner, this, [ + events_1.WorkerEvents.BEFORE_FILE_READ, + events_1.WorkerEvents.AFTER_FILE_READ, + events_1.WorkerEvents.AFTER_TESTS_READ, + events_1.WorkerEvents.NEW_BROWSER, + events_1.WorkerEvents.UPDATE_REFERENCE, + ]); + } + async init() { + await this._init(); + if (!global.expect) { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { setOptions } = require("expect-webdriverio"); + setOptions(this._config.system.expectOpts); + } + } + runTest(fullTitle, options) { + return this.runner.runTest(fullTitle, options); + } + isWorker() { + return true; + } +} +exports.Hermione = Hermione; +//# sourceMappingURL=hermione.js.map \ No newline at end of file diff --git a/build/src/worker/hermione.js.map b/build/src/worker/hermione.js.map new file mode 100644 index 000000000..d7f2463c7 --- /dev/null +++ b/build/src/worker/hermione.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hermione.js","sourceRoot":"","sources":["../../../src/worker/hermione.ts"],"names":[],"mappings":";;;;;;AAAA,2CAAmD;AACnD,sCAAyC;AACzC,sDAA8B;AAC9B,oDAAgD;AAgChD,MAAa,QAAS,SAAQ,4BAAY;IAGtC,YAAY,UAAkB;QAC1B,KAAK,CAAC,UAAU,CAAC,CAAC;QAElB,IAAI,CAAC,MAAM,GAAG,gBAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE1C,IAAA,wBAAgB,EAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE;YAChC,qBAAY,CAAC,gBAAgB;YAC7B,qBAAY,CAAC,eAAe;YAC5B,qBAAY,CAAC,gBAAgB;YAC7B,qBAAY,CAAC,WAAW;YACxB,qBAAY,CAAC,gBAAgB;SAChC,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,IAAI;QACN,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAEnB,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACjB,8DAA8D;YAC9D,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;YACrD,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC/C,CAAC;IACL,CAAC;IAED,OAAO,CAAC,SAAiB,EAAE,OAA0B;QACjD,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;IAED,QAAQ;QACJ,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ;AAlCD,4BAkCC"} \ No newline at end of file diff --git a/build/src/worker/index.d.ts b/build/src/worker/index.d.ts new file mode 100644 index 000000000..d43e18804 --- /dev/null +++ b/build/src/worker/index.d.ts @@ -0,0 +1 @@ +export function runTest(fullTitle: any, options: any): import("bluebird"); diff --git a/build/src/worker/index.js b/build/src/worker/index.js new file mode 100644 index 000000000..a48d363d6 --- /dev/null +++ b/build/src/worker/index.js @@ -0,0 +1,8 @@ +"use strict"; +const HermioneFacade = require("./hermione-facade"); +const hermioneFacade = HermioneFacade.create(); +hermioneFacade.init(); +exports.runTest = (fullTitle, options) => { + return hermioneFacade.runTest(fullTitle, options); +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/worker/index.js.map b/build/src/worker/index.js.map new file mode 100644 index 000000000..b8f8df9b7 --- /dev/null +++ b/build/src/worker/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/worker/index.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAEpD,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC;AAC/C,cAAc,CAAC,IAAI,EAAE,CAAC;AAEtB,OAAO,CAAC,OAAO,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE;IACrC,OAAO,cAAc,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AACtD,CAAC,CAAC"} \ No newline at end of file diff --git a/build/src/worker/runner/browser-agent.d.ts b/build/src/worker/runner/browser-agent.d.ts new file mode 100644 index 000000000..f1f025dfd --- /dev/null +++ b/build/src/worker/runner/browser-agent.d.ts @@ -0,0 +1,19 @@ +export = BrowserAgent; +declare class BrowserAgent { + static create(opts: any): import("./browser-agent"); + constructor({ id, version, pool }: { + id: any; + version: any; + pool: any; + }); + browserId: any; + browserVersion: any; + _pool: any; + getBrowser({ sessionId, sessionCaps, sessionOpts, testXReqId }: { + sessionId: any; + sessionCaps: any; + sessionOpts: any; + testXReqId: any; + }): any; + freeBrowser(browser: any): void; +} diff --git a/build/src/worker/runner/browser-agent.js b/build/src/worker/runner/browser-agent.js new file mode 100644 index 000000000..07d5558b7 --- /dev/null +++ b/build/src/worker/runner/browser-agent.js @@ -0,0 +1,25 @@ +"use strict"; +module.exports = class BrowserAgent { + static create(opts) { + return new this(opts); + } + constructor({ id, version, pool }) { + this.browserId = id; + this.browserVersion = version; + this._pool = pool; + } + getBrowser({ sessionId, sessionCaps, sessionOpts, testXReqId }) { + return this._pool.getBrowser({ + browserId: this.browserId, + browserVersion: this.browserVersion, + sessionId, + sessionCaps, + sessionOpts, + testXReqId, + }); + } + freeBrowser(browser) { + this._pool.freeBrowser(browser); + } +}; +//# sourceMappingURL=browser-agent.js.map \ No newline at end of file diff --git a/build/src/worker/runner/browser-agent.js.map b/build/src/worker/runner/browser-agent.js.map new file mode 100644 index 000000000..dcc68d352 --- /dev/null +++ b/build/src/worker/runner/browser-agent.js.map @@ -0,0 +1 @@ +{"version":3,"file":"browser-agent.js","sourceRoot":"","sources":["../../../../src/worker/runner/browser-agent.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,OAAO,GAAG,MAAM,YAAY;IAC/B,MAAM,CAAC,MAAM,CAAC,IAAI;QACd,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,YAAY,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QAC7B,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QACpB,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC;QAE9B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,UAAU,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE;QAC1D,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;YACzB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,SAAS;YACT,WAAW;YACX,WAAW;YACX,UAAU;SACb,CAAC,CAAC;IACP,CAAC;IAED,WAAW,CAAC,OAAO;QACf,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/worker/runner/browser-pool.d.ts b/build/src/worker/runner/browser-pool.d.ts new file mode 100644 index 000000000..fbf5f2c1b --- /dev/null +++ b/build/src/worker/runner/browser-pool.d.ts @@ -0,0 +1,19 @@ +export = BrowserPool; +declare class BrowserPool { + static create(config: any, emitter: any): import("./browser-pool"); + constructor(config: any, emitter: any); + _config: any; + _emitter: any; + _calibrator: Calibrator; + getBrowser({ browserId, browserVersion, sessionId, sessionCaps, sessionOpts, testXReqId }: { + browserId: any; + browserVersion: any; + sessionId: any; + sessionCaps: any; + sessionOpts: any; + testXReqId: any; + }): Promise; + freeBrowser(browser: any): void; +} +import Calibrator = require("../../browser/calibrator"); +import Browser = require("../../browser/existing-browser"); diff --git a/build/src/worker/runner/browser-pool.js b/build/src/worker/runner/browser-pool.js new file mode 100644 index 000000000..ec2fa7469 --- /dev/null +++ b/build/src/worker/runner/browser-pool.js @@ -0,0 +1,41 @@ +"use strict"; +const Browser = require("../../browser/existing-browser"); +const Calibrator = require("../../browser/calibrator"); +const { WorkerEvents } = require("../../events"); +const ipc = require("../../utils/ipc"); +module.exports = class BrowserPool { + static create(config, emitter) { + return new BrowserPool(config, emitter); + } + constructor(config, emitter) { + this._config = config; + this._emitter = emitter; + this._calibrator = new Calibrator(); + } + async getBrowser({ browserId, browserVersion, sessionId, sessionCaps, sessionOpts, testXReqId }) { + const browser = Browser.create(this._config, { + id: browserId, + version: browserVersion, + testXReqId, + emitter: this._emitter, + }); + try { + await browser.init({ sessionId, sessionCaps, sessionOpts }, this._calibrator); + this._emitter.emit(WorkerEvents.NEW_BROWSER, browser.publicAPI, { browserId: browser.id, browserVersion }); + return browser; + } + catch (error) { + if (!browser) { + throw error; + } + browser.markAsBroken(); + this.freeBrowser(browser); + throw Object.assign(error, { meta: browser.meta }); + } + } + freeBrowser(browser) { + ipc.emit(`worker.${browser.sessionId}.freeBrowser`, browser.state); + browser.quit(); + } +}; +//# sourceMappingURL=browser-pool.js.map \ No newline at end of file diff --git a/build/src/worker/runner/browser-pool.js.map b/build/src/worker/runner/browser-pool.js.map new file mode 100644 index 000000000..9730e81b8 --- /dev/null +++ b/build/src/worker/runner/browser-pool.js.map @@ -0,0 +1 @@ +{"version":3,"file":"browser-pool.js","sourceRoot":"","sources":["../../../../src/worker/runner/browser-pool.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,OAAO,GAAG,OAAO,CAAC,gCAAgC,CAAC,CAAC;AAC1D,MAAM,UAAU,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAC;AACvD,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AACjD,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEvC,MAAM,CAAC,OAAO,GAAG,MAAM,WAAW;IAC9B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO;QACzB,OAAO,IAAI,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,YAAY,MAAM,EAAE,OAAO;QACvB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,WAAW,GAAG,IAAI,UAAU,EAAE,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE;QAC3F,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE;YACzC,EAAE,EAAE,SAAS;YACb,OAAO,EAAE,cAAc;YACvB,UAAU;YACV,OAAO,EAAE,IAAI,CAAC,QAAQ;SACzB,CAAC,CAAC;QAEH,IAAI,CAAC;YACD,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;YAE9E,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,cAAc,EAAE,CAAC,CAAC;YAE3G,OAAO,OAAO,CAAC;QACnB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,IAAI,CAAC,OAAO,EAAE,CAAC;gBACX,MAAM,KAAK,CAAC;YAChB,CAAC;YAED,OAAO,CAAC,YAAY,EAAE,CAAC;YACvB,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAE1B,MAAM,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QACvD,CAAC;IACL,CAAC;IAED,WAAW,CAAC,OAAO;QACf,GAAG,CAAC,IAAI,CAAC,UAAU,OAAO,CAAC,SAAS,cAAc,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QAEnE,OAAO,CAAC,IAAI,EAAE,CAAC;IACnB,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/worker/runner/caching-test-parser.d.ts b/build/src/worker/runner/caching-test-parser.d.ts new file mode 100644 index 000000000..8404f1839 --- /dev/null +++ b/build/src/worker/runner/caching-test-parser.d.ts @@ -0,0 +1,22 @@ +export = CachingTestParser; +declare class CachingTestParser extends EventEmitter { + static create(...args: any[]): import("./caching-test-parser"); + constructor(config: any); + _config: any; + _cache: {}; + _sequenceTestParser: SequenceTestParser; + parse({ file, browserId }: { + file: any; + browserId: any; + }): Promise; + _getFromCache({ file, browserId }: { + file: any; + browserId: any; + }): any; + _putToCache(testsPromise: any, { file, browserId }: { + file: any; + browserId: any; + }): void; +} +import { EventEmitter } from "events"; +import SequenceTestParser = require("./sequence-test-parser"); diff --git a/build/src/worker/runner/caching-test-parser.js b/build/src/worker/runner/caching-test-parser.js new file mode 100644 index 000000000..6fc57f947 --- /dev/null +++ b/build/src/worker/runner/caching-test-parser.js @@ -0,0 +1,37 @@ +"use strict"; +const { EventEmitter } = require("events"); +const { passthroughEvent } = require("../../events/utils"); +const SequenceTestParser = require("./sequence-test-parser"); +const { TestCollection } = require("../../test-collection"); +const { WorkerEvents } = require("../../events"); +module.exports = class CachingTestParser extends EventEmitter { + static create(...args) { + return new this(...args); + } + constructor(config) { + super(); + this._config = config; + this._cache = {}; + this._sequenceTestParser = SequenceTestParser.create(config); + passthroughEvent(this._sequenceTestParser, this, [WorkerEvents.BEFORE_FILE_READ, WorkerEvents.AFTER_FILE_READ]); + } + async parse({ file, browserId }) { + const cached = this._getFromCache({ file, browserId }); + if (cached) { + return cached; + } + const testsPromise = this._sequenceTestParser.parse({ file, browserId }); + this._putToCache(testsPromise, { file, browserId }); + const tests = await testsPromise; + this.emit(WorkerEvents.AFTER_TESTS_READ, TestCollection.create({ [browserId]: tests }, this._config)); + return tests; + } + _getFromCache({ file, browserId }) { + return this._cache[browserId] && this._cache[browserId][file]; + } + _putToCache(testsPromise, { file, browserId }) { + this._cache[browserId] = this._cache[browserId] || {}; + this._cache[browserId][file] = testsPromise; + } +}; +//# sourceMappingURL=caching-test-parser.js.map \ No newline at end of file diff --git a/build/src/worker/runner/caching-test-parser.js.map b/build/src/worker/runner/caching-test-parser.js.map new file mode 100644 index 000000000..30a50c89b --- /dev/null +++ b/build/src/worker/runner/caching-test-parser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"caching-test-parser.js","sourceRoot":"","sources":["../../../../src/worker/runner/caching-test-parser.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC3C,MAAM,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAC3D,MAAM,kBAAkB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;AAC7D,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;AAC5D,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAEjD,MAAM,CAAC,OAAO,GAAG,MAAM,iBAAkB,SAAQ,YAAY;IACzD,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI;QACjB,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,YAAY,MAAM;QACd,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QAEjB,IAAI,CAAC,mBAAmB,GAAG,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7D,gBAAgB,CAAC,IAAI,CAAC,mBAAmB,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC,CAAC;IACpH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QACvD,IAAI,MAAM,EAAE,CAAC;YACT,OAAO,MAAM,CAAC;QAClB,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QACzE,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QAEpD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC;QAEjC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,gBAAgB,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAEtG,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,aAAa,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE;QAC7B,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC;IAClE,CAAC;IAED,WAAW,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QACzC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QACtD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC;IAChD,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/worker/runner/index.d.ts b/build/src/worker/runner/index.d.ts new file mode 100644 index 000000000..85dabeb57 --- /dev/null +++ b/build/src/worker/runner/index.d.ts @@ -0,0 +1,23 @@ +export = Runner; +declare class Runner extends AsyncEmitter { + static create(config: any): import("."); + constructor(config: any); + _config: any; + _browserPool: BrowserPool; + _testParser: CachingTestParser; + runTest(fullTitle: any, { browserId, browserVersion, file, sessionId, sessionCaps, sessionOpts, testXReqId }: { + browserId: any; + browserVersion: any; + file: any; + sessionId: any; + sessionCaps: any; + sessionOpts: any; + testXReqId: any; + }): Promise<{ + hermioneCtx: any; + meta: any; + }>; +} +import { AsyncEmitter } from "../../events/async-emitter"; +import BrowserPool = require("./browser-pool"); +import CachingTestParser = require("./caching-test-parser"); diff --git a/build/src/worker/runner/index.js b/build/src/worker/runner/index.js new file mode 100644 index 000000000..17f8a785f --- /dev/null +++ b/build/src/worker/runner/index.js @@ -0,0 +1,32 @@ +"use strict"; +const { AsyncEmitter } = require("../../events/async-emitter"); +const { passthroughEvent } = require("../../events/utils"); +const { WorkerEvents } = require("../../events"); +const BrowserPool = require("./browser-pool"); +const BrowserAgent = require("./browser-agent"); +const TestRunner = require("./test-runner"); +const CachingTestParser = require("./caching-test-parser"); +module.exports = class Runner extends AsyncEmitter { + static create(config) { + return new Runner(config); + } + constructor(config) { + super(); + this._config = config; + this._browserPool = BrowserPool.create(this._config, this); + this._testParser = CachingTestParser.create(config); + passthroughEvent(this._testParser, this, [ + WorkerEvents.BEFORE_FILE_READ, + WorkerEvents.AFTER_FILE_READ, + WorkerEvents.AFTER_TESTS_READ, + ]); + } + async runTest(fullTitle, { browserId, browserVersion, file, sessionId, sessionCaps, sessionOpts, testXReqId }) { + const tests = await this._testParser.parse({ file, browserId }); + const test = tests.find(t => t.fullTitle() === fullTitle); + const browserAgent = BrowserAgent.create({ id: browserId, version: browserVersion, pool: this._browserPool }); + const runner = TestRunner.create(test, this._config.forBrowser(browserId), browserAgent); + return runner.run({ sessionId, sessionCaps, sessionOpts, testXReqId }); + } +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/worker/runner/index.js.map b/build/src/worker/runner/index.js.map new file mode 100644 index 000000000..a90424805 --- /dev/null +++ b/build/src/worker/runner/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/worker/runner/index.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;AAC/D,MAAM,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAC3D,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AACjD,MAAM,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAC9C,MAAM,YAAY,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAChD,MAAM,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;AAC5C,MAAM,iBAAiB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;AAE3D,MAAM,CAAC,OAAO,GAAG,MAAM,MAAO,SAAQ,YAAY;IAC9C,MAAM,CAAC,MAAM,CAAC,MAAM;QAChB,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAED,YAAY,MAAM;QACd,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAE3D,IAAI,CAAC,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpD,gBAAgB,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE;YACrC,YAAY,CAAC,gBAAgB;YAC7B,YAAY,CAAC,eAAe;YAC5B,YAAY,CAAC,gBAAgB;SAChC,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE;QACzG,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,KAAK,SAAS,CAAC,CAAC;QAC1D,MAAM,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QAC9G,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,YAAY,CAAC,CAAC;QAEzF,OAAO,MAAM,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;IAC3E,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/worker/runner/sequence-test-parser.d.ts b/build/src/worker/runner/sequence-test-parser.d.ts new file mode 100644 index 000000000..ce7cde4da --- /dev/null +++ b/build/src/worker/runner/sequence-test-parser.d.ts @@ -0,0 +1,14 @@ +export = SequenceTestParser; +declare class SequenceTestParser extends EventEmitter { + static create(...args: any[]): import("./sequence-test-parser"); + constructor(config: any); + _parser: SimpleTestParser; + _queue: fastq.queueAsPromised; + parse({ file, browserId }: { + file: any; + browserId: any; + }): Promise; +} +import { EventEmitter } from "events"; +import SimpleTestParser = require("./simple-test-parser"); +import fastq = require("fastq"); diff --git a/build/src/worker/runner/sequence-test-parser.js b/build/src/worker/runner/sequence-test-parser.js new file mode 100644 index 000000000..e0e10f0d7 --- /dev/null +++ b/build/src/worker/runner/sequence-test-parser.js @@ -0,0 +1,21 @@ +"use strict"; +const { EventEmitter } = require("events"); +const { passthroughEvent } = require("../../events/utils"); +const SimpleTestParser = require("./simple-test-parser"); +const { WorkerEvents } = require("../../events"); +const fastq = require("fastq"); +module.exports = class SequenceTestParser extends EventEmitter { + static create(...args) { + return new this(...args); + } + constructor(config) { + super(); + this._parser = SimpleTestParser.create(config); + passthroughEvent(this._parser, this, [WorkerEvents.BEFORE_FILE_READ, WorkerEvents.AFTER_FILE_READ]); + this._queue = fastq.promise(fn => fn(), 1); + } + async parse({ file, browserId }) { + return this._queue.push(() => this._parser.parse({ file, browserId })); + } +}; +//# sourceMappingURL=sequence-test-parser.js.map \ No newline at end of file diff --git a/build/src/worker/runner/sequence-test-parser.js.map b/build/src/worker/runner/sequence-test-parser.js.map new file mode 100644 index 000000000..4a129b491 --- /dev/null +++ b/build/src/worker/runner/sequence-test-parser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"sequence-test-parser.js","sourceRoot":"","sources":["../../../../src/worker/runner/sequence-test-parser.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC3C,MAAM,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAC3D,MAAM,gBAAgB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;AACzD,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AACjD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAE/B,MAAM,CAAC,OAAO,GAAG,MAAM,kBAAmB,SAAQ,YAAY;IAC1D,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI;QACjB,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,YAAY,MAAM;QACd,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC/C,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC,CAAC;QAEpG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE;QAC3B,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IAC3E,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/worker/runner/simple-test-parser.d.ts b/build/src/worker/runner/simple-test-parser.d.ts new file mode 100644 index 000000000..a801575d9 --- /dev/null +++ b/build/src/worker/runner/simple-test-parser.d.ts @@ -0,0 +1,11 @@ +export = SimpleTestParser; +declare class SimpleTestParser extends EventEmitter { + static create(...args: any[]): import("./simple-test-parser"); + constructor(config: any); + _config: any; + parse({ file, browserId }: { + file: any; + browserId: any; + }): Promise; +} +import { EventEmitter } from "events"; diff --git a/build/src/worker/runner/simple-test-parser.js b/build/src/worker/runner/simple-test-parser.js new file mode 100644 index 000000000..798bf4079 --- /dev/null +++ b/build/src/worker/runner/simple-test-parser.js @@ -0,0 +1,21 @@ +"use strict"; +const { EventEmitter } = require("events"); +const { passthroughEvent } = require("../../events/utils"); +const { TestParser } = require("../../test-reader/test-parser"); +const { WorkerEvents } = require("../../events"); +module.exports = class SimpleTestParser extends EventEmitter { + static create(...args) { + return new this(...args); + } + constructor(config) { + super(); + this._config = config; + } + async parse({ file, browserId }) { + const parser = new TestParser(); + passthroughEvent(parser, this, [WorkerEvents.BEFORE_FILE_READ, WorkerEvents.AFTER_FILE_READ]); + await parser.loadFiles([file], this._config); + return parser.parse([file], { browserId, config: this._config.forBrowser(browserId) }); + } +}; +//# sourceMappingURL=simple-test-parser.js.map \ No newline at end of file diff --git a/build/src/worker/runner/simple-test-parser.js.map b/build/src/worker/runner/simple-test-parser.js.map new file mode 100644 index 000000000..6f1daf1e8 --- /dev/null +++ b/build/src/worker/runner/simple-test-parser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"simple-test-parser.js","sourceRoot":"","sources":["../../../../src/worker/runner/simple-test-parser.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC3C,MAAM,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAC3D,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,+BAA+B,CAAC,CAAC;AAChE,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAEjD,MAAM,CAAC,OAAO,GAAG,MAAM,gBAAiB,SAAQ,YAAY;IACxD,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI;QACjB,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,YAAY,MAAM;QACd,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE;QAC3B,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAEhC,gBAAgB,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC,CAAC;QAE9F,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAE7C,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAC3F,CAAC;CACJ,CAAC"} \ No newline at end of file diff --git a/build/src/worker/runner/test-runner/execution-thread.d.ts b/build/src/worker/runner/test-runner/execution-thread.d.ts new file mode 100644 index 000000000..68245170f --- /dev/null +++ b/build/src/worker/runner/test-runner/execution-thread.d.ts @@ -0,0 +1,21 @@ +export = ExecutionThread; +declare class ExecutionThread { + static create(...args: any[]): import("./execution-thread"); + constructor({ test, browser, hermioneCtx, screenshooter }: { + test: any; + browser: any; + hermioneCtx: any; + screenshooter: any; + }); + _hermioneCtx: any; + _screenshooter: any; + _ctx: { + browser: any; + currentTest: any; + }; + _runtimeConfig: any; + _isReplBeforeTestOpened: boolean; + run(runnable: any): globalThis.Promise; + _call(runnable: any): globalThis.Promise; + _setExecutionContext(context: any): void; +} diff --git a/build/src/worker/runner/test-runner/execution-thread.js b/build/src/worker/runner/test-runner/execution-thread.js new file mode 100644 index 000000000..224b807e7 --- /dev/null +++ b/build/src/worker/runner/test-runner/execution-thread.js @@ -0,0 +1,64 @@ +"use strict"; +const Promise = require("bluebird"); +const RuntimeConfig = require("../../../config/runtime-config"); +const logger = require("../../../utils/logger"); +module.exports = class ExecutionThread { + static create(...args) { + return new this(...args); + } + constructor({ test, browser, hermioneCtx, screenshooter }) { + this._hermioneCtx = hermioneCtx; + this._screenshooter = screenshooter; + this._ctx = { + browser: browser.publicAPI, + currentTest: test, + }; + this._runtimeConfig = RuntimeConfig.getInstance(); + this._isReplBeforeTestOpened = false; + } + async run(runnable) { + this._setExecutionContext(Object.assign(runnable, { + hermioneCtx: this._hermioneCtx, + ctx: this._ctx, + })); + try { + await this._call(runnable); + } + catch (err) { + this._ctx.currentTest.err = this._ctx.currentTest.err || err; + throw err; + } + finally { + this._setExecutionContext(null); + } + } + async _call(runnable) { + const { replMode } = this._runtimeConfig; + if (replMode?.beforeTest && !this._isReplBeforeTestOpened) { + await this._ctx.browser.switchToRepl(); + this._isReplBeforeTestOpened = true; + } + let fnPromise = Promise.method(runnable.fn).call(this._ctx, this._ctx); + if (runnable.timeout) { + const msg = `'${runnable.fullTitle()}' timed out after ${runnable.timeout} ms`; + fnPromise = fnPromise.timeout(runnable.timeout, msg); + } + return fnPromise + .tapCatch(async (e) => { + if (replMode?.onFail) { + logger.log("Caught error:", e); + await this._ctx.browser.switchToRepl(); + } + return this._screenshooter.extendWithScreenshot(e); + }) + .finally(async () => { + if (this._hermioneCtx.assertViewResults && this._hermioneCtx.assertViewResults.hasFails()) { + await this._screenshooter.captureScreenshotOnAssertViewFail(); + } + }); + } + _setExecutionContext(context) { + Object.getPrototypeOf(this._ctx.browser).executionContext = context; + } +}; +//# sourceMappingURL=execution-thread.js.map \ No newline at end of file diff --git a/build/src/worker/runner/test-runner/execution-thread.js.map b/build/src/worker/runner/test-runner/execution-thread.js.map new file mode 100644 index 000000000..f8886a684 --- /dev/null +++ b/build/src/worker/runner/test-runner/execution-thread.js.map @@ -0,0 +1 @@ +{"version":3,"file":"execution-thread.js","sourceRoot":"","sources":["../../../../../src/worker/runner/test-runner/execution-thread.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/worker/runner/test-runner/hook-runner.d.ts b/build/src/worker/runner/test-runner/hook-runner.d.ts new file mode 100644 index 000000000..f452b5dc8 --- /dev/null +++ b/build/src/worker/runner/test-runner/hook-runner.d.ts @@ -0,0 +1,15 @@ +export = HookRunner; +declare class HookRunner { + static create(...args: any[]): import("./hook-runner"); + constructor(test: any, executionThread: any); + _test: any; + _executionThread: any; + _failedSuite: any; + hasBeforeEachHooks(): any; + runBeforeEachHooks(): globalThis.Promise; + _runBeforeEachHooks(suite: any): globalThis.Promise; + _runHook(hook: any): any; + hasAfterEachHooks(): any; + runAfterEachHooks(): globalThis.Promise; + _runAfterEachHooks(suite: any): globalThis.Promise; +} diff --git a/build/src/worker/runner/test-runner/hook-runner.js b/build/src/worker/runner/test-runner/hook-runner.js new file mode 100644 index 000000000..0a5bc3192 --- /dev/null +++ b/build/src/worker/runner/test-runner/hook-runner.js @@ -0,0 +1,65 @@ +"use strict"; +const Promise = require("bluebird"); +module.exports = class HookRunner { + static create(...args) { + return new this(...args); + } + constructor(test, executionThread) { + this._test = test; + this._executionThread = executionThread; + this._failedSuite = null; + } + hasBeforeEachHooks() { + const suite = this._test.parent; + return hasHooks(suite, "beforeEach"); + } + async runBeforeEachHooks() { + await this._runBeforeEachHooks(this._test.parent); + } + async _runBeforeEachHooks(suite) { + if (suite.parent) { + await this._runBeforeEachHooks(suite.parent); + } + try { + await Promise.mapSeries(suite.beforeEachHooks, hook => this._runHook(hook)); + } + catch (e) { + this._failedSuite = suite; + throw e; + } + } + _runHook(hook) { + return this._executionThread.run(hook.clone()); + } + hasAfterEachHooks() { + const suite = this._failedSuite || this._test.parent; + return hasHooks(suite, "afterEach"); + } + async runAfterEachHooks() { + await this._runAfterEachHooks(this._failedSuite || this._test.parent); + } + async _runAfterEachHooks(suite) { + let error; + try { + await Promise.mapSeries(suite.afterEachHooks, hook => this._runHook(hook)); + } + catch (e) { + error = e; + } + if (suite.parent) { + try { + await this._runAfterEachHooks(suite.parent); + } + catch (e) { + error = error || e; + } + } + if (error) { + throw error; + } + } +}; +function hasHooks(suite, hookType) { + return suite && (suite[`${hookType}Hooks`].length || hasHooks(suite.parent, hookType)); +} +//# sourceMappingURL=hook-runner.js.map \ No newline at end of file diff --git a/build/src/worker/runner/test-runner/hook-runner.js.map b/build/src/worker/runner/test-runner/hook-runner.js.map new file mode 100644 index 000000000..4e561d886 --- /dev/null +++ b/build/src/worker/runner/test-runner/hook-runner.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hook-runner.js","sourceRoot":"","sources":["../../../../../src/worker/runner/test-runner/hook-runner.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEpC,MAAM,CAAC,OAAO,GAAG,MAAM,UAAU;IAC7B,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI;QACjB,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,YAAY,IAAI,EAAE,eAAe;QAC7B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAC;QAExC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;IAC7B,CAAC;IAED,kBAAkB;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAEhC,OAAO,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,kBAAkB;QACpB,MAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,KAAK;QAC3B,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACf,MAAM,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,CAAC;YACD,MAAM,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,eAAe,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAChF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;YAC1B,MAAM,CAAC,CAAC;QACZ,CAAC;IACL,CAAC;IAED,QAAQ,CAAC,IAAI;QACT,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,iBAAiB;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAErD,OAAO,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,iBAAiB;QACnB,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1E,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,KAAK;QAC1B,IAAI,KAAK,CAAC;QAEV,IAAI,CAAC;YACD,MAAM,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,cAAc,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/E,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,KAAK,GAAG,CAAC,CAAC;QACd,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACf,IAAI,CAAC;gBACD,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAChD,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACT,KAAK,GAAG,KAAK,IAAI,CAAC,CAAC;YACvB,CAAC;QACL,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACR,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;CACJ,CAAC;AAEF,SAAS,QAAQ,CAAC,KAAK,EAAE,QAAQ;IAC7B,OAAO,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAC,MAAM,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC3F,CAAC"} \ No newline at end of file diff --git a/build/src/worker/runner/test-runner/index.d.ts b/build/src/worker/runner/test-runner/index.d.ts new file mode 100644 index 000000000..01cb2c951 --- /dev/null +++ b/build/src/worker/runner/test-runner/index.d.ts @@ -0,0 +1,20 @@ +export = TestRunner; +declare class TestRunner { + static create(...args: any[]): import("."); + constructor(test: any, config: any, browserAgent: any); + _test: any; + _config: any; + _browserAgent: any; + run({ sessionId, sessionCaps, sessionOpts, testXReqId }: { + sessionId: any; + sessionCaps: any; + sessionOpts: any; + testXReqId: any; + }): Promise<{ + hermioneCtx: any; + meta: any; + }>; + _resetCursorPosition({ publicAPI: session }: { + publicAPI: any; + }): Promise; +} diff --git a/build/src/worker/runner/test-runner/index.js b/build/src/worker/runner/test-runner/index.js new file mode 100644 index 000000000..533c39aef --- /dev/null +++ b/build/src/worker/runner/test-runner/index.js @@ -0,0 +1,111 @@ +/* global document */ +"use strict"; +const _ = require("lodash"); +const HookRunner = require("./hook-runner"); +const ExecutionThread = require("./execution-thread"); +const OneTimeScreenshooter = require("./one-time-screenshooter"); +const { AssertViewError } = require("../../../browser/commands/assert-view/errors/assert-view-error"); +const history = require("../../../browser/history"); +const { SAVE_HISTORY_MODE } = require("../../../constants/config"); +module.exports = class TestRunner { + static create(...args) { + return new this(...args); + } + constructor(test, config, browserAgent) { + this._test = test.clone(); + this._test.hermioneCtx = _.cloneDeep(test.hermioneCtx); + this._config = config; + this._browserAgent = browserAgent; + } + async run({ sessionId, sessionCaps, sessionOpts, testXReqId }) { + const test = this._test; + const hermioneCtx = test.hermioneCtx || {}; + let browser; + try { + browser = await this._browserAgent.getBrowser({ sessionId, sessionCaps, sessionOpts, testXReqId }); + } + catch (e) { + throw Object.assign(e, { hermioneCtx }); + } + const screenshooter = OneTimeScreenshooter.create(this._config, browser); + const executionThread = ExecutionThread.create({ test, browser, hermioneCtx, screenshooter }); + const hookRunner = HookRunner.create(test, executionThread); + const { callstackHistory } = browser; + let error; + try { + const { resetCursor } = browser.config; + const shouldRunBeforeEach = resetCursor || hookRunner.hasBeforeEachHooks(); + if (shouldRunBeforeEach) { + await history.runGroup(callstackHistory, "beforeEach", async () => { + if (resetCursor) { + // TODO: make it on browser.init when "actions" method will be implemented in all webdrivers + await history.runGroup(callstackHistory, "resetCursor", () => this._resetCursorPosition(browser)); + } + await hookRunner.runBeforeEachHooks(); + }); + } + await executionThread.run(test); + } + catch (e) { + error = e; + } + if (isSessionBroken(error, this._config)) { + browser.markAsBroken(); + } + try { + const needsAfterEach = hookRunner.hasAfterEachHooks(); + if (needsAfterEach) { + await history.runGroup(callstackHistory, "afterEach", () => hookRunner.runAfterEachHooks()); + } + } + catch (e) { + error = error || e; + } + const assertViewResults = hermioneCtx.assertViewResults; + if (!error && assertViewResults && assertViewResults.hasFails()) { + error = new AssertViewError(); + if (screenshooter.getScreenshot()) { + error.screenshot = screenshooter.getScreenshot(); + } + } + // we need to check session twice: + // 1. before afterEach hook to prevent work with broken sessions + // 2. after collecting all assertView errors (including afterEach section) + if (!browser.state.isBroken && isSessionBroken(error, this._config)) { + browser.markAsBroken(); + } + hermioneCtx.assertViewResults = assertViewResults ? assertViewResults.toRawObject() : []; + const { meta } = browser; + const commandsHistory = callstackHistory ? callstackHistory.release() : []; + const results = { + hermioneCtx, + meta, + }; + switch (browser.config.saveHistoryMode) { + case SAVE_HISTORY_MODE.ALL: + case error && SAVE_HISTORY_MODE.ONLY_FAILED: + results.history = commandsHistory; + break; + } + this._browserAgent.freeBrowser(browser); + if (error) { + throw Object.assign(error, results); + } + return results; + } + async _resetCursorPosition({ publicAPI: session }) { + const body = await session.$("body"); + if (!body) { + throw new Error('There is no "body" element on the page when resetting cursor position'); + } + await body.scrollIntoView(); + const { x = 0, y = 0 } = await session.execute(function () { + return document.body.getBoundingClientRect(); + }); + await body.moveTo({ xOffset: -x, yOffset: -y }); + } +}; +function isSessionBroken(error, { system: { patternsOnReject } }) { + return error && patternsOnReject.some(p => new RegExp(p).test(error.message)); +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/worker/runner/test-runner/index.js.map b/build/src/worker/runner/test-runner/index.js.map new file mode 100644 index 000000000..84bd30238 --- /dev/null +++ b/build/src/worker/runner/test-runner/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/worker/runner/test-runner/index.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/src/worker/runner/test-runner/one-time-screenshooter.d.ts b/build/src/worker/runner/test-runner/one-time-screenshooter.d.ts new file mode 100644 index 000000000..9d1b6006e --- /dev/null +++ b/build/src/worker/runner/test-runner/one-time-screenshooter.d.ts @@ -0,0 +1,38 @@ +export = OneTimeScreenshooter; +declare class OneTimeScreenshooter { + static create(...args: any[]): import("./one-time-screenshooter"); + constructor(config: any, browser: any); + _config: any; + _browser: any; + _screenshot: void | { + base64: any; + size: any; + } | null; + _alreadyTryToScreenshot: boolean; + _screenshooter: ScreenShooter; + _screenshotTimeout: any; + extendWithScreenshot(error: any): globalThis.Promise; + captureScreenshotOnAssertViewFail(): globalThis.Promise; + _captureScreenshot(): globalThis.Promise; + _makeScreenshot(): globalThis.Promise<{ + base64: any; + size: any; + }>; + _makeFullPageScreenshot(): globalThis.Promise<{ + base64: any; + size: any; + }>; + _getPageSize(): globalThis.Promise; + _makeViewportScreenshot(): globalThis.Promise<{ + base64: any; + size: { + width: number; + height: number; + }; + }>; + getScreenshot(): void | { + base64: any; + size: any; + } | null; +} +import ScreenShooter = require("../../../browser/screen-shooter"); diff --git a/build/src/worker/runner/test-runner/one-time-screenshooter.js b/build/src/worker/runner/test-runner/one-time-screenshooter.js new file mode 100644 index 000000000..d48246b80 --- /dev/null +++ b/build/src/worker/runner/test-runner/one-time-screenshooter.js @@ -0,0 +1,88 @@ +"use strict"; +const Promise = require("bluebird"); +const Image = require("../../../image"); +const ScreenShooter = require("../../../browser/screen-shooter"); +const logger = require("../../../utils/logger"); +module.exports = class OneTimeScreenshooter { + static create(...args) { + return new this(...args); + } + constructor(config, browser) { + this._config = config; + this._browser = browser; + this._screenshot = null; + this._alreadyTryToScreenshot = false; + this._screenshooter = new ScreenShooter(browser); + this._screenshotTimeout = this._config.takeScreenshotOnFailsTimeout || this._config.httpTimeout; + } + async extendWithScreenshot(error) { + if (!error.screenshot && this._config.takeScreenshotOnFails.testFail) { + await this._captureScreenshot(); + if (this._screenshot) { + error.screenshot = this._screenshot; + } + } + return error; + } + async captureScreenshotOnAssertViewFail() { + if (!this._config.takeScreenshotOnFails.assertViewFail) { + return; + } + return this._captureScreenshot(); + } + async _captureScreenshot() { + if (this._alreadyTryToScreenshot) { + return; + } + this._alreadyTryToScreenshot = true; + this._browser.setHttpTimeout(this._screenshotTimeout); + this._screenshot = await Promise.resolve(this._makeScreenshot()) + .timeout(this._screenshotTimeout, `timed out after ${this._screenshotTimeout} ms`) + .catch(e => logger.warn(`WARN: Failed to take screenshot on test fail: ${e}`)); + this._browser.restoreHttpTimeout(); + } + async _makeScreenshot() { + if (this._config.takeScreenshotOnFailsMode === "fullpage") { + return this._makeFullPageScreenshot(); + } + return this._makeViewportScreenshot(); + } + async _makeFullPageScreenshot() { + const pageSize = await this._getPageSize(); + const page = await this._browser.prepareScreenshot([ + { + left: 0, + top: 0, + width: pageSize.width, + height: pageSize.height, + }, + ], { + ignoreSelectors: [], + captureElementFromTop: true, + allowViewportOverflow: true, + }); + const image = await this._screenshooter.capture(page, { + compositeImage: true, + allowViewportOverflow: true, + }); + const { data, size } = await image.toPngBuffer(); + const base64 = data.toString("base64"); + return { base64, size }; + } + async _getPageSize() { + return this._browser.evalScript(`{ + height: document.documentElement.scrollHeight, + width: document.documentElement.scrollWidth + }`); + } + async _makeViewportScreenshot() { + const base64 = await this._browser.publicAPI.takeScreenshot(); + const image = Image.fromBase64(base64); + const size = await image.getSize(); + return { base64, size }; + } + getScreenshot() { + return this._screenshot; + } +}; +//# sourceMappingURL=one-time-screenshooter.js.map \ No newline at end of file diff --git a/build/src/worker/runner/test-runner/one-time-screenshooter.js.map b/build/src/worker/runner/test-runner/one-time-screenshooter.js.map new file mode 100644 index 000000000..d17b973e0 --- /dev/null +++ b/build/src/worker/runner/test-runner/one-time-screenshooter.js.map @@ -0,0 +1 @@ +{"version":3,"file":"one-time-screenshooter.js","sourceRoot":"","sources":["../../../../../src/worker/runner/test-runner/one-time-screenshooter.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/typings/api.d.ts b/build/typings/api.d.ts new file mode 100644 index 000000000..6b6825de0 --- /dev/null +++ b/build/typings/api.d.ts @@ -0,0 +1,4 @@ +declare const it: TestDefinition; +declare const describe: SuiteDefinition; +declare const beforeEach: TestHookDefinition; +declare const afterEach: TestHookDefinition; diff --git a/build/typings/global.d.ts b/build/typings/global.d.ts new file mode 100644 index 000000000..6fe5974d2 --- /dev/null +++ b/build/typings/global.d.ts @@ -0,0 +1,35 @@ +// eslint-disable-next-line @typescript-eslint/triple-slash-reference +/// +/// +/// + +interface TestFunctionCtx { + browser: WebdriverIO.Browser; + currentTest: Mocha.Test; +} + +type TestFunction = (this: TestFunctionCtx, ctx: T) => void | Promise; + +interface TestHookDefinition { + = TestFunctionCtx>(fn?: TestFunction): void; +} + +interface TestDefinition { + = TestFunctionCtx>(title: string, fn?: TestFunction): Mocha.Test; + + only: (title: string, fn?: TestFunction) => Mocha.Test; + + skip: (title: string, fn?: TestFunction) => Mocha.Test; +} + +interface SuiteDefinition { + (title: string, fn: (this: Mocha.Suite) => void): Mocha.Suite; + + only: (title: string, fn: (this: Mocha.Suite) => void) => Mocha.Suite; + skip: (title: string, fn: (this: Mocha.Suite) => void) => Mocha.Suite; +} + +declare namespace globalThis { + // eslint-disable-next-line no-var + var expect: ExpectWebdriverIO.Expect; +}