diff --git a/.eslintignore b/.eslintignore index a9a2530..55779fb 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1,2 @@ /lib/browser/client-scripts/calibrate.min.js +/build diff --git a/.gitignore b/.gitignore index 4782ef0..73fa3ea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules +build *.log /lib/browser/client-scripts/calibrate.min.js diff --git a/index.js b/index.js deleted file mode 100644 index 8218e40..0000000 --- a/index.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; - -module.exports = { - BaseStats: require('./lib/base-stats'), - SetsBuilder: require('./lib/sets-builder'), - config: { - options: require('./lib/config/options') - }, - Calibrator: require('./lib/calibrator'), - BrowserPool: require('./lib/browser-pool'), - BrowserAgent: require('./lib/browser-agent'), - Image: require('./lib/image'), - temp: require('./lib/temp'), - errors: require('./lib/errors'), - events: require('./lib/events'), - promiseUtils: require('./lib/promise-utils'), - clientBridge: require('./lib/client-bridge'), - coverage: { - coverageLevel: require('./lib/coverage/coverage-level') - }, - browser: { - Camera: require('./lib/browser/camera') - }, - ScreenShooter: require('./lib/screen-shooter'), - Viewport: require('./lib/screen-shooter/viewport'), - CoordValidator: require('./lib/screen-shooter/viewport/coord-validator') -}; diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..07b0b59 --- /dev/null +++ b/index.ts @@ -0,0 +1,26 @@ +export { default as BaseStats } from "./lib/base-stats"; +export { default as SetsBuilder } from "./lib/sets-builder"; + +import options from "./lib/config/options"; +export const config = { options }; + +export { default as Calibrator } from "./lib/calibrator"; +export * as BrowserPool from "./lib/browser-pool"; +export { default as BrowserAgent } from "./lib/browser-agent"; +export { default as Image } from "./lib/image"; +export * as temp from "./lib/temp"; +export * as errors from "./lib/errors"; +export * as events from "./lib/events"; +export * as promiseUtils from "./lib/promise-utils"; +export * as clientBridge from "./lib/client-bridge"; + +import * as coverageLevel from "./lib/coverage/coverage-level"; +export const coverage = { coverageLevel }; + +import Camera from "./lib/browser/camera"; +export const browser = { Camera }; +export { Camera }; + +export { default as ScreenShooter } from "./lib/screen-shooter"; +export { default as Viewport } from "./lib/screen-shooter/viewport"; +export { default as CoordValidator } from "./lib/screen-shooter/viewport/coord-validator"; diff --git a/lib/base-stats/index.js b/lib/base-stats/index.js deleted file mode 100644 index 7c627c2..0000000 --- a/lib/base-stats/index.js +++ /dev/null @@ -1,61 +0,0 @@ -'use strict'; - -const _ = require('lodash'); - -module.exports = class BaseStats { - static create(...args) { - return new this(...args); - } - - constructor(statNames) { - this._tests = new Set(); - this._retries = 0; - this._statNames = statNames; - - this._stats = this._fillEmptyStats(); - } - - addPassed(test) { - this._addStat(this._statNames.PASSED, test); - } - - addFailed(test) { - this._addStat(this._statNames.FAILED, test); - } - - addSkipped(test) { - this._addStat(this._statNames.SKIPPED, test); - } - - addRetries() { - this._retries++; - } - - _addStat(stat, test, statsStorage = this._stats, testsStorage = this._tests) { - const key = `${this._buildSuiteKey(test)} ${this._buildStateKey(test)}`; - - statsStorage[stat]++; - testsStorage.add(key); - } - - _fillEmptyStats() { - const statValues = _.values(this._statNames); - - return _.zipObject(statValues, Array(statValues.length).fill(0)); - } - - _buildStateKey() { - throw new Error('Method must be implemented in child classes'); - } - - _buildSuiteKey() { - throw new Error('Method must be implemented in child classes'); - } - - getResult() { - return _.extend(this._stats, { - total: this._tests.size, - retries: this._retries - }); - } -}; diff --git a/lib/base-stats/index.ts b/lib/base-stats/index.ts new file mode 100644 index 0000000..028ddf2 --- /dev/null +++ b/lib/base-stats/index.ts @@ -0,0 +1,72 @@ +import _ from "lodash"; + +type StatNames = Record, Lowercase>; + +type Stats = { [StatName in StatNames[keyof StatNames]]: number }; +type StatsResult = Stats & { + total: number; + retries: number; +}; + +export default class BaseStats { + private _tests: Set; + private _retries: number; + private _statNames: StatNames; + private _stats: Stats; + + public static create(statNames: StatNames): BaseStats { + return new this(statNames); + } + + constructor(statNames: StatNames) { + this._tests = new Set(); + this._retries = 0; + this._statNames = statNames; + + this._stats = this._fillEmptyStats(); + } + + public addPassed(test: unknown) { + this._addStat(this._statNames.PASSED, test); + } + + public addFailed(test: unknown) { + this._addStat(this._statNames.FAILED, test); + } + + public addSkipped(test: unknown) { + this._addStat(this._statNames.SKIPPED, test); + } + + public addRetries() { + this._retries++; + } + + private _addStat(stat: StatNames[keyof StatNames], test: unknown, statsStorage = this._stats, testsStorage = this._tests) { + const key = `${this._buildSuiteKey(test)} ${this._buildStateKey(test)}`; + + statsStorage[stat]++; + testsStorage.add(key); + } + + private _fillEmptyStats(): Stats { + const statValues = _.values(this._statNames); + + return _.zipObject(statValues, Array(statValues.length).fill(0)) as Stats; + } + + private _buildStateKey(_test: unknown): string { + throw new Error('Method must be implemented in child classes'); + } + + private _buildSuiteKey(_test: unknown): string { + throw new Error('Method must be implemented in child classes'); + } + + public getResult(): StatsResult { + return _.extend(this._stats, { + total: this._tests.size, + retries: this._retries + }); + } +}; diff --git a/lib/browser-agent/index.js b/lib/browser-agent/index.js deleted file mode 100644 index e9e7721..0000000 --- a/lib/browser-agent/index.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -const _ = require('lodash'); - -module.exports = class BrowserAgent { - static create(browserId, pool) { - return new BrowserAgent(browserId, pool); - } - - constructor(browserId, pool) { - this.browserId = browserId; - this._pool = pool; - this._sessions = []; - } - - getBrowser(opts) { - return this._pool.getBrowser(this.browserId, opts) - .then((browser) => { - if (_.includes(this._sessions, browser.sessionId)) { - return this.freeBrowser(browser, {force: true}).then(() => this.getBrowser(opts)); - } - - this._sessions.push(browser.sessionId); - return browser; - }); - } - - freeBrowser(browser, opts) { - return this._pool.freeBrowser(browser, opts); - } -}; diff --git a/lib/browser-agent/index.ts b/lib/browser-agent/index.ts new file mode 100644 index 0000000..4121e50 --- /dev/null +++ b/lib/browser-agent/index.ts @@ -0,0 +1,34 @@ +import _ from 'lodash'; + +import type { Pool } from '../types/pool'; +import type { NewBrowser } from '../types/new-browser'; + +export default class BrowserAgent { + private _sessions: Array; + + public static create(browserId: string, pool: Pool): BrowserAgent { + return new BrowserAgent(browserId, pool); + } + + constructor(public browserId: string, private _pool: Pool) { + this._sessions = []; + } + + public async getBrowser(opts: any): Promise { + const browser = await this._pool.getBrowser(this.browserId, opts); + + if (_.includes(this._sessions, browser.sessionId)) { + await this.freeBrowser(browser, {force: true}); + + return this.getBrowser(opts); + } + + this._sessions.push(browser.sessionId); + + return browser; + } + + public async freeBrowser(browser: NewBrowser, opts: any): Promise { + return this._pool.freeBrowser(browser, opts); + } +} diff --git a/lib/browser-pool/basic-pool.js b/lib/browser-pool/basic-pool.js deleted file mode 100644 index b8d9e88..0000000 --- a/lib/browser-pool/basic-pool.js +++ /dev/null @@ -1,65 +0,0 @@ -'use strict'; - -const _ = require('lodash'); -const Promise = require('bluebird'); -const CancelledError = require('../errors/cancelled-error'); -const Pool = require('./pool'); -const debug = require('debug'); - -module.exports = class BasicPool extends Pool { - static create(BrowserManager, opts) { - return new BasicPool(BrowserManager, opts); - } - - constructor(BrowserManager, opts) { - super(); - - this._browserMgr = BrowserManager; - this.log = debug(`${opts.logNamespace}:pool:basic`); - - this._activeSessions = {}; - } - - getBrowser(id, opts = {}) { - const {version} = opts; - const browser = this._browserMgr.create(id, version); - - return this._browserMgr.start(browser) - .then(() => this.log(`browser ${browser.fullId} started`)) - .then(() => this._browserMgr.onStart(browser)) - .then(() => { - if (this._cancelled) { - return Promise.reject(new CancelledError()); - } - - this._activeSessions[browser.sessionId] = browser; - }) - .then(() => browser.reset()) - .then(() => browser) - .catch(async (e) => { - if (browser.publicAPI) { - await this.freeBrowser(browser); - } - - return Promise.reject(e); - }); - } - - freeBrowser(browser) { - delete this._activeSessions[browser.sessionId]; - - this.log(`stop browser ${browser.fullId}`); - - return this._browserMgr.onQuit(browser) - .catch((err) => console.warn(err && err.stack || err)) - .then(() => this._browserMgr.quit(browser)); - } - - cancel() { - this._cancelled = true; - - _.forEach(this._activeSessions, (browser) => this._browserMgr.quit(browser)); - - this._activeSessions = {}; - } -}; diff --git a/lib/browser-pool/basic-pool.ts b/lib/browser-pool/basic-pool.ts new file mode 100644 index 0000000..6121a1d --- /dev/null +++ b/lib/browser-pool/basic-pool.ts @@ -0,0 +1,72 @@ +import Bluebird from 'bluebird'; +import debug from 'debug'; +import _ from 'lodash'; + +import CancelledError from '../errors/cancelled-error'; + +import type { BrowserManager } from '.'; +import type { Pool } from '../types/pool'; +import type { NewBrowser } from '../types/new-browser'; + +export default class BasicPool implements Pool { + public log: debug.Debugger; + private _browserMgr: BrowserManager; + private _activeSessions: Record; + private _cancelled?: boolean; + + public static create(browserManager: BrowserManager, opts: any): BasicPool { + return new BasicPool(browserManager, opts); + } + + constructor(browserManager: BrowserManager, opts: any) { + this._browserMgr = browserManager; + this.log = debug(`${opts.logNamespace}:pool:basic`); + + this._activeSessions = {}; + } + + public getBrowser(id: string, opts: any = {}): Bluebird { + const {version} = opts; + const browser = this._browserMgr.create(id, version); + + return this._browserMgr.start(browser) + .then(() => this.log(`browser ${browser.fullId} started`)) + .then(() => this._browserMgr.onStart(browser)) + .then(() => { + if (this._cancelled) { + return Bluebird.reject(new CancelledError()); + } + + return this._activeSessions[browser.sessionId] = browser; + }) + .then(() => browser.reset()) + .then(() => browser) + .catch(async (e: unknown) => { + if (browser.publicAPI) { + await this.freeBrowser(browser); + } + + return Bluebird.reject(e); + }); + } + + public freeBrowser(browser: NewBrowser): Bluebird { + delete this._activeSessions[browser.sessionId]; + + this.log(`stop browser ${browser.fullId}`); + + return this._browserMgr.onQuit(browser) + .catch((err: unknown) => { + console.warn(err instanceof Error ? err.stack : err); + }) + .then(() => this._browserMgr.quit(browser)); + } + + public cancel(): void { + this._cancelled = true; + + _.forEach(this._activeSessions, (browser) => this._browserMgr.quit(browser)); + + this._activeSessions = {}; + } +} diff --git a/lib/browser-pool/caching-pool.js b/lib/browser-pool/caching-pool.ts similarity index 70% rename from lib/browser-pool/caching-pool.js rename to lib/browser-pool/caching-pool.ts index 6183a57..3a44766 100644 --- a/lib/browser-pool/caching-pool.js +++ b/lib/browser-pool/caching-pool.ts @@ -1,20 +1,25 @@ -'use strict'; +import Bluebird from 'bluebird'; +import debug from 'debug'; -const Promise = require('bluebird'); -const Pool = require('./pool'); -const LimitedUseSet = require('./limited-use-set'); -const debug = require('debug'); -const {buildCompositeBrowserId} = require('./utils'); +import LimitedUseSet from './limited-use-set'; +import { buildCompositeBrowserId } from './utils'; -module.exports = class CachingPool extends Pool { - /** - * @constructor - * @extends BasicPool - * @param {BasicPool} underlyingPool - */ - constructor(underlyingPool, config, opts) { - super(); +import type { Pool } from '../types/pool'; +import type { NewBrowser } from '../types/new-browser'; +import type { Config } from '../types/config'; + +type CachingPoolOpts = { + logNamespace?: string; +}; +export default class CachingPool implements Pool { + public log: debug.Debugger; + public underlyingPool: Pool; + private _caches: Record>; + private _config: Config; + private _logNamespace?: string; + + constructor(underlyingPool: Pool, config: Config, opts: CachingPoolOpts) { this.log = debug(`${opts.logNamespace}:pool:caching`); this.underlyingPool = underlyingPool; this._caches = {}; @@ -22,7 +27,7 @@ module.exports = class CachingPool extends Pool { this._logNamespace = opts.logNamespace; } - _getCacheFor(id, version) { + private _getCacheFor(id: string, version: string): LimitedUseSet { const compositeId = buildCompositeBrowserId(id, version); this.log(`request for ${compositeId}`); @@ -35,7 +40,7 @@ module.exports = class CachingPool extends Pool { return this._caches[compositeId]; } - getBrowser(id, opts = {}) { + public getBrowser(id: string, opts: any = {}): Bluebird { const {version} = opts; const cache = this._getCacheFor(id, version); const browser = cache.pop(); @@ -49,15 +54,16 @@ module.exports = class CachingPool extends Pool { this.log(`has cached browser ${browser.fullId}`); return browser.reset() - .catch((e) => { - const reject = Promise.reject.bind(null, e); + .catch((e: unknown) => { + const reject = Bluebird.reject.bind(null, e); + return this.underlyingPool.freeBrowser(browser) .then(reject, reject); }) .then(() => browser); } - _initPool(browserId, version) { + private _initPool(browserId: string, version: string): void { const compositeId = buildCompositeBrowserId(browserId, version); const freeBrowser = this.underlyingPool.freeBrowser.bind(this.underlyingPool); const browserConfig = this._config.forBrowser(browserId); @@ -79,9 +85,9 @@ module.exports = class CachingPool extends Pool { * @param {Object} [options] - advanced options * @param {Boolean} [options.force] - if `true` than browser should * not be cached - * @returns {Promise} + * @returns {Bluebird} */ - freeBrowser(browser, options = {}) { + public freeBrowser(browser: NewBrowser, options: any = {}): Bluebird { const shouldFreeForNextRequest = () => { const {compositeIdForNextRequest} = options; @@ -107,8 +113,8 @@ module.exports = class CachingPool extends Pool { return cache.push(browser); } - cancel() { + public cancel(): void { this.log('cancel'); this.underlyingPool.cancel(); } -}; +} diff --git a/lib/browser-pool/index.js b/lib/browser-pool/index.js deleted file mode 100644 index 9ede0f1..0000000 --- a/lib/browser-pool/index.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -const _ = require('lodash'); -const Promise = require('bluebird'); -const BasicPool = require('./basic-pool'); -const LimitedPool = require('./limited-pool'); -const PerBrowserLimitedPool = require('./per-browser-limited-pool'); -const CachingPool = require('./caching-pool'); - -/** - * @param {Object} BrowserManager - * @param {Function} BrowserManager.start - * @param {Function} BrowserManager.onStart - * @param {Function} BrowserManager.onQuit - * @param {Function} BrowserManager.quit - * @returns {BasicPool} - */ -exports.create = function(BrowserManager, opts) { - BrowserManager = _.defaults(BrowserManager, { - onStart: () => Promise.resolve(), - onQuit: () => Promise.resolve() - }); - - var pool = BasicPool.create(BrowserManager, opts); - - pool = new CachingPool(pool, opts.config, opts); - pool = new PerBrowserLimitedPool(pool, opts.config, opts); - - if (_.isFinite(opts.config.system.parallelLimit)) { - pool = new LimitedPool(pool, { - limit: opts.config.system.parallelLimit, - logNamespace: opts.logNamespace, - isSpecificBrowserLimiter: false - }); - } - - return pool; -}; diff --git a/lib/browser-pool/index.ts b/lib/browser-pool/index.ts new file mode 100644 index 0000000..b53d3ac --- /dev/null +++ b/lib/browser-pool/index.ts @@ -0,0 +1,46 @@ +import _ from 'lodash'; +import Bluebird from 'bluebird'; + +import BasicPool from './basic-pool'; +import CachingPool from './caching-pool'; +import LimitedPool from './limited-pool'; +import PerBrowserLimitedPool from './per-browser-limited-pool'; + +import type { Pool } from '../types/pool'; +import type { Config } from '../types/config'; +import type { NewBrowser } from '../types/new-browser'; + +export type BrowserManager = { + create: (id: string, version: string) => NewBrowser; + start: (browser: NewBrowser) => Bluebird; + onStart: (browser: NewBrowser) => Bluebird; + onQuit: (browser: NewBrowser) => Bluebird; + quit: (browser: NewBrowser) => Bluebird; +}; + +type CreateBrowserManagerOpts = { + config: Config; + logNamespace: string; +}; + +export function create(browserManager: BrowserManager, opts: CreateBrowserManagerOpts): Pool { + browserManager = _.defaults(browserManager, { + onStart: () => Bluebird.resolve(), + onQuit: () => Bluebird.resolve() + }); + + let pool: Pool = BasicPool.create(browserManager, opts); + + pool = new CachingPool(pool, opts.config, opts); + pool = new PerBrowserLimitedPool(pool, opts.config, opts); + + if (_.isFinite(opts.config.system.parallelLimit)) { + pool = new LimitedPool(pool, { + limit: opts.config.system.parallelLimit, + logNamespace: opts.logNamespace, + isSpecificBrowserLimiter: false + }); + } + + return pool; +} diff --git a/lib/browser-pool/limited-pool.js b/lib/browser-pool/limited-pool.ts similarity index 64% rename from lib/browser-pool/limited-pool.js rename to lib/browser-pool/limited-pool.ts index 9111f72..194278d 100644 --- a/lib/browser-pool/limited-pool.js +++ b/lib/browser-pool/limited-pool.ts @@ -1,26 +1,43 @@ -'use strict'; - -const _ = require('lodash'); -const Promise = require('bluebird'); -const yallist = require('yallist'); -const Pool = require('./pool'); -const CancelledError = require('../errors/cancelled-error'); -const debug = require('debug'); -const {buildCompositeBrowserId} = require('./utils'); - -module.exports = class LimitedPool extends Pool { - static create(underlyingPool, opts) { +import Bluebird from 'bluebird'; +import debug from 'debug'; +import _ from 'lodash'; +import yallist from 'yallist'; + +import { buildCompositeBrowserId } from './utils'; +import CancelledError from '../errors/cancelled-error'; + +import type { Pool } from '../types/pool'; +import type { NewBrowser } from '../types/new-browser'; + +type LimitedPoolOpts = { + logNamespace?: string; + limit: number; + isSpecificBrowserLimiter?: boolean; +}; + +type Request = { + id: string; + version: string; + resolve: (browser: NewBrowser) => void; + reject: (err: any) => void; +}; + +export default class LimitedPool implements Pool { + public log: debug.Debugger; + public underlyingPool: Pool; + private _limit: number; + private _launched: number; + private _requests: number; + private _requestQueue: yallist; + private _highPriorityRequestQueue: yallist; + private _isSpecificBrowserLimiter: boolean; + + + public static create(underlyingPool: Pool, opts: LimitedPoolOpts): LimitedPool { return new LimitedPool(underlyingPool, opts); } - /** - * @extends BasicPool - * @param {Number} limit - * @param {BasicPool} underlyingPool - */ - constructor(underlyingPool, opts) { - super(); - + constructor(underlyingPool: Pool, opts: LimitedPoolOpts) { this.log = debug(`${opts.logNamespace}:pool:limited`); this.underlyingPool = underlyingPool; @@ -34,19 +51,22 @@ module.exports = class LimitedPool extends Pool { : true; } - getBrowser(id, opts = {}) { + public getBrowser(id: string, opts = {}): Bluebird { 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) => { + .catch(e => { --this._requests; - return Promise.reject(e); + + return Bluebird.reject(e); }); } - freeBrowser(browser, opts = {}) { + public freeBrowser(browser: NewBrowser, opts: any = {}): Bluebird { --this._requests; const nextRequest = this._lookAtNextRequest(); @@ -63,10 +83,10 @@ module.exports = class LimitedPool extends Pool { .finally(() => this._launchNextBrowser()); } - cancel() { + public cancel(): void { this.log('cancel'); - const reject_ = (entry) => entry.reject(new CancelledError()); + const reject_ = (entry: Request) => entry.reject(new CancelledError()); this._highPriorityRequestQueue.forEach(reject_); this._requestQueue.forEach(reject_); @@ -76,10 +96,11 @@ module.exports = class LimitedPool extends Pool { this.underlyingPool.cancel(); } - _getBrowser(id, opts = {}) { + private _getBrowser(id: string, opts: any = {}): Bluebird { if (this._launched < this._limit) { this.log('can launch one more'); this._launched++; + return this._newBrowser(id, opts); } @@ -88,30 +109,27 @@ module.exports = class LimitedPool extends Pool { const queue = opts.highPriority ? this._highPriorityRequestQueue : this._requestQueue; const {version} = opts; - return new Promise((resolve, reject) => { + return new Bluebird((resolve, reject) => { queue.push({id, version, resolve, reject}); }); } - /** - * @param {String} id - * @returns {Promise} - */ - _newBrowser(id, opts) { + private _newBrowser(id: string, opts: any): Bluebird { 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); + + return Bluebird.reject(e); }); } - _lookAtNextRequest() { + private _lookAtNextRequest(): Request | undefined { return this._highPriorityRequestQueue.get(0) || this._requestQueue.get(0); } - _launchNextBrowser() { + private _launchNextBrowser(): void { const queued = this._highPriorityRequestQueue.shift() || this._requestQueue.shift(); if (queued) { @@ -125,4 +143,4 @@ module.exports = class LimitedPool extends Pool { this._launched--; } } -}; +} diff --git a/lib/browser-pool/limited-use-set.js b/lib/browser-pool/limited-use-set.ts similarity index 55% rename from lib/browser-pool/limited-use-set.js rename to lib/browser-pool/limited-use-set.ts index 5927ad7..b0af518 100644 --- a/lib/browser-pool/limited-use-set.js +++ b/lib/browser-pool/limited-use-set.ts @@ -1,8 +1,13 @@ -'use strict'; +import Bluebird from 'bluebird'; +import debug from 'debug'; +import _ from 'lodash'; -const _ = require('lodash'); -const Promise = require('bluebird'); -const debug = require('debug'); +type LimitedUseSetOpts = { + useLimit: number; + finalize: (value: T, ...args: [...any]) => Bluebird; + formatItem?: (value: T) => any; + logNamespace?: string; +}; /** * Set implementation which allows to get and put an object @@ -10,14 +15,21 @@ const debug = require('debug'); * 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 + * @param useLimit number of times object can be popped from set * before finalizing. - * @param {Function} finalize callback which will be called when value in + * @param finalize callback which will be called when value in * set needs to be finalized. */ -module.exports = class LimitedUseSet { - constructor(opts) { - this._useCounts = new WeakMap(); +export default class LimitedUseSet { + private _useCounts: WeakMap; + private _useLimit: number; + private _finalize: (value: T) => Bluebird; + private _formatItem: (value: T) => any; + private _objects: Array; + public log: debug.Debugger; + + constructor(opts: LimitedUseSetOpts) { + this._useCounts = new WeakMap(); this._useLimit = opts.useLimit; this._finalize = opts.finalize; this._formatItem = opts.formatItem || _.identity; @@ -26,36 +38,38 @@ module.exports = class LimitedUseSet { this.log = debug(`${opts.logNamespace}:pool:limited-use-set`); } - push(value) { + public push(value: T): Bluebird { 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(); + return Bluebird.resolve(); } - _isOverLimit(value) { + private _isOverLimit(value: T): boolean { if (this._useLimit === 0) { return true; } - return this._useCounts.has(value) && this._useCounts.get(value) >= this._useLimit; + return this._useCounts.has(value) && (this._useCounts.get(value) || 0) >= this._useLimit; } - pop() { - if (this._objects.length === 0) { + public pop(): T | null { + const result = this._objects.pop(); + + if (!result) { return null; } - const result = this._objects.pop(); const useCount = this._useCounts.get(result) || 0; const formatedItem = this._formatItem(result); diff --git a/lib/browser-pool/per-browser-limited-pool.js b/lib/browser-pool/per-browser-limited-pool.js deleted file mode 100644 index 0fb84bf..0000000 --- a/lib/browser-pool/per-browser-limited-pool.js +++ /dev/null @@ -1,40 +0,0 @@ -'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, opts) { - super(); - - this.log = debug(`${opts.logNamespace}:pool:per-browser-limited`); - - const ids = config.getBrowserIds(); - this._browserPools = _.zipObject( - ids, - ids.map((id) => LimitedPool.create(underlyingPool, { - limit: config.forBrowser(id).parallelLimit, - logNamespace: opts.logNamespace - })) - ); - } - - 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()); - } -}; diff --git a/lib/browser-pool/per-browser-limited-pool.ts b/lib/browser-pool/per-browser-limited-pool.ts new file mode 100644 index 0000000..1087bb8 --- /dev/null +++ b/lib/browser-pool/per-browser-limited-pool.ts @@ -0,0 +1,49 @@ +import debug from 'debug'; +import _ from 'lodash'; + +import LimitedPool from './limited-pool'; + +import type Bluebird from 'bluebird'; + +import type { Pool } from '../types/pool'; +import type { NewBrowser } from '../types/new-browser'; +import type { Config } from '../types/config'; + +type PerBrowserLimitedPoolOpts = { + logNamespace?: string; +}; + +export default class PerBrowserLimitedPool implements Pool { + public log: debug.Debugger; + private _browserPools: Record; + + constructor(underlyingPool: Pool, config: Config, opts: PerBrowserLimitedPoolOpts) { + this.log = debug(`${opts.logNamespace}:pool:per-browser-limited`); + + const ids = config.getBrowserIds(); + this._browserPools = _.zipObject( + ids, + ids.map((id: string) => LimitedPool.create(underlyingPool, { + limit: config.forBrowser(id).parallelLimit, + logNamespace: opts.logNamespace + })) + ); + } + + public getBrowser(id: string, opts: any): Bluebird { + this.log(`request ${id} with opts: ${JSON.stringify(opts)}`); + + return this._browserPools[id].getBrowser(id, opts); + } + + public freeBrowser(browser: NewBrowser, opts: any): Bluebird { + this.log(`free ${browser.fullId}`); + + return this._browserPools[browser.id].freeBrowser(browser, opts); + } + + public cancel(): void { + this.log('cancel'); + _.forEach(this._browserPools, (pool) => pool.cancel()); + } +}; diff --git a/lib/browser-pool/pool.js b/lib/browser-pool/pool.js deleted file mode 100644 index ed75bf3..0000000 --- a/lib/browser-pool/pool.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -const Promise = require('bluebird'); - -module.exports = class Pool { - /** - * @returns {Promise.} - */ - getBrowser() {} - - /** - * @param {Browser} browser - * @returns {Promise} - */ - freeBrowser() { - return Promise.resolve(); - } - - cancel() {} -}; diff --git a/lib/browser-pool/utils.js b/lib/browser-pool/utils.js deleted file mode 100644 index a6903de..0000000 --- a/lib/browser-pool/utils.js +++ /dev/null @@ -1,3 +0,0 @@ -exports.buildCompositeBrowserId = (browserId, version) => version - ? `${browserId}.${version}` - : browserId; diff --git a/lib/browser-pool/utils.ts b/lib/browser-pool/utils.ts new file mode 100644 index 0000000..3646450 --- /dev/null +++ b/lib/browser-pool/utils.ts @@ -0,0 +1,3 @@ +export const buildCompositeBrowserId = (browserId: string, version: string): string => { + return version ? `${browserId}.${version}` : browserId; +}; diff --git a/lib/browser/camera/index.js b/lib/browser/camera/index.js deleted file mode 100644 index d0f7b94..0000000 --- a/lib/browser/camera/index.js +++ /dev/null @@ -1,56 +0,0 @@ -'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; - } - - captureViewportImage(page) { - return this._takeScreenshot() - .then((base64) => this._applyCalibration(Image.fromBase64(base64))) - .then((image) => this._cropToViewport(image, page)); - } - - _applyCalibration(image) { - if (!this._calibration) { - return image; - } - - const {left, top} = this._calibration; - const {width, height} = image.getSize(); - - return image.crop({left, top, width: width - left, height: height - top}); - } - - _cropToViewport(image, page) { - if (!page) { - return image; - } - - const isFullPage = utils.isFullPage(image, page, this._screenshotMode); - const cropArea = _.clone(page.viewport); - - if (!isFullPage) { - _.extend(cropArea, { - top: 0, - left: 0 - }); - } - - return image.crop(cropArea, {scaleFactor: page.pixelRatio}); - } -}; diff --git a/lib/browser/camera/index.ts b/lib/browser/camera/index.ts new file mode 100644 index 0000000..970b11f --- /dev/null +++ b/lib/browser/camera/index.ts @@ -0,0 +1,64 @@ +import _ from "lodash"; + +import * as utils from "./utils"; +import Image from "../../image"; + +import type { Page } from "../../types/page"; +import type { CalibrationResult } from "../../types/calibrator"; + +export type ScreenshotMode = "fullpage" | "viewport" | "auto"; + +export default class Camera { + private _calibration: CalibrationResult | null; + + public static create(screenshotMode: ScreenshotMode, takeScreenshot: () => Promise): Camera { + return new this(screenshotMode, takeScreenshot); + } + + constructor( + private _screenshotMode: ScreenshotMode, + private _takeScreenshot: () => Promise + ) { + this._calibration = null; + } + + public calibrate(calibration: CalibrationResult): void { + this._calibration = calibration; + } + + public async captureViewportImage(page?: Page): Promise { + const base64 = await this._takeScreenshot(); + const image = await this._applyCalibration(Image.fromBase64(base64)); + + return this._cropToViewport(image, page); + } + + private async _applyCalibration(image: Image): Promise { + if (!this._calibration) { + return image; + } + + const {left, top} = this._calibration; + const {width, height} = image.getSize(); + + return image.crop({left, top, width: width - left, height: height - top}); + } + + private async _cropToViewport(image: Image, page?: Page): Promise { + if (!page) { + return image; + } + + const isFullPage = utils.isFullPage(image, page, this._screenshotMode); + const cropArea = _.clone(page.viewport); + + if (!isFullPage) { + _.extend(cropArea, { + top: 0, + left: 0 + }); + } + + return image.crop(cropArea, {scaleFactor: page.pixelRatio}); + } +}; diff --git a/lib/browser/camera/utils.js b/lib/browser/camera/utils.ts similarity index 71% rename from lib/browser/camera/utils.js rename to lib/browser/camera/utils.ts index af3c631..598996c 100644 --- a/lib/browser/camera/utils.js +++ b/lib/browser/camera/utils.ts @@ -1,6 +1,7 @@ -'use strict'; +import type { ScreenshotMode } from "."; +import type Image from "../../image"; -exports.isFullPage = (image, page, screenshotMode) => { +export function isFullPage(image: Image, page: any, screenshotMode: ScreenshotMode): boolean { switch (screenshotMode) { case 'fullpage': return true; case 'viewport': return false; @@ -14,7 +15,7 @@ exports.isFullPage = (image, page, screenshotMode) => { * @returns {boolean} * @private */ -function compareDimensions(image, page) { +function compareDimensions(image: Image, page: any): boolean { const pixelRatio = page.pixelRatio; const documentWidth = page.documentWidth * pixelRatio; const documentHeight = page.documentHeight * pixelRatio; diff --git a/lib/browser/client-scripts/calibrate.js b/lib/browser/client-scripts/calibrate.ts similarity index 62% rename from lib/browser/client-scripts/calibrate.js rename to lib/browser/client-scripts/calibrate.ts index 35c0d22..9ef4325 100644 --- a/lib/browser/client-scripts/calibrate.js +++ b/lib/browser/client-scripts/calibrate.ts @@ -1,6 +1,6 @@ -(function(window) { - 'use strict'; +import type { Features as BrowserFeatures } from '../../types/calibrator'; +(function(_window: Window) { // HACK: ie8 does not need to reset the body border, // while any other browser does. // This hack is obsolete in standards mode, but @@ -8,30 +8,30 @@ // which is in quirks mode. // Needs to find a proper way to open calibration // page in standards mode. - function needsResetBorder() { + function needsResetBorder(): boolean { return !/MSIE 8\.0/.test(navigator.userAgent); } - function resetZoom() { - var meta = document.createElement('meta'); + function resetZoom(): void { + const 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; + function createPattern(): void { + const bodyStyle = document.body.style; + bodyStyle.margin = '0'; + bodyStyle.padding = '0'; if (needsResetBorder()) { - bodyStyle.border = 0; + bodyStyle.border = '0'; } bodyStyle.backgroundColor = '#96fa00'; } - function hasCSS3Selectors() { + function hasCSS3Selectors(): boolean { try { document.querySelector('body:nth-child(1)'); } catch (e) { @@ -40,27 +40,27 @@ return true; } - function needsCompatLib() { + function needsCompatLib(): boolean { return !hasCSS3Selectors() || - !window.getComputedStyle || - !window.matchMedia || + !_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); + function getInnerWidth(): number { + const isSafari = /Safari/.test(navigator.userAgent); return isSafari ? document.documentElement.clientWidth || document.body.clientWidth - : window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; + : _window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; } - function getBrowserFeatures() { - var features = { + function getBrowserFeatures(): BrowserFeatures { + const features = { needsCompatLib: needsCompatLib(), - pixelRatio: window.devicePixelRatio, + pixelRatio: _window.devicePixelRatio, innerWidth: getInnerWidth() }; diff --git a/lib/browser/client-scripts/ignore-areas.deprecated.js b/lib/browser/client-scripts/ignore-areas.deprecated.js deleted file mode 100644 index 3d78cd5..0000000 --- a/lib/browser/client-scripts/ignore-areas.deprecated.js +++ /dev/null @@ -1,9 +0,0 @@ -'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/lib/browser/client-scripts/ignore-areas.deprecated.ts b/lib/browser/client-scripts/ignore-areas.deprecated.ts new file mode 100644 index 0000000..d241d35 --- /dev/null +++ b/lib/browser/client-scripts/ignore-areas.deprecated.ts @@ -0,0 +1,13 @@ +import type * as libTypings from './lib.native'; + +const lib: typeof libTypings = require('./lib'); + +export default function queryIgnoreAreas(selector: string | { every: string }): Array | NodeListOf { + if (typeof selector === 'string') { + const node = lib.queryFirst(selector); + + return node ? [node] : []; + } + + return lib.queryAll(selector.every); +} diff --git a/lib/browser/client-scripts/ignore-areas.js b/lib/browser/client-scripts/ignore-areas.js deleted file mode 100644 index 9ef492b..0000000 --- a/lib/browser/client-scripts/ignore-areas.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -var lib = require('./lib'); - -module.exports = function queryIgnoreAreas(selector) { - return lib.queryAll(selector); -}; diff --git a/lib/browser/client-scripts/ignore-areas.ts b/lib/browser/client-scripts/ignore-areas.ts new file mode 100644 index 0000000..fdc98b9 --- /dev/null +++ b/lib/browser/client-scripts/ignore-areas.ts @@ -0,0 +1,7 @@ +import type * as libTypings from './lib.native'; + +const lib: typeof libTypings = require('./lib'); + +export function queryIgnoreAreas(selector: string): Array | NodeListOf { + return lib.queryAll(selector); +} diff --git a/lib/browser/client-scripts/index.coverage.js b/lib/browser/client-scripts/index.coverage.js deleted file mode 100644 index f0b9703..0000000 --- a/lib/browser/client-scripts/index.coverage.js +++ /dev/null @@ -1,108 +0,0 @@ -'use strict'; - -var util = require('./util'), - coverageLevel = require('../../coverage/coverage-level'), - rect = require('./rect'), - lib = require('./lib'); - -exports.collectCoverage = function collectCoverage(rect) { - var coverage = {}, - sheets = document.styleSheets; - for (var i = 0; i < sheets.length; i++) { - var href = sheets[i].href, - rules = getRules(sheets[i]); - - if (rules.ignored) { - coverage[href] = rules; - continue; - } - var ctx = { - // media rule counter - // coverage for media rules is stored by its index within stylesheet - media: -1, - href: href, - coverage: coverage - }; - for (var r = 0; r < rules.length; r++) { - coverageForRule(rules[r], rect, ctx); - } - } - - return coverage; -}; - -function getRules(styleSheet) { - try { - return styleSheet.cssRules || styleSheet.rules; - } catch (e) { - if (e.name === 'SecurityError') { - return { - ignored: true, - message: 'Unable to read stylesheet rules due to the same origin policy' - }; - } - throw e; - } -} - -function coverageForRule(rule, area, ctx) { - if (rule.cssRules || rule.styleSheet) { - if (rule.conditionText) { - ctx.media++; - if (!lib.matchMedia(rule.conditionText).matches) { - return; - } - } - - var rules = rule.cssRules || rule.styleSheet.cssRules; - for (var r = 0; r < rules.length; r++) { - coverageForRule(rules[r], area, ctx); - } - - return; - } - - if (!rule.selectorText) { - return; - } - - util.each(rule.selectorText.split(','), function(selector) { - selector = lib.trim(selector); - var coverage = coverageLevel.NONE, - matches = lib.queryAll(selector); - - var re = /:{1,2}(?:after|before|first-letter|first-line|selection)(:{1,2}\w+)?$/; - // if selector contains pseudo-elements cut it off and try to find element without it - if (matches.length === 0 && re.test(selector)) { - var newSelector = lib.trim(selector.replace(re, '$1')); - - if (newSelector.length > 0) { - matches = lib.queryAll(newSelector); - } - } - - if (matches.length > 0) { - for (var match = 0; match < matches.length; match++) { - var newCoverage = coverageForElem(matches[match], area); - coverage = coverageLevel.merge(coverage, newCoverage); - } - } - - var byURL = ctx.coverage[ctx.href] = ctx.coverage[ctx.href] || {}; - if (rule.parentRule && rule.parentRule.conditionText) { - selector = '?' + ctx.media + ':' + selector; - } - - byURL[selector] = coverageLevel.merge(byURL[selector], coverage); - }); -} - -function coverageForElem(elem, captureRect) { - var elemRect = rect.getAbsoluteClientRect(elem); - if (captureRect.rectInside(elemRect)) { - return coverageLevel.FULL; - } else if (captureRect.rectIntersects(elemRect)) { - return coverageLevel.PARTIAL; - } - return coverageLevel.NONE; -} diff --git a/lib/browser/client-scripts/index.coverage.ts b/lib/browser/client-scripts/index.coverage.ts new file mode 100644 index 0000000..0c793db --- /dev/null +++ b/lib/browser/client-scripts/index.coverage.ts @@ -0,0 +1,128 @@ +import * as util from './util'; +import * as coverageLevel from '../../coverage/coverage-level'; +import Rect, { getAbsoluteClientRect } from './rect'; + +import type * as libTyping from './lib.native'; +import type { CoverageError, CoverageByUrl, Coverage } from '../../types/coverage'; + +const lib: typeof libTyping = require('./lib'); + +type Context = { + media: number; + href: string; + coverage: Coverage; +}; + +export function collectCoverage(rect: Rect): Coverage { + const coverage: Coverage = {}; + const sheets = document.styleSheets; + + for (let i = 0; i < sheets.length; i++) { + const href = sheets[i].href as string; + const rules = getRules(sheets[i]); + + if (isSecurityError(rules)) { + coverage[href] = rules; + continue; + } + + const ctx: Context = { + // media rule counter + // coverage for media rules is stored by its index within stylesheet + media: -1, + href: href, + coverage: coverage + }; + + for (let r = 0; r < rules.length; r++) { + coverageForRule(rules[r], rect, ctx); + } + } + + return coverage; +} + +function isSecurityError(rule: CSSRuleList | CoverageError): rule is CoverageError { + return (rule as CoverageError).ignored; +} + +function getRules(styleSheet: CSSStyleSheet): CSSRuleList | CoverageError { + try { + return styleSheet.cssRules || styleSheet.rules; + } catch (e: unknown) { + if (e instanceof Error && e.name === 'SecurityError') { + return { + ignored: true, + message: 'Unable to read stylesheet rules due to the same origin policy' + }; + } + throw e; + } +} + +function coverageForRule(rule: CSSRule, area: Rect, ctx: Context): void { + if (rule instanceof CSSConditionRule || rule instanceof CSSImportRule) { + if (rule instanceof CSSConditionRule) { + ctx.media++; + + if (!lib.matchMedia(rule.conditionText).matches) { + return; + } + } + + const rules = (rule as CSSConditionRule).cssRules || (rule as CSSImportRule).styleSheet.cssRules; + + for (let r = 0; r < rules.length; r++) { + coverageForRule(rules[r], area, ctx); + } + + return; + } + + if (!(rule instanceof CSSStyleRule)) { + return; + } + + util.each(rule.selectorText.split(','), function(selector) { + selector = lib.trim(selector); + let coverage = coverageLevel.NONE, + matches = lib.queryAll(selector); + + const re = /:{1,2}(?:after|before|first-letter|first-line|selection)(:{1,2}\w+)?$/; + + // if selector contains pseudo-elements cut it off and try to find element without it + if (matches.length === 0 && re.test(selector)) { + const newSelector = lib.trim(selector.replace(re, '$1')); + + if (newSelector.length > 0) { + matches = lib.queryAll(newSelector); + } + } + + if (matches.length > 0) { + for (let match = 0; match < matches.length; match++) { + const newCoverage = coverageForElem(matches[match] as Element, area); + + coverage = coverageLevel.merge(coverage, newCoverage); + } + } + + const byURL = ctx.coverage[ctx.href] = ctx.coverage[ctx.href] as CoverageByUrl || {}; + + if (rule.parentRule && rule.parentRule instanceof CSSConditionRule) { + selector = '?' + ctx.media + ':' + selector; + } + + byURL[selector] = coverageLevel.merge(byURL[selector], coverage); + }); +} + +function coverageForElem(elem: Element, captureRect: Rect): coverageLevel.CoverageValue { + const elemRect = getAbsoluteClientRect(elem); + if (captureRect.rectInside(elemRect)) { + return coverageLevel.FULL; + } else if (captureRect.rectIntersects(elemRect)) { + return coverageLevel.PARTIAL; + } + return coverageLevel.NONE; +} diff --git a/lib/browser/client-scripts/index.js b/lib/browser/client-scripts/index.ts similarity index 58% rename from lib/browser/client-scripts/index.js rename to lib/browser/client-scripts/index.ts index be40e69..cfc2ffb 100644 --- a/lib/browser/client-scripts/index.js +++ b/lib/browser/client-scripts/index.ts @@ -1,19 +1,32 @@ /*jshint browserify:true*/ -'use strict'; +import { queryIgnoreAreas } from './ignore-areas'; +import Rect, { getAbsoluteClientRect } from './rect'; +import * as util from './util'; -var util = require('./util'), - rect = require('./rect'), - lib = require('./lib'), - queryIgnoreAreas = require('./ignore-areas'), - Rect = rect.Rect; +import type * as libTyping from './lib.native'; +import type { Page } from '../../types/page'; +import type { SerializedRect } from '../../types/rect'; + +const lib: typeof libTyping = require('./lib'); if (typeof window === 'undefined') { + //@ts-ignore global.__geminiCore = exports; } else { + //@ts-ignore window.__geminiCore = exports; } -exports.queryFirst = lib.queryFirst; +export const queryFirst = lib.queryFirst; + +type PrepareScreenshotOpts = { + ignoreSelectors: Array; + allowViewportOverflow?: boolean; + captureElementFromTop?: boolean; + selectorToScroll?: string; + usePixelRatio?: boolean; + coverage?: boolean; +}; // Terminology // - clientRect - the result of calling getBoundingClientRect of the element @@ -21,25 +34,23 @@ exports.queryFirst = lib.queryFirst; // - elementCaptureRect - sum of extRects of the element and its pseudo-elements // - captureRect - sum of all elementCaptureRect for each captureSelectors -exports.prepareScreenshot = function prepareScreenshot(selectors, opts) { - opts = opts || {}; +export function prepareScreenshot(selectors: Array, opts: PrepareScreenshotOpts = { ignoreSelectors: [] }) { try { return prepareScreenshotUnsafe(selectors, opts); - } catch (e) { + } catch (e: any) { return { error: 'JS', message: e.stack || e.message }; } -}; +} -function prepareScreenshotUnsafe(selectors, opts) { - var allowViewportOverflow = opts.allowViewportOverflow; - var captureElementFromTop = opts.captureElementFromTop; - var scrollElem = window; +function prepareScreenshotUnsafe(selectors: Array, opts: PrepareScreenshotOpts): Page | RectError { + const { allowViewportOverflow, captureElementFromTop } = opts; + let scrollElem: Element | Window = window; if (opts.selectorToScroll) { - scrollElem = document.querySelector(opts.selectorToScroll); + scrollElem = document.querySelector(opts.selectorToScroll) as Element; if (!scrollElem) { return { @@ -50,16 +61,17 @@ function prepareScreenshotUnsafe(selectors, opts) { } } - var rect = getCaptureRect(selectors, {allowViewportOverflow: allowViewportOverflow, scrollElem: scrollElem}); - if (rect.error) { + const rect = getCaptureRect(selectors, {allowViewportOverflow: allowViewportOverflow, scrollElem: scrollElem}); + + if (isRectError(rect)) { return rect; } - - var viewportHeight = document.documentElement.clientHeight, + + let coverage; + const viewportHeight = document.documentElement.clientHeight, viewportWidth = document.documentElement.clientWidth, documentHeight = document.documentElement.scrollHeight, documentWidth = document.documentElement.scrollWidth, - coverage, viewPort = new Rect({ left: util.getScrollLeft(scrollElem), top: util.getScrollTop(scrollElem), @@ -104,21 +116,40 @@ function prepareScreenshotUnsafe(selectors, opts) { }; } -exports.resetZoom = function() { - var meta = lib.queryFirst('meta[name="viewport"]'); +function isRectError(obj: Rect | RectError): obj is RectError { + return Boolean((obj as RectError).error); +} + +export function resetZoom(): void { + let meta = lib.queryFirst('meta[name="viewport"]'); if (!meta) { meta = document.createElement('meta'); - meta.name = 'viewport'; - var head = lib.queryFirst('head'); + (meta as any).name = 'viewport'; + const head = lib.queryFirst('head'); head && head.appendChild(meta); } - meta.content = 'width=device-width,initial-scale=1.0,user-scalable=no'; + (meta as any).content = 'width=device-width,initial-scale=1.0,user-scalable=no'; +} + +type RectError = { + error: string; + message: string; + selector?: string | Array; +}; + +type GetCaptureRectOpts = { + allowViewportOverflow?: boolean; + scrollElem: Element | Window; }; -function getCaptureRect(selectors, opts) { - var element, elementRect, rect; - for (var i = 0; i < selectors.length; i++) { - element = lib.queryFirst(selectors[i]); +function getCaptureRect(selectors: Array, opts: GetCaptureRectOpts): Rect | RectError { + let element: Element | null; + let elementRect: Rect | null; + let rect: Rect | null = null; + + for (let i = 0; i < selectors.length; i++) { + element = lib.queryFirst(selectors[i]) as Element | null; + if (!element) { return { error: 'NOTFOUND', @@ -140,7 +171,7 @@ function getCaptureRect(selectors, opts) { }; } -function configurePixelRatio(usePixelRatio) { +function configurePixelRatio(usePixelRatio?: boolean): number { if (usePixelRatio === false) { return 1; } @@ -150,13 +181,14 @@ function configurePixelRatio(usePixelRatio) { } // for ie6-ie10 (https://developer.mozilla.org/ru/docs/Web/API/Window/devicePixelRatio) + //@ts-expect-error return window.screen.deviceXDPI / window.screen.logicalXDPI || 1; } -function findIgnoreAreas(selectors, scrollElem) { - var result = []; +function findIgnoreAreas(selectors: Array, scrollElem: Element | Window) { + const result: Array = []; util.each(selectors, function(selector) { - var elements = queryIgnoreAreas(selector); + const elements = queryIgnoreAreas(selector) as Array; util.each(elements, function(elem) { return addIgnoreArea.call(result, elem, scrollElem); @@ -166,29 +198,29 @@ function findIgnoreAreas(selectors, scrollElem) { return result; } -function addIgnoreArea(element, scrollElem) { - var rect = element && getElementCaptureRect(element, {scrollElem: scrollElem}); +function addIgnoreArea(this: Array, element: Element | null, scrollElem: Element | Window) { + const rect = element && getElementCaptureRect(element, {scrollElem: scrollElem}); rect && this.push(rect.round().serialize()); } -function isHidden(css, clientRect) { +function isHidden(css: CSSStyleDeclaration, clientRect: Rect): boolean { return css.display === 'none' || css.visibility === 'hidden' || - css.opacity < 0.0001 || + +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.scrollElem); +function getElementCaptureRect(element: Element, opts: GetCaptureRectOpts): Rect | null { + const pseudo = [':before', ':after']; + let css = lib.getComputedStyle(element); + const clientRect = getAbsoluteClientRect(element, opts.scrollElem); if (isHidden(css, clientRect)) { return null; } - var elementRect = getExtRect(css, clientRect, opts.allowViewportOverflow); + let elementRect = getExtRect(css, clientRect, opts.allowViewportOverflow); util.each(pseudo, function(pseudoEl) { css = lib.getComputedStyle(element, pseudoEl); @@ -198,9 +230,9 @@ function getElementCaptureRect(element, opts) { return elementRect; } -function getExtRect(css, clientRect, allowViewportOverflow) { - var shadows = parseBoxShadow(css.boxShadow), - outline = parseInt(css.outlineWidth, 10); +function getExtRect(css: CSSStyleDeclaration, clientRect: Rect, allowViewportOverflow?: boolean): Rect { + const shadows = parseBoxShadow(css.boxShadow); + let outline = parseInt(css.outlineWidth, 10); if (isNaN(outline)) { outline = 0; @@ -209,12 +241,20 @@ function getExtRect(css, clientRect, allowViewportOverflow) { return adjustRect(clientRect, shadows, outline, allowViewportOverflow); } -function parseBoxShadow(value) { - value = value || ''; - var regex = /[-+]?\d*\.?\d+px/g, - values = value.split(','), - results = [], - match; +type BoxShadow = { + offsetX: number; + offsetY: number; + blurRadius: number; + spreadRadius: number; + inset: boolean; +}; + +function parseBoxShadow(value: string = ''): Array { + const regex = /[-+]?\d*\.?\d+px/g; + const values = value.split(','); + const results: Array = []; + + let match: RegExpMatchArray | null; util.each(values, function(value) { if ((match = value.match(regex))) { @@ -227,18 +267,20 @@ function parseBoxShadow(value) { }); } }); + return results; } -function adjustRect(rect, shadows, outline, allowViewportOverflow) { - var shadowRect = calculateShadowRect(rect, shadows, allowViewportOverflow), - outlineRect = calculateOutlineRect(rect, outline, allowViewportOverflow); +function adjustRect(rect: Rect, shadows: Array, outline: number, allowViewportOverflow?: boolean): Rect { + const shadowRect = calculateShadowRect(rect, shadows, allowViewportOverflow); + const outlineRect = calculateOutlineRect(rect, outline, allowViewportOverflow); + return shadowRect.merge(outlineRect); } -function calculateOutlineRect(rect, outline, allowViewportOverflow) { - var top = rect.top - outline, - left = rect.left - outline; +function calculateOutlineRect(rect: Rect, outline: number, allowViewportOverflow?: boolean): Rect { + const top = rect.top - outline; + const left = rect.left - outline; return new Rect({ top: allowViewportOverflow ? top : Math.max(0, top), @@ -248,10 +290,10 @@ function calculateOutlineRect(rect, outline, allowViewportOverflow) { }); } -function calculateShadowRect(rect, shadows, allowViewportOverflow) { - var extent = calculateShadowExtent(shadows), - left = rect.left + extent.left, - top = rect.top + extent.top; +function calculateShadowRect(rect: Rect, shadows: Array, allowViewportOverflow?: boolean): Rect { + const extent = calculateShadowExtent(shadows); + const left = rect.left + extent.left; + const top = rect.top + extent.top; return new Rect({ left: allowViewportOverflow ? left : Math.max(0, left), @@ -261,8 +303,8 @@ function calculateShadowRect(rect, shadows, allowViewportOverflow) { }); } -function calculateShadowExtent(shadows) { - var result = {top: 0, left: 0, right: 0, bottom: 0}; +function calculateShadowExtent(shadows: Array) { + const result = {top: 0, left: 0, right: 0, bottom: 0}; util.each(shadows, function(shadow) { if (shadow.inset) { @@ -270,27 +312,30 @@ function calculateShadowExtent(shadows) { return; } - var blurAndSpread = shadow.spreadRadius + shadow.blurRadius; + const 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) { +function isEditable(element: Element | null): boolean { if (!element) { return false; } + return /^(input|textarea)$/i.test(element.tagName) || - element.isContentEditable; + (element as HTMLElement).isContentEditable; } -function scrollToCaptureAreaInSafari(viewportCurr, captureArea, scrollElem) { - var documentHeight = Math.round(document.documentElement.scrollHeight); - var viewportHeight = Math.round(document.documentElement.clientHeight); - var maxScrollByY = documentHeight - viewportHeight; +function scrollToCaptureAreaInSafari(viewportCurr: Rect, captureArea: Rect, scrollElem: Element | Window): void { + const documentHeight = Math.round(document.documentElement.scrollHeight); + const viewportHeight = Math.round(document.documentElement.clientHeight); + const maxScrollByY = documentHeight - viewportHeight; scrollElem.scrollTo(viewportCurr.left, Math.min(captureArea.top, maxScrollByY)); @@ -302,7 +347,6 @@ function scrollToCaptureAreaInSafari(viewportCurr, captureArea, scrollElem) { width: viewportCurr.width, height: viewportCurr.height }); - if (!viewportAfterScroll.rectInside(captureArea)) { scrollElem.scrollTo(captureArea.left, captureArea.top); } diff --git a/lib/browser/client-scripts/lib.compat.js b/lib/browser/client-scripts/lib.compat.ts similarity index 56% rename from lib/browser/client-scripts/lib.compat.js rename to lib/browser/client-scripts/lib.compat.ts index 4970ca2..4e85914 100644 --- a/lib/browser/client-scripts/lib.compat.js +++ b/lib/browser/client-scripts/lib.compat.ts @@ -1,28 +1,31 @@ -'use strict'; /*jshint newcap:false*/ -var Sizzle = require('sizzle'); -var xpath = require('./xpath'); +import Sizzle from 'sizzle'; -exports.queryFirst = function(selector) { +import * as xpath from './xpath'; + +export function queryFirst(selector: string): Node | null { if (xpath.isXpathSelector(selector)) { return xpath.queryFirst(selector); } - var elems = Sizzle(exports.trim(selector) + ':first'); + + const elems = Sizzle(trim(selector) + ':first'); + return elems.length > 0 ? elems[0] : null; -}; +} -exports.queryAll = function(selector) { +export function queryAll(selector: string): Array { if (xpath.isXpathSelector(selector)) { return xpath.queryAll(selector); } + return Sizzle(selector); -}; +} -exports.trim = function(str) { +export function trim(str: string): string { // 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; +export { getComputedStyle } from './polyfills/getComputedStyle'; +export { matchMedia } from './polyfills/matchMedia'; diff --git a/lib/browser/client-scripts/lib.native.js b/lib/browser/client-scripts/lib.native.js deleted file mode 100644 index 1cc3d07..0000000 --- a/lib/browser/client-scripts/lib.native.js +++ /dev/null @@ -1,28 +0,0 @@ -'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/lib/browser/client-scripts/lib.native.ts b/lib/browser/client-scripts/lib.native.ts new file mode 100644 index 0000000..4ac0f61 --- /dev/null +++ b/lib/browser/client-scripts/lib.native.ts @@ -0,0 +1,29 @@ +import * as xpath from './xpath'; + +export function queryFirst(selector: string): Node | null { + if (xpath.isXpathSelector(selector)) { + return xpath.queryFirst(selector); + } + + return document.querySelector(selector); +} + +export function queryAll(selector: string): Node[] | NodeListOf { + if (xpath.isXpathSelector(selector)) { + return xpath.queryAll(selector); + } + + return document.querySelectorAll(selector); +} + +export function getComputedStyle(element: Element, pseudoElement?: string): CSSStyleDeclaration { + return window.getComputedStyle(element, pseudoElement); +} + +export function matchMedia(mediaQuery: string): MediaQueryList { + return window.matchMedia(mediaQuery); +} + +export function trim(str: string): string { + return str.trim(); +} diff --git a/lib/browser/client-scripts/rect.js b/lib/browser/client-scripts/rect.js deleted file mode 100644 index b76b9d7..0000000 --- a/lib/browser/client-scripts/rect.js +++ /dev/null @@ -1,119 +0,0 @@ -'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.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({ - top: this.top + y, - left: this.left + x, - 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) - }); - }, - - serialize: function() { - return { - top: this.top, - left: this.left, - width: this.width, - height: this.height - }; - }, - - overflowsTopBound: function(rect) { - return this._overflowsBound(rect, 'top'); - }, - - overflowsLeftBound: function(rect) { - return this._overflowsBound(rect, 'left'); - }, - - recalculateHeight: function(rect) { - this.height = this.height - (rect.top - Math.max(0, this.top)); - }, - - 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, scrollElem) { - var clientRect = new Rect(element.getBoundingClientRect()); - return clientRect.translate(util.getScrollLeft(scrollElem), util.getScrollTop(scrollElem)); -}; diff --git a/lib/browser/client-scripts/rect.ts b/lib/browser/client-scripts/rect.ts new file mode 100644 index 0000000..b4cbab1 --- /dev/null +++ b/lib/browser/client-scripts/rect.ts @@ -0,0 +1,135 @@ +import * as util from './util'; + +import type { SerializedRect } from '../../types/rect'; + +type RectConstructor = { + top: number; + left: number; + right?: number; + bottom?: number; + width?: number; + height?: number; +}; + +function hasWidthAndHeight(data: T): data is T & Record<'width'|'height', number> { + return 'width' in data && 'height' in data; +} + +function hasRightAndBottom(data: T): data is T & Record<'right'|'bottom', number> { + return 'right' in data && 'bottom' in data; +} + +export default class Rect { + public top: number; + public left: number; + public right: number; + public bottom: number; + public width: number; + public height: number; + + constructor(data: RectConstructor) { + this.top = data.top; + this.left = data.left; + + if (hasWidthAndHeight(data)) { + this.width = data.width; + this.height = data.height; + this.right = data.right || this.left + this.width; + this.bottom = data.bottom || this.top + this.height; + } else if (hasRightAndBottom(data)) { + this.right = data.right; + this.bottom = data.bottom; + 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'); + } + } + + public merge(otherRect: Rect): Rect { + 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) + }); + } + + public translate(x: number, y: number): Rect { + return new Rect({ + top: this.top + y, + left: this.left + x, + width: this.width, + height: this.height + }); + } + + public pointInside(x: number, y: number): boolean { + return x >= this.left && x <= this.right && + y >= this.top && y <= this.bottom; + } + + public rectInside(rect: Rect): boolean { + return util.every(rect._keyPoints(), function(point: [number, number]) { + return this.pointInside(point[0], point[1]); + }, this); + } + + public rectIntersects(other: Rect): boolean { + const isOtherOutside = other.right <= this.left || other.bottom <= this.top || other.left >= this.right || other.top >= this.bottom; + + return !isOtherOutside; + } + + public round(): Rect { + return new Rect({ + top: Math.floor(this.top), + left: Math.floor(this.left), + right: Math.ceil(this.right), + bottom: Math.ceil(this.bottom) + }); + } + + public serialize(): SerializedRect { + return { + top: this.top, + left: this.left, + width: this.width, + height: this.height + }; + } + + public overflowsTopBound(rect: Rect): boolean { + return this._overflowsBound(rect, 'top'); + } + + public overflowsLeftBound(rect: Rect): boolean { + return this._overflowsBound(rect, 'left'); + } + + public recalculateHeight(rect: Rect): void { + this.height = this.height - (rect.top - Math.max(0, this.top)); + } + + public recalculateWidth(rect: Rect): void { + this.width = this.width - (rect.left - Math.max(0, this.left)); + } + + private _overflowsBound(rect: Rect, prop: keyof SerializedRect): boolean { + return Math.max(0, this[prop]) < rect[prop]; + } + + private _keyPoints(): Array<[number, number]> { + return [ + [this.left, this.top], + [this.left, this.bottom], + [this.right, this.top], + [this.right, this.bottom] + ]; + } +} + +export function getAbsoluteClientRect(element: Element, scrollElem?: Element | Window): Rect { + const clientRect = new Rect(element.getBoundingClientRect()); + return clientRect.translate(util.getScrollLeft(scrollElem), util.getScrollTop(scrollElem)); +} diff --git a/lib/browser/client-scripts/tsconfig.json b/lib/browser/client-scripts/tsconfig.json new file mode 100644 index 0000000..b7fdb6a --- /dev/null +++ b/lib/browser/client-scripts/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/recommended/tsconfig.json", + "include": ["**/*"], + "compilerOptions": { + "target": "ES3", + "outDir": "../../../build/lib", + "types": ["node"], + "allowJs": true, + "noImplicitReturns": true, + "noUnusedLocals": true, + "noUnusedParameters": true + } +} diff --git a/lib/browser/client-scripts/util.js b/lib/browser/client-scripts/util.js deleted file mode 100644 index 7ed298a..0000000 --- a/lib/browser/client-scripts/util.js +++ /dev/null @@ -1,84 +0,0 @@ -'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); -}; diff --git a/lib/browser/client-scripts/util.ts b/lib/browser/client-scripts/util.ts new file mode 100644 index 0000000..e1f15bb --- /dev/null +++ b/lib/browser/client-scripts/util.ts @@ -0,0 +1,103 @@ +enum SCROLL_DIR_NAME { + top = 'scrollTop', + left = 'scrollLeft' +}; + +enum PAGE_OFFSET_NAME { + x = 'pageXOffset', + y = 'pageYOffset' +}; + +export const each = arrayUtil(Array.prototype.forEach, myForEach); +export const some = arrayUtil(Array.prototype.some, mySome); +export const every = arrayUtil(Array.prototype.every, myEvery); + +type NativeFuncEach = typeof Array.prototype.forEach; +type NativeFuncSome = typeof Array.prototype.some; +type NativeFuncEvery = typeof Array.prototype.every; +type NativeFunc = NativeFuncEach | NativeFuncSome | NativeFuncEvery; + +type Callback = (this: C, value: T, index: number, array: Array) => R; + +type ContextFuncEach = (ctx: Array, cb: Callback, thisArg?: C) => void; +type ContextFuncSome = (ctx: Array, cb: Callback, thisArg?: C) => boolean; +type ContextFuncEvery = (ctx: Array, cb: Callback, thisArg?: C) => boolean; +type ContextFunc = ContextFuncEach | ContextFuncSome | ContextFuncEvery; + +function arrayUtil(nativeFunc: NativeFuncEach | undefined, shimFunc: typeof myForEach): ContextFuncEach; +function arrayUtil(nativeFunc: NativeFuncSome | undefined, shimFunc: typeof mySome): ContextFuncSome; +function arrayUtil(nativeFunc: NativeFuncEvery | undefined, shimFunc: typeof myEvery): ContextFuncEvery; +function arrayUtil(nativeFunc: NativeFunc | undefined, shimFunc: ContextFunc): ContextFunc { + return nativeFunc ? contextify(nativeFunc) : shimFunc; +} + +/** + * Makes function f to accept context as a + * first argument + */ +function contextify(f: NativeFunc): ContextFunc { + return function(ctx: Array, ...rest: Parameters): ReturnType { + + return f.apply(ctx, rest); + }; +} + +function myForEach(array: Array, cb: Callback, context?: C): void { + for (var i = 0; i < array.length; i++) { + cb.call(context as C, array[i], i, array); + } +} + +function mySome(array: Array, cb: Callback, context?: C): boolean { + for (var i = 0; i < array.length; i++) { + if (cb.call(context as C, array[i], i, array)) { + return true; + } + } + + return false; +} + +function myEvery(array: Array, cb: Callback, context?: C): boolean { + for (var i = 0; i < array.length; i++) { + if (!cb.call(context as C, array[i], i, array)) { + return false; + } + } + + return true; +} + +function getScroll(scrollElem: Element | Window | undefined, direction: keyof typeof SCROLL_DIR_NAME, coord: keyof typeof PAGE_OFFSET_NAME): number { + var scrollDir = SCROLL_DIR_NAME[direction]; + var pageOffset = PAGE_OFFSET_NAME[coord]; + + if (scrollElem && !isWindow(scrollElem)) { + return scrollElem[scrollDir]; + } + + if (typeof window[pageOffset] !== 'undefined') { + return window[pageOffset]; + } + + return document.documentElement[scrollDir]; +} + +function isWindow(elem: Element | Window): elem is Window { + return elem !== window; +} + +export function getScrollTop(scrollElem?: Element | Window): number { + return getScroll(scrollElem, 'top', 'y'); +} + +export function getScrollLeft(scrollElem?: Element | Window): number { + return getScroll(scrollElem, 'left', 'x'); +} + +export function isSafariMobile(): boolean { + return navigator + && typeof navigator.vendor === 'string' + && Boolean(navigator.vendor.match(/apple/i)) + && /(iPhone|iPad).*AppleWebKit.*Safari/i.test(navigator.userAgent); +} diff --git a/lib/browser/client-scripts/xpath.js b/lib/browser/client-scripts/xpath.js deleted file mode 100644 index 5008c2f..0000000 --- a/lib/browser/client-scripts/xpath.js +++ /dev/null @@ -1,32 +0,0 @@ -'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/lib/browser/client-scripts/xpath.ts b/lib/browser/client-scripts/xpath.ts new file mode 100644 index 0000000..ed2f1b5 --- /dev/null +++ b/lib/browser/client-scripts/xpath.ts @@ -0,0 +1,26 @@ +const XPATH_SELECTORS_START = [ + '/', '(', '../', './', '*/' +] as const; + +export function isXpathSelector(selector: string): boolean { + return XPATH_SELECTORS_START.some(function(startString) { + return selector.indexOf(startString) === 0; + }); +} + +export function queryFirst(selector: string): Node | null { + return document.evaluate(selector, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; +} + +export function queryAll(selector: string): Node[] { + const elements = document.evaluate(selector, document, null, XPathResult.ANY_TYPE, null); + const nodes = []; + let node = elements.iterateNext(); + + while (node) { + nodes.push(node); + node = elements.iterateNext(); + } + + return nodes; +} diff --git a/lib/calibrator/index.js b/lib/calibrator/index.js deleted file mode 100644 index 9086039..0000000 --- a/lib/calibrator/index.js +++ /dev/null @@ -1,127 +0,0 @@ -'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('../errors'); - -const clientScriptCalibrate = fs.readFileSync(path.join(__dirname, '..', 'browser', 'client-scripts', 'calibrate.min.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((features, image) => { - const {innerWidth, pixelRatio} = features; - const hasPixelRatio = Boolean(pixelRatio && pixelRatio > 1.0); - const imageFeatures = 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; - }); - } - - _analyzeImage(image, params) { - const imageHeight = image.getSize().height; - - for (var y = 0; y < imageHeight; y++) { - var result = analyzeRow(y, image, params); - - if (result) { - return result; - } - } - - return null; - } -}; - -function analyzeRow(row, image, params = {}) { - const markerStart = findMarkerInRow(row, image, DIRECTION.FORWARD); - - if (markerStart === -1) { - return null; - } - - const result = {viewportStart: {x: markerStart, y: row}}; - - if (!params.calculateColorLength) { - return result; - } - - const markerEnd = findMarkerInRow(row, image, DIRECTION.REVERSE); - const colorLength = markerEnd - markerStart + 1; - - return _.extend(result, {colorLength}); -} - -function findMarkerInRow(row, image, searchDirection) { - const imageWidth = image.getSize().width; - const searchColor = {R: 148, G: 250, B: 0}; - - if (searchDirection === DIRECTION.REVERSE) { - return searchReverse_(); - } else { - return searchForward_(); - } - - function searchForward_() { - for (var x = 0; x < imageWidth; x++) { - if (compare_(x)) { - return x; - } - } - return -1; - } - - function searchReverse_() { - for (var x = imageWidth - 1; x >= 0; x--) { - if (compare_(x)) { - return x; - } - } - return -1; - } - - function compare_(x) { - var color = pickRGB(image.getRGBA(x, row)); - return looksSame.colors(color, searchColor); - } -} - -function pickRGB(rgba) { - return { - R: rgba.r, - G: rgba.g, - B: rgba.b - }; -} diff --git a/lib/calibrator/index.ts b/lib/calibrator/index.ts new file mode 100644 index 0000000..a390ab0 --- /dev/null +++ b/lib/calibrator/index.ts @@ -0,0 +1,150 @@ +import Bluebird from 'bluebird'; +import fs from 'fs'; +import _ from 'lodash'; +import looksSame from 'looks-same'; +import path from 'path'; + +import { CoreError } from '../errors'; + +import type { Color } from 'png-img'; +import type { RGBColor } from 'color-diff'; + +import type Image from '../image'; +import type { ExistingBrowser } from '../types/existing-browser'; +import type { Features, CalibrationResult } from '../types/calibrator'; + +const clientScriptCalibrate = fs.readFileSync(path.join(__dirname, '..', 'browser', 'client-scripts', 'calibrate.min.js'), 'utf8'); + +enum DIRECTION { + FORWARD = 'forward', + REVERSE = 'reverse' +}; + +type AnalyzeImageParams = { + calculateColorLength?: boolean; +}; + +type AnalyzeRowResult = { + viewportStart: { + x: number; + y: number; + }; + colorLength?: number; +}; + +export default class Calibrator { + private _cache: Record; + + constructor() { + this._cache = {}; + } + + public async calibrate(browser: ExistingBrowser): Promise { + if (this._cache[browser.id]) { + return Bluebird.resolve(this._cache[browser.id]); + } + + await browser.open('about:blank'); + + const features = await browser.evalScript(clientScriptCalibrate); + const image = await browser.captureViewportImage(); + + const {innerWidth, pixelRatio} = features; + const hasPixelRatio = Boolean(pixelRatio && pixelRatio > 1.0); + const imageFeatures = this._analyzeImage(image, {calculateColorLength: hasPixelRatio}); + + if (!imageFeatures) { + return Bluebird.reject(new CoreError( + 'Could not calibrate. This could be due to calibration page has failed to open properly' + )); + } + + const calibrationResult = _.extend(features, { + top: imageFeatures.viewportStart.y, + left: imageFeatures.viewportStart.x, + usePixelRatio: hasPixelRatio && (imageFeatures.colorLength || 0) > innerWidth + }); + + this._cache[browser.id] = calibrationResult; + + return calibrationResult; + } + + private _analyzeImage(image: Image, params: AnalyzeImageParams): AnalyzeRowResult | null { + const imageHeight = image.getSize().height; + + for (let y = 0; y < imageHeight; y++) { + const result = analyzeRow(y, image, params); + + if (result) { + return result; + } + } + + return null; + } +}; + +function analyzeRow(row: number, image: Image, params: AnalyzeImageParams = {}): AnalyzeRowResult | null { + const markerStart = findMarkerInRow(row, image, DIRECTION.FORWARD); + + if (markerStart === -1) { + return null; + } + + const result = {viewportStart: {x: markerStart, y: row}}; + + if (!params.calculateColorLength) { + return result; + } + + const markerEnd = findMarkerInRow(row, image, DIRECTION.REVERSE); + const colorLength = markerEnd - markerStart + 1; + + return _.extend(result, {colorLength}); +} + +function findMarkerInRow(row: number, image: Image, searchDirection: DIRECTION): number { + const imageWidth = image.getSize().width; + const searchColor = {R: 148, G: 250, B: 0}; + + if (searchDirection === DIRECTION.REVERSE) { + return searchReverse_(); + } else { + return searchForward_(); + } + + function searchForward_(): number { + for (let x = 0; x < imageWidth; x++) { + if (compare_(x)) { + return x; + } + } + + return -1; + } + + function searchReverse_(): number { + for (let x = imageWidth - 1; x >= 0; x--) { + if (compare_(x)) { + return x; + } + } + + return -1; + } + + function compare_(x: number): boolean { + const color = pickRGB(image.getRGBA(x, row)); + + return looksSame.colors(color, searchColor); + } +} + +function pickRGB(rgba: Color): RGBColor { + return { + R: rgba.r, + G: rgba.g, + B: rgba.b + }; +} diff --git a/lib/client-bridge/client-bridge.js b/lib/client-bridge/client-bridge.js deleted file mode 100644 index 73261b3..0000000 --- a/lib/client-bridge/client-bridge.js +++ /dev/null @@ -1,51 +0,0 @@ -'use strict'; - -const Promise = require('bluebird'); -const ClientBridgeError = require('../errors').ClientBridgeError; - -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 gemini-core 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); - } -}; diff --git a/lib/client-bridge/client-bridge.ts b/lib/client-bridge/client-bridge.ts new file mode 100644 index 0000000..22c2f8a --- /dev/null +++ b/lib/client-bridge/client-bridge.ts @@ -0,0 +1,54 @@ +import Bluebird from 'bluebird'; +import { ClientBridgeError } from '../errors'; + +import type { ExistingBrowser } from '../types/existing-browser'; + +export default class ClientBridge { + public static create(browser: ExistingBrowser, script: string): ClientBridge { + return new ClientBridge(browser, script); + } + + constructor( + private _browser: ExistingBrowser, + private _script: string + ) {} + + public async call(name: string, args = []): Promise { + return this._callCommand(this._clientMethodCommand(name, args), true); + } + + private async _callCommand(command: string, injectAllowed: boolean): Promise { + const result = await this._browser.evalScript(command); + + try { + if (!result || !result.isClientScriptNotInjected) { + return Bluebird.resolve(result); + } + + if (injectAllowed) { + await this._inject(); + + return this._callCommand(command, false); + } + + return Bluebird.reject(new ClientBridgeError('Unable to inject gemini-core client script')); + } catch (e: unknown) { + return Bluebird.reject(new ClientBridgeError((e as Error).message)); + } + } + + private _clientMethodCommand(name: string, args: Array): string { + const params = args.map((arg) => JSON.stringify(arg)).join(', '); + const call = `__geminiCore.${name}(${params})`; + + return this._guardClientCall(call); + } + + private _guardClientCall(call: string): string { + return `typeof __geminiCore !== "undefined" ? ${call} : {isClientScriptNotInjected: true}`; + } + + private async _inject(): Promise { + return this._browser.injectScript(this._script); + } +}; diff --git a/lib/client-bridge/index.js b/lib/client-bridge/index.ts similarity index 50% rename from lib/client-bridge/index.js rename to lib/client-bridge/index.ts index 910a65c..93afc81 100644 --- a/lib/client-bridge/index.js +++ b/lib/client-bridge/index.ts @@ -1,13 +1,20 @@ -'use strict'; +import path from 'path'; +import Bluebird from 'bluebird'; +import browserify from 'browserify'; +import ClientBridge from './client-bridge'; -const path = require('path'); -const Promise = require('bluebird'); -const browserify = require('browserify'); -const ClientBridge = require('./client-bridge'); +import type { CalibrationResult } from '../types/calibrator'; +import type { ExistingBrowser } from '../types/existing-browser'; -exports.ClientBridge = ClientBridge; +export { default as ClientBridge } from './client-bridge'; -exports.build = (browser, opts = {}) => { +type BuildClientBridgeOpts = { + coverage?: boolean; + calibration?: CalibrationResult; + supportDeprecated?: boolean; +}; + +export const build = async (browser: ExistingBrowser, opts: BuildClientBridgeOpts = {}) => { const script = browserify({ entries: './index', basedir: path.join(__dirname, '..', 'browser', 'client-scripts') @@ -17,29 +24,27 @@ exports.build = (browser, opts = {}) => { script.exclude('./index.coverage'); } - script.transform({ + script.transform('uglifyify', { 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({ + script.transform('aliasify', { aliases: { './lib': {relative: lib}, './ignore-areas': {relative: ignoreAreas} }, verbose: false - }, 'aliasify'); + }); - return Promise.fromCallback((cb) => script.bundle(cb)) - .then((buf) => { - const scripts = buf.toString(); + const buf = await Bluebird.fromCallback((cb: (err: any, src: Buffer) => any) => script.bundle(cb)); + const scripts = buf.toString(); - return ClientBridge.create(browser, scripts); - }); + return ClientBridge.create(browser, scripts); }; diff --git a/lib/config/options.js b/lib/config/options.ts similarity index 77% rename from lib/config/options.js rename to lib/config/options.ts index e2a3996..b273fd1 100644 --- a/lib/config/options.js +++ b/lib/config/options.ts @@ -1,13 +1,17 @@ -'use strict'; +import _ from 'lodash'; +import { section, map, option } from 'gemini-configparser'; -const _ = require('lodash'); -const configparser = require('gemini-configparser'); +export type SetConfig = { + files: Array; + ignoreFiles: Array; + browsers: Array; +}; -const section = configparser.section; -const option = configparser.option; -const map = configparser.map; +export type SetsConfig = { + [platform: string]: SetConfig; +}; -module.exports = { +export default { sets: map(section({ files: option({ validate: (value) => { @@ -19,10 +23,10 @@ module.exports = { throw new Error('"sets.files" must be an array of strings'); } }, - map: (val) => [].concat(val) + map: (val: string | Array) => ([] as Array).concat(val) }), ignoreFiles: option({ - defaultValue: [], + defaultValue: [] as Array, validate: (value) => { if (!_.isArray(value) || !_.every(value, _.isString)) { throw new Error('"sets.ignoreFiles" must be an array of strings'); diff --git a/lib/coverage/coverage-level.js b/lib/coverage/coverage-level.js deleted file mode 100644 index ad46dfd..0000000 --- a/lib/coverage/coverage-level.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; -exports.FULL = 'full'; -exports.PARTIAL = 'partial'; -exports.NONE = 'none'; - -exports.merge = function(oldValue, newValue) { - oldValue = oldValue || exports.NONE; - if (oldValue === exports.FULL || newValue === exports.FULL) { - return exports.FULL; - } - - if (oldValue === exports.PARTIAL || newValue === exports.PARTIAL) { - return exports.PARTIAL; - } - - return exports.NONE; -}; diff --git a/lib/coverage/coverage-level.ts b/lib/coverage/coverage-level.ts new file mode 100644 index 0000000..6b642a4 --- /dev/null +++ b/lib/coverage/coverage-level.ts @@ -0,0 +1,21 @@ +export enum CoverageValue { + FULL = 'full', + PARTIAL = 'partial', + NONE = 'none' +} + +export const FULL = CoverageValue.FULL; +export const PARTIAL = CoverageValue.PARTIAL; +export const NONE = CoverageValue.NONE; + +export function merge(oldValue: CoverageValue = CoverageValue.NONE, newValue: CoverageValue): CoverageValue { + if (oldValue === CoverageValue.FULL || newValue === CoverageValue.FULL) { + return CoverageValue.FULL; + } + + if (oldValue === CoverageValue.PARTIAL || newValue === CoverageValue.PARTIAL) { + return CoverageValue.PARTIAL; + } + + return CoverageValue.NONE; +}; diff --git a/lib/errors/cancelled-error.js b/lib/errors/cancelled-error.ts similarity index 73% rename from lib/errors/cancelled-error.js rename to lib/errors/cancelled-error.ts index fe655c4..051e0a5 100644 --- a/lib/errors/cancelled-error.js +++ b/lib/errors/cancelled-error.ts @@ -1,6 +1,4 @@ -'use strict'; - -module.exports = class CancelledError extends Error { +export default class CancelledError extends Error { constructor() { super(); diff --git a/lib/errors/client-bridge-error.js b/lib/errors/client-bridge-error.js deleted file mode 100644 index ae46f6a..0000000 --- a/lib/errors/client-bridge-error.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; - -module.exports = class ClientBridgeError extends Error { - constructor(message) { - super(message); - - this.name = this.constructor.name; - } -}; diff --git a/lib/errors/client-bridge-error.ts b/lib/errors/client-bridge-error.ts new file mode 100644 index 0000000..4259117 --- /dev/null +++ b/lib/errors/client-bridge-error.ts @@ -0,0 +1,7 @@ +export default class ClientBridgeError extends Error { + constructor(message: string) { + super(message); + + this.name = this.constructor.name; + } +}; diff --git a/lib/errors/core-error.js b/lib/errors/core-error.js deleted file mode 100644 index 3dea8fc..0000000 --- a/lib/errors/core-error.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; - -module.exports = class CoreError extends Error { - constructor(message) { - super(message); - - this.name = 'CoreError'; - } -}; diff --git a/lib/errors/core-error.ts b/lib/errors/core-error.ts new file mode 100644 index 0000000..3dbb243 --- /dev/null +++ b/lib/errors/core-error.ts @@ -0,0 +1,7 @@ +export default class CoreError extends Error { + constructor(message: string) { + super(message); + + this.name = 'CoreError'; + } +}; diff --git a/lib/errors/index.js b/lib/errors/index.js deleted file mode 100644 index c908afb..0000000 --- a/lib/errors/index.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -exports.CoreError = require('./core-error'); -exports.CancelledError = require('./cancelled-error'); -exports.ClientBridgeError = require('./client-bridge-error'); -exports.HeightViewportError = require('../screen-shooter/viewport/coord-validator/errors/height-viewport-error'); -exports.OffsetViewportError = require('../screen-shooter/viewport/coord-validator/errors/offset-viewport-error'); diff --git a/lib/errors/index.ts b/lib/errors/index.ts new file mode 100644 index 0000000..9037850 --- /dev/null +++ b/lib/errors/index.ts @@ -0,0 +1,5 @@ +export { default as CoreError } from './core-error'; +export { default as CancelledError } from './cancelled-error'; +export { default as ClientBridgeError } from './client-bridge-error'; +export { default as HeightViewportError } from '../screen-shooter/viewport/coord-validator/errors/height-viewport-error'; +export { default as OffsetViewportError } from '../screen-shooter/viewport/coord-validator/errors/offset-viewport-error'; diff --git a/lib/events/async-emitter/index.js b/lib/events/async-emitter/index.js deleted file mode 100644 index 57e9e25..0000000 --- a/lib/events/async-emitter/index.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -const _ = require('lodash'); -const Promise = require('bluebird'); -const EventEmitter = require('events').EventEmitter; -const promiseUtils = require('../../promise-utils'); - -module.exports = class AsyncEmitter extends EventEmitter { - emitAndWait(event, ...args) { - return _(this.listeners(event)) - .map((l) => Promise.method(l).apply(this, args)) - .thru(promiseUtils.waitForResults) - .value(); - } -}; diff --git a/lib/events/async-emitter/index.ts b/lib/events/async-emitter/index.ts new file mode 100644 index 0000000..5b65e29 --- /dev/null +++ b/lib/events/async-emitter/index.ts @@ -0,0 +1,17 @@ +import _ from 'lodash'; +import Bluebird from 'bluebird'; +import EventEmitter from 'events'; +import * as promiseUtils from '../../promise-utils'; + +type AnyArgsFunction = (...args: Array) => R; + +export default class AsyncEmitter extends EventEmitter { + public emitAndWait(event: string | symbol, ...args: Array): Bluebird { + const promises = _(this.listeners(event) as Array) + .map((l) => (Bluebird.method(l) as AnyArgsFunction>).apply(this, args)) + .thru(promiseUtils.waitForResults) + .value(); + + return Bluebird.all(promises); + } +}; diff --git a/lib/events/index.js b/lib/events/index.js deleted file mode 100644 index 32e33ae..0000000 --- a/lib/events/index.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; - -module.exports = { - AsyncEmitter: require('./async-emitter'), - utils: require('./utils') -}; diff --git a/lib/events/index.ts b/lib/events/index.ts new file mode 100644 index 0000000..2f697bd --- /dev/null +++ b/lib/events/index.ts @@ -0,0 +1,2 @@ +export { default as AsyncEmitter } from './async-emitter'; +export * as utils from './utils'; diff --git a/lib/events/utils.js b/lib/events/utils.js deleted file mode 100644 index 250e7c6..0000000 --- a/lib/events/utils.js +++ /dev/null @@ -1,16 +0,0 @@ -'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'); diff --git a/lib/events/utils.ts b/lib/events/utils.ts new file mode 100644 index 0000000..3d17f32 --- /dev/null +++ b/lib/events/utils.ts @@ -0,0 +1,18 @@ +import type { EventEmitter } from 'events'; + +import type AsyncEmitter from './async-emitter'; + +const mkPassthroughFn = (methodName: T extends AsyncEmitter ? 'emitAndWait' : 'emit'): (from: T, to: T, event: string | Array) => void => { + const passEvents = (from: T, to: T, event: string | Array): void => { + if (typeof event === 'string') { + from.on(event, (...args: Array) => to[methodName](event, ...args)); + return; + } + event.forEach((event) => passEvents(from, to, event)); + }; + + return passEvents; +}; + +export const passthroughEvent = mkPassthroughFn('emit'); +export const passthroughEventAsync = mkPassthroughFn('emitAndWait'); diff --git a/lib/image/index.js b/lib/image/index.js deleted file mode 100644 index 248dfb6..0000000 --- a/lib/image/index.js +++ /dev/null @@ -1,106 +0,0 @@ -'use strict'; - -const Promise = require('bluebird'); -const looksSame = require('looks-same'); -const PngImg = require('png-img'); -const utils = require('png-img/utils'); -const SafeRect = require('./safe-rect'); - -module.exports = class Image { - static create(buffer) { - return new this(buffer); - } - - constructor(buffer) { - this._img = new PngImg(buffer); - } - - crop(rect, opts = {}) { - rect = this._scale(rect, (opts).scaleFactor); - const imageSize = this.getSize(); - const safeRect = SafeRect.create(rect, imageSize); - - this._img.crop( - safeRect.left, - safeRect.top, - safeRect.width, - safeRect.height - ); - - return Promise.resolve(this); - } - - getSize() { - return this._img.size(); - } - - getRGBA(x, y) { - return this._img.get(x, y); - } - - save(file) { - return Promise.fromCallback((cb) => this._img.save(file, cb)); - } - - clear(area, opts = {}) { - area = this._scale(area, (opts).scaleFactor); - this._img.fill( - area.left, - area.top, - area.width, - area.height, - '#000000' - ); - } - - join(newImage) { - const imageSize = this.getSize(); - this._img - .setSize(imageSize.width, imageSize.height + newImage.getSize().height) - .insert(newImage._img, 0, imageSize.height); - - return this; - } - - _scale(area, scaleFactor) { - scaleFactor = scaleFactor || 1; - - return { - left: area.left * scaleFactor, - top: area.top * scaleFactor, - width: area.width * scaleFactor, - height: area.height * scaleFactor - }; - } - - static fromBase64(base64) { - return new Image(new Buffer(base64, 'base64')); - } - - static RGBToString(rgb) { - return utils.RGBToString(rgb); - } - - static compare(path1, path2, opts = {}) { - const compareOptions = { - ignoreCaret: opts.canHaveCaret, - pixelRatio: opts.pixelRatio, - ...opts.compareOpts - }; - ['tolerance', 'antialiasingTolerance'].forEach((option) => { - if (option in opts) { - compareOptions[option] = opts[option]; - } - }); - return Promise.fromCallback((cb) => { - looksSame(path1, path2, compareOptions, cb); - }); - } - - static buildDiff(opts) { - const {diffColor: highlightColor, ...otherOpts} = opts; - const diffOptions = {highlightColor, ...otherOpts}; - - return Promise.fromCallback((cb) => looksSame.createDiff(diffOptions, cb)); - } -}; diff --git a/lib/image/index.ts b/lib/image/index.ts new file mode 100644 index 0000000..f6b4b5c --- /dev/null +++ b/lib/image/index.ts @@ -0,0 +1,128 @@ +import Bluebird from 'bluebird'; +import looksSame from 'looks-same'; +import PngImg, { Size, Color } from 'png-img'; +import * as utils from 'png-img/utils'; + +import SafeRect from './safe-rect'; + +import type { SerializedRect } from '../types/rect'; + +type ImageCompareOpts = { + canHaveCaret?: boolean; + pixelRatio?: number; + compareOpts?: looksSame.LooksSameOptions; + tolerance?: number; + antialiasingTolerance?: number; +}; + +type ImageBuildDiffOpts = Omit & { + diffColor: string; +}; + +type LooksSameResult = Parameters[2]>[1]; + +type ScaleOpts = { + scaleFactor?: number; +}; + +export default class Image { + private _img: PngImg; + + public static create(buffer: Buffer): Image { + return new this(buffer); + } + + constructor(buffer: Buffer) { + this._img = new PngImg(buffer); + } + + public crop(rect: SerializedRect, opts: ScaleOpts = {}): Promise { + rect = this._scale(rect, (opts).scaleFactor); + const imageSize = this.getSize(); + const safeRect = SafeRect.create(rect, imageSize); + + this._img.crop( + safeRect.left, + safeRect.top, + safeRect.width, + safeRect.height + ); + + return Bluebird.resolve(this); + } + + public getSize(): Size { + return this._img.size(); + } + + public getRGBA(x: number, y: number): Color { + return this._img.get(x, y); + } + + public save(file: string): Promise { + return Bluebird.fromCallback((cb) => this._img.save(file, cb)); + } + + public clear(area: SerializedRect, opts: ScaleOpts = {}): void { + area = this._scale(area, (opts).scaleFactor); + this._img.fill( + area.left, + area.top, + area.width, + area.height, + '#000000' + ); + } + + public join(newImage: Image): this { + const imageSize = this.getSize(); + this._img + .setSize(imageSize.width, imageSize.height + newImage.getSize().height) + .insert(newImage._img, 0, imageSize.height); + + return this; + } + + private _scale(area: SerializedRect, scaleFactor?: number): SerializedRect { + scaleFactor = scaleFactor || 1; + return { + left: area.left * scaleFactor, + top: area.top * scaleFactor, + width: area.width * scaleFactor, + height: area.height * scaleFactor + }; + } + + public static fromBase64(base64: string): Image { + return new Image(Buffer.from(base64, 'base64')); + } + + public static RGBToString(rgb: Color): string { + return utils.RGBToString(rgb); + } + + public static compare(path1: string, path2: string, opts: ImageCompareOpts = {}): Promise { + const compareOptions = { + ignoreCaret: opts.canHaveCaret, + pixelRatio: opts.pixelRatio, + ...opts.compareOpts + }; + + (['tolerance', 'antialiasingTolerance'] as const).forEach((option) => { + if (option in opts) { + compareOptions[option] = opts[option]; + } + }); + + return Bluebird.fromCallback((cb) => { + looksSame(path1, path2, compareOptions, cb); + }); + } + + public static buildDiff(opts: ImageBuildDiffOpts): Promise { + const {diffColor: highlightColor, ...otherOpts} = opts; + const diffOptions = {highlightColor, ...otherOpts}; + + return Bluebird.fromCallback((cb) => looksSame.createDiff(diffOptions, cb)); + } +}; diff --git a/lib/image/safe-rect.js b/lib/image/safe-rect.js deleted file mode 100644 index 55dfa73..0000000 --- a/lib/image/safe-rect.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -module.exports = class SafeRect { - static create(rect, imageSize) { - return new SafeRect(rect, imageSize); - } - - constructor(rect, imageSize) { - this._rect = rect; - this._imageSize = imageSize; - } - - get left() { - return this._calcCoord('left'); - } - - get top() { - return this._calcCoord('top'); - } - - _calcCoord(coord) { - return Math.max(this._rect[coord], 0); - } - - get width() { - return this._calcSize('width', 'left'); - } - - get height() { - return this._calcSize('height', 'top'); - } - - _calcSize(size, coord) { - const rectCoord = this._calcCoord(coord); - - return Math.min(this._rect[size], this._imageSize[size] - rectCoord); - } -}; diff --git a/lib/image/safe-rect.ts b/lib/image/safe-rect.ts new file mode 100644 index 0000000..6402686 --- /dev/null +++ b/lib/image/safe-rect.ts @@ -0,0 +1,37 @@ +import type { Size } from 'png-img'; + +import type { SerializedRect } from '../types/rect'; + +export default class SafeRect { + public static create(rect: SerializedRect, imageSize: Size): SafeRect { + return new SafeRect(rect, imageSize); + } + + constructor(private _rect: SerializedRect, private _imageSize: Size) {} + + public get left(): number { + return this._calcCoord('left'); + } + + public get top(): number { + return this._calcCoord('top'); + } + + private _calcCoord(coord: keyof SerializedRect): number { + return Math.max(this._rect[coord], 0); + } + + public get width(): number { + return this._calcSize('width', 'left'); + } + + public get height(): number { + return this._calcSize('height', 'top'); + } + + private _calcSize(size: keyof Size, coord: keyof SerializedRect): number { + const rectCoord = this._calcCoord(coord); + + return Math.min(this._rect[size], this._imageSize[size] - rectCoord); + } +}; diff --git a/lib/promise-utils/index.js b/lib/promise-utils/index.js deleted file mode 100644 index 05872b3..0000000 --- a/lib/promise-utils/index.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -const Promise = require('bluebird'); - -exports.waitForResults = (promises) => { - return Promise.all(promises.map((p) => p.reflect())) - .then((res) => { - const firstRejection = res.find((v) => v.isRejected()); - return firstRejection ? Promise.reject(firstRejection.reason()) : res.map((r) => r.value()); - }); -}; diff --git a/lib/promise-utils/index.ts b/lib/promise-utils/index.ts new file mode 100644 index 0000000..8ad3248 --- /dev/null +++ b/lib/promise-utils/index.ts @@ -0,0 +1,8 @@ +import Bluebird from 'bluebird'; + +export async function waitForResults(promises: Array>): Promise> { + const res = await Bluebird.all(promises.map((p) => p.reflect())); + const firstRejection = res.find((v) => v.isRejected()); + + return firstRejection ? Bluebird.reject(firstRejection.reason()) : res.map((r) => r.value()); +} diff --git a/lib/screen-shooter/index.js b/lib/screen-shooter/index.js deleted file mode 100644 index c63e891..0000000 --- a/lib/screen-shooter/index.js +++ /dev/null @@ -1,55 +0,0 @@ -'use strict'; - -const Promise = require('bluebird'); -const Viewport = require('./viewport'); -const HeightViewportError = require('./viewport/coord-validator/errors/height-viewport-error'); - -module.exports = class ScreenShooter { - static create(browser) { - return new ScreenShooter(browser); - } - - constructor(browser) { - this._browser = browser; - } - - capture(page, opts = {}) { - const {allowViewportOverflow, compositeImage, screenshotDelay, selectorToScroll} = opts; - const viewportOpts = {allowViewportOverflow, compositeImage}; - const cropImageOpts = {screenshotDelay, compositeImage, selectorToScroll}; - - return this._browser.captureViewportImage(page, screenshotDelay) - .then((viewportImage) => Viewport.create(page.viewport, viewportImage, page.pixelRatio, viewportOpts)) - .then((viewport) => this._cropImage(viewport, page, cropImageOpts)); - } - - _cropImage(viewport, page, opts) { - try { - viewport.validate(page.captureArea, this._browser); - } catch (e) { - return e instanceof HeightViewportError && opts.compositeImage - ? this._extendImage(viewport, page, opts) - : Promise.reject(e); - } - - viewport.ignoreAreas(page.ignoreAreas); - - return viewport.crop(page.captureArea); - } - - _extendImage(viewport, page, opts) { - const scrollHeight = Math.min( - viewport.getVerticalOverflow(page.captureArea), - page.viewport.height - ); - - return this._browser - .scrollBy({x: 0, y: scrollHeight, selector: opts.selectorToScroll}) - .then(() => { - page.viewport.top += scrollHeight; - return this._browser.captureViewportImage(page, opts.screenshotDelay); - }) - .then((newImage) => viewport.extendBy(scrollHeight, newImage)) - .then(() => this._cropImage(viewport, page, opts)); - } -}; diff --git a/lib/screen-shooter/index.ts b/lib/screen-shooter/index.ts new file mode 100644 index 0000000..828f1fe --- /dev/null +++ b/lib/screen-shooter/index.ts @@ -0,0 +1,64 @@ +import Bluebird from 'bluebird'; + +import Viewport from './viewport'; +import HeightViewportError from './viewport/coord-validator/errors/height-viewport-error'; + +import type { Page } from '../types/page'; +import type Image from '../image'; +import type { ExistingBrowser } from '../types/existing-browser'; + +type ScreenShooterOpts = { + allowViewportOverflow?: boolean; + compositeImage?: boolean; + screenshotDelay?: number; + selectorToScroll?: string; +}; + +export default class ScreenShooter { + public static create(browser: ExistingBrowser): ScreenShooter { + return new ScreenShooter(browser); + } + + constructor(private _browser: ExistingBrowser) {} + + public async capture(page: Page, opts: ScreenShooterOpts = {}): Promise { + const {allowViewportOverflow, compositeImage, screenshotDelay, selectorToScroll} = opts; + const viewportOpts = {allowViewportOverflow, compositeImage}; + const cropImageOpts = {screenshotDelay, compositeImage, selectorToScroll}; + + const viewportImage = await this._browser.captureViewportImage(page, screenshotDelay); + const viewport = Viewport.create(page.viewport, viewportImage, page.pixelRatio, viewportOpts); + + return this._cropImage(viewport, page, cropImageOpts); + } + + private async _cropImage(viewport: Viewport, page: Page, opts: ScreenShooterOpts): Promise { + try { + viewport.validate(page.captureArea, this._browser); + } catch (e) { + return e instanceof HeightViewportError && opts.compositeImage + ? this._extendImage(viewport, page, opts) + : Bluebird.reject(e); + } + + viewport.ignoreAreas(page.ignoreAreas); + + return viewport.crop(page.captureArea); + } + + private async _extendImage(viewport: Viewport, page: Page, opts: ScreenShooterOpts): Promise { + const scrollHeight = Math.min( + viewport.getVerticalOverflow(page.captureArea), + page.viewport.height + ); + + await this._browser.scrollBy({x: 0, y: scrollHeight, selector: opts.selectorToScroll}); + page.viewport.top += scrollHeight; + + const newImage = await this._browser.captureViewportImage(page, opts.screenshotDelay); + + await viewport.extendBy(scrollHeight, newImage); + + return this._cropImage(viewport, page, opts); + } +}; diff --git a/lib/screen-shooter/viewport/coord-validator/errors/height-viewport-error.js b/lib/screen-shooter/viewport/coord-validator/errors/height-viewport-error.ts similarity index 57% rename from lib/screen-shooter/viewport/coord-validator/errors/height-viewport-error.js rename to lib/screen-shooter/viewport/coord-validator/errors/height-viewport-error.ts index 1578980..afdb346 100644 --- a/lib/screen-shooter/viewport/coord-validator/errors/height-viewport-error.js +++ b/lib/screen-shooter/viewport/coord-validator/errors/height-viewport-error.ts @@ -1,10 +1,8 @@ -'use strict'; - /** * Height of the element is larger than viewport */ -module.exports = class HeightViewportError extends Error { - constructor(message) { + export default class HeightViewportError extends Error { + constructor(message: string) { super(message); this.name = this.constructor.name; diff --git a/lib/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.js b/lib/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.ts similarity index 61% rename from lib/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.js rename to lib/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.ts index aaac055..0dbb738 100644 --- a/lib/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.js +++ b/lib/screen-shooter/viewport/coord-validator/errors/offset-viewport-error.ts @@ -1,10 +1,8 @@ -'use strict'; - /** * Position of an element is outside of a viewport left, top or right bounds */ -module.exports = class OffsetViewportError extends Error { - constructor(message) { + export default class OffsetViewportError extends Error { + constructor(message: string) { super(message); this.name = this.constructor.name; diff --git a/lib/screen-shooter/viewport/coord-validator/index.js b/lib/screen-shooter/viewport/coord-validator/index.ts similarity index 70% rename from lib/screen-shooter/viewport/coord-validator/index.js rename to lib/screen-shooter/viewport/coord-validator/index.ts index 3888b71..e7c17ce 100644 --- a/lib/screen-shooter/viewport/coord-validator/index.js +++ b/lib/screen-shooter/viewport/coord-validator/index.ts @@ -1,34 +1,36 @@ -'use strict'; +import debug from 'debug'; -const debug = require('debug'); -const HeightViewportError = require('./errors/height-viewport-error'); -const OffsetViewportError = require('./errors/offset-viewport-error'); +import HeightViewportError from './errors/height-viewport-error'; +import OffsetViewportError from './errors/offset-viewport-error'; -const isOutsideOfViewport = (viewport, cropArea) => +import type { SerializedRect } from '../../../types/rect'; +import type { ExistingBrowser } from '../../../types/existing-browser'; + +const isOutsideOfViewport = (viewport: SerializedRect, cropArea: SerializedRect): boolean => cropArea.top < 0 || cropArea.left < 0 || cropArea.left + cropArea.width > viewport.width; -module.exports = class CoordValidator { - static create(...args) { - return new CoordValidator(...args); +type CoordValidatorOpts = { + allowViewportOverflow?: boolean; + compositeImage?: boolean; +}; + +export default class CoordValidator { + private _log: debug.Debugger; + private _opts: CoordValidatorOpts; + + public static create(browser: ExistingBrowser, opts: CoordValidatorOpts): CoordValidator { + return new CoordValidator(browser, opts); } - /** - * @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 = {}) { + constructor(browser: ExistingBrowser, opts: CoordValidatorOpts = {}) { this._log = debug('gemini-core:coord-validator:' + browser.id); this._opts = opts; } /** * Validates compatibility of viewport and crop area coordinates - * @param {Object} viewport - * @param {Object} cropArea */ - validate(viewport, cropArea) { + public validate(viewport: SerializedRect, cropArea: SerializedRect): void { this._log('viewport size', viewport); this._log('crop area', cropArea); @@ -47,10 +49,8 @@ module.exports = class CoordValidator { /** * Reports error if crop area is outside of viewport - * @returns {OffsetViewportError} - * @private */ - _reportOffsetViewportError() { + private _reportOffsetViewportError(): never { 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. @@ -70,12 +70,8 @@ module.exports = class CoordValidator { * 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) { + private _reportHeightViewportError(viewport: SerializedRect, cropArea: SerializedRect): never { this._log('crop area bottom bound is outside of the viewport height'); const message = `Can not capture the specified region of the viewport. diff --git a/lib/screen-shooter/viewport/index.js b/lib/screen-shooter/viewport/index.ts similarity index 52% rename from lib/screen-shooter/viewport/index.js rename to lib/screen-shooter/viewport/index.ts index 102efbb..05901b2 100644 --- a/lib/screen-shooter/viewport/index.js +++ b/lib/screen-shooter/viewport/index.ts @@ -1,37 +1,43 @@ -'use strict'; +import _ from 'lodash'; -const _ = require('lodash'); +import CoordValidator from './coord-validator'; -const CoordValidator = require('./coord-validator'); +import type Image from '../../image'; +import type { SerializedRect } from '../../types/rect'; +import type { ExistingBrowser } from '../../types/existing-browser'; -module.exports = class Viewport { - static create(...args) { - return new Viewport(...args); +type ViewportOpts = { + allowViewportOverflow?: boolean; + compositeImage?: boolean; +}; + +export default class Viewport { + private _viewport: SerializedRect; + + public static create(viewport: SerializedRect, image: Image, pixelRatio: number, opts: ViewportOpts): Viewport { + return new Viewport(viewport, image, pixelRatio, opts); } - constructor(viewport, image, pixelRatio, opts) { + constructor(viewport: SerializedRect, private _image: Image, private _pixelRatio: number, private _opts: ViewportOpts) { this._viewport = _.clone(viewport); - this._image = image; - this._pixelRatio = pixelRatio; - this._opts = opts; } - validate(captureArea, browser) { + public validate(captureArea: SerializedRect, browser: ExistingBrowser): void { CoordValidator.create(browser, this._opts).validate(this._viewport, captureArea); } - ignoreAreas(areas) { + public ignoreAreas(areas: Array): void { _(areas) .map((area) => this._getIntersectionWithViewport(area)) .compact() .forEach((area) => this._image.clear(this._transformToViewportOrigin(area), {scaleFactor: this._pixelRatio})); } - crop(captureArea) { + public crop(captureArea: SerializedRect): Promise { return this._image.crop(this._transformToViewportOrigin(captureArea), {scaleFactor: this._pixelRatio}); } - _getIntersectionWithViewport(area) { + private _getIntersectionWithViewport(area: SerializedRect): SerializedRect | null { const top = Math.max(this._viewport.top, area.top); const bottom = Math.min(getAreaBottom(this._viewport), getAreaBottom(area)); const left = Math.max(this._viewport.left, area.left); @@ -43,41 +49,42 @@ module.exports = class Viewport { return {top, left, width: right - left, height: bottom - top}; } - _transformToViewportOrigin(area) { + private _transformToViewportOrigin(area: SerializedRect): SerializedRect { return _.extend({}, area, { top: area.top - this._viewport.top, left: area.left - this._viewport.left }); } - save(path) { + public save(path: string): Promise { return this._image.save(path); } - extendBy(scrollHeight, newImage) { + public async extendBy(scrollHeight: number, newImage: Image): Promise { const newImageSize = newImage.getSize(); const physicalScrollHeight = scrollHeight * this._pixelRatio; this._viewport.height += scrollHeight; - return newImage.crop({ + const croppedImage = await newImage.crop({ left: 0, top: newImageSize.height - physicalScrollHeight, width: newImageSize.width, height: physicalScrollHeight - }) - .then((croppedImage) => this._image.join(croppedImage)); + }); + + return this._image.join(croppedImage); } - getVerticalOverflow(captureArea) { + public getVerticalOverflow(captureArea: SerializedRect): number { return (captureArea.top + captureArea.height) - (this._viewport.top + this._viewport.height); } }; -function getAreaBottom(area) { +function getAreaBottom(area: SerializedRect): number { return area.top + area.height; } -function getAreaRight(area) { +function getAreaRight(area: SerializedRect): number { return area.left + area.width; } diff --git a/lib/sets-builder/index.js b/lib/sets-builder/index.js deleted file mode 100644 index 6ef539d..0000000 --- a/lib/sets-builder/index.js +++ /dev/null @@ -1,119 +0,0 @@ -'use strict'; - -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']; - -module.exports = class SetsBuilder { - static create(sets, opts) { - return new SetsBuilder(sets, opts); - } - - constructor(sets, opts) { - this._sets = _.mapValues(sets, (set) => TestSet.create(set)); - this._defaultDir = opts.defaultDir; - - this._filesToUse = this._hasFiles() ? [] : [this._defaultDir]; - } - - useSets(setsToUse) { - this._validateUnknownSets(setsToUse); - - if (!_.isEmpty(setsToUse)) { - this._sets = _.pick(this._sets, setsToUse); - } - - return this; - } - - _validateUnknownSets(setsToUse) { - const setsNames = _.keys(this._sets); - 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); - } - - useFiles(files) { - if (!_.isEmpty(files)) { - this._filesToUse = files; - } - - return this; - } - - useBrowsers(browsers) { - _.forEach(this._sets, (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 this._transformDirsToMasks() - .then(() => this._resolvePaths(projectRoot)) - .then(() => globExtra.expandPaths(this._filesToUse, expandOpts, globOpts)) - .then((expandedFiles) => { - this._validateFoundFiles(expandedFiles); - this._useFiles(expandedFiles); - }) - .then(() => this._expandFiles(expandOpts, globOpts)) - .then(() => SetCollection.create(this._sets)); - } - - _transformDirsToMasks() { - return Promise.map(this._getSets(), (set) => set.transformDirsToMasks()); - } - - _getSets() { - return _.values(this._sets); - } - - _resolvePaths(projectRoot) { - _.forEach(this._sets, (set) => set.resolveFiles(projectRoot)); - } - - _validateFoundFiles(foundFiles) { - if (!_.isEmpty(this._filesToUse) && _.isEmpty(foundFiles)) { - const paths = [].concat(this._filesToUse).join(', '); - throw new Error(`Cannot find files by specified paths: ${paths}`); - } - } - - _useFiles(filesToUse) { - _.forEach(this._sets, (set) => set.useFiles(filesToUse)); - - if (!this._hasFiles()) { - throw new Error('Cannot find files by masks in sets'); - } - } - - _expandFiles(expandOpts, globOpts) { - return Promise.map(this._getSets(), (set) => set.expandFiles(expandOpts, globOpts)); - } - - _hasFiles() { - return _.some(this._sets, (set) => !_.isEmpty(set.getFiles())); - } -}; diff --git a/lib/sets-builder/index.ts b/lib/sets-builder/index.ts new file mode 100644 index 0000000..87a4fe2 --- /dev/null +++ b/lib/sets-builder/index.ts @@ -0,0 +1,135 @@ +import Bluebird from 'bluebird'; +import * as globExtra from 'glob-extra'; +import _ from 'lodash'; +import path from 'path'; + +import SetCollection from './set-collection'; +import TestSet from './test-set'; + +import type { ExpandOpts, GlobOpts } from 'glob-extra'; + +import type { SetsConfig, SetConfig } from '../config/options'; + +const FILE_EXTENSIONS = ['.js']; + +export type TestSetsByPlatform = { + [platform in keyof SetsConfig]: TestSet +} + +type SetsBuilderOpts = { + defaultDir: string; +}; + +export default class SetsBuilder { + private _sets: TestSetsByPlatform; + private _defaultDir: string; + private _filesToUse: Array; + + static create(sets: SetsConfig, opts: SetsBuilderOpts): SetsBuilder { + return new SetsBuilder(sets, opts); + } + + constructor(sets: SetsConfig, opts: SetsBuilderOpts) { + this._sets = _.mapValues(sets, (set) => TestSet.create(set)); + this._defaultDir = opts.defaultDir; + + this._filesToUse = this._hasFiles() ? [] : [this._defaultDir]; + } + + public useSets(setsToUse: Array): this { + this._validateUnknownSets(setsToUse); + + if (!_.isEmpty(setsToUse)) { + this._sets = _.pick(this._sets, setsToUse); + } + + return this; + } + + private _validateUnknownSets(setsToUse: Array): void { + const setsNames = _.keys(this._sets); + 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); + } + + public useFiles(files: Array): this { + if (!_.isEmpty(files)) { + this._filesToUse = files; + } + + return this; + } + + public useBrowsers(browsers: Array): this { + _.forEach(this._sets, (set) => set.useBrowsers(browsers)); + + return this; + } + + public async build(projectRoot: string, globOpts: GlobOpts = {}, fileExtensions: Array = FILE_EXTENSIONS): Promise { + const expandOpts = {formats: fileExtensions, root: projectRoot}; + + if (globOpts.ignore) { + globOpts.ignore = ([] as Array).concat(globOpts.ignore) + .map((ignorePattern) => path.resolve(projectRoot, ignorePattern)); + } + + await this._transformDirsToMasks(); + + this._resolvePaths(projectRoot); + const expandedFiles = await globExtra.expandPaths(this._filesToUse, expandOpts, globOpts); + + this._validateFoundFiles(expandedFiles); + this._useFiles(expandedFiles); + + await this._expandFiles(expandOpts, globOpts); + + return SetCollection.create(this._sets); + } + + private _transformDirsToMasks(): Promise>> { + return Bluebird.map(this._getSets(), (set) => set.transformDirsToMasks()); + } + + private _getSets(): Array { + return _.values(this._sets); + } + + private _resolvePaths(projectRoot: string): void { + _.forEach(this._sets, (set) => set.resolveFiles(projectRoot)); + } + + private _validateFoundFiles(foundFiles: Array): void { + if (!_.isEmpty(this._filesToUse) && _.isEmpty(foundFiles)) { + const paths = ([] as Array).concat(this._filesToUse).join(', '); + throw new Error(`Cannot find files by specified paths: ${paths}`); + } + } + + private _useFiles(filesToUse: Array): void { + _.forEach(this._sets, (set) => set.useFiles(filesToUse)); + + if (!this._hasFiles()) { + throw new Error('Cannot find files by masks in sets'); + } + } + + private _expandFiles(expandOpts: ExpandOpts, globOpts: GlobOpts): Promise> { + return Bluebird.map(this._getSets(), (set) => set.expandFiles(expandOpts, globOpts)); + } + + private _hasFiles(): boolean { + return _.some(this._sets, (set) => !_.isEmpty(set.getFiles())); + } +}; diff --git a/lib/sets-builder/set-collection.js b/lib/sets-builder/set-collection.ts similarity index 54% rename from lib/sets-builder/set-collection.js rename to lib/sets-builder/set-collection.ts index 3100091..1d1a96d 100644 --- a/lib/sets-builder/set-collection.js +++ b/lib/sets-builder/set-collection.ts @@ -1,47 +1,51 @@ -'use strict'; +import _ from 'lodash'; -const _ = require('lodash'); +import TestSet from './test-set'; -module.exports = class SetCollection { - static create(sets) { +import type { TestSetsByPlatform } from "."; + +export default class SetCollection { + private _sets: TestSetsByPlatform; + + static create(sets: TestSetsByPlatform): SetCollection { return new SetCollection(sets); } - constructor(sets) { + constructor(sets: TestSetsByPlatform) { this._sets = sets; } - groupByFile() { + public groupByFile(): Record> { const files = this._getFiles(); const browsers = files.map((file) => this._getBrowsersForFile(file)); return _.zipObject(files, browsers); } - _getFiles() { + private _getFiles(): Array { return this._getFromSets((set) => set.getFiles()); } - _getBrowsersForFile(path) { + private _getBrowsersForFile(path: string): Array { return this._getFromSets((set) => set.getBrowsersForFile(path)); } - groupByBrowser() { + public groupByBrowser(): Record> { const browsers = this._getBrowsers(); const files = browsers.map((browser) => this._getFilesForBrowser(browser)); return _.zipObject(browsers, files); } - _getBrowsers() { + private _getBrowsers(): Array { return this._getFromSets((set) => set.getBrowsers()); } - _getFilesForBrowser(browser) { + private _getFilesForBrowser(browser: string): Array { return this._getFromSets((set) => set.getFilesForBrowser(browser)); } - _getFromSets(cb) { + private _getFromSets Array>(cb: T): Array { return _(this._sets) .map(cb) .flatten() diff --git a/lib/sets-builder/test-set.js b/lib/sets-builder/test-set.js deleted file mode 100644 index def82fb..0000000 --- a/lib/sets-builder/test-set.js +++ /dev/null @@ -1,77 +0,0 @@ -'use strict'; - -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 = class TestSet { - static create(set) { - return new TestSet(set); - } - - constructor(set) { - this._set = _.clone(set); - } - - expandFiles(expandOpts, globOpts = {}) { - const {files, ignoreFiles = []} = this._set; - globOpts = _.clone(globOpts); - globOpts.ignore = [] - .concat(globOpts.ignore || [], ignoreFiles) - .map((p) => path.resolve(expandOpts.root, p)); - - return globExtra.expandPaths(files, expandOpts, globOpts) - .then((expandedFiles) => this._set = _.extend(this._set, {files: expandedFiles})); - } - - transformDirsToMasks() { - return Promise.map(this._set.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) => this._set.files = files); - } - - resolveFiles(projectRoot) { - this._set.files = this._set.files.map((file) => path.resolve(projectRoot, file)); - } - - getFiles() { - return this._set.files; - } - - getBrowsers() { - return this._set.browsers; - } - - getFilesForBrowser(browser) { - return _.includes(this._set.browsers, browser) ? this._set.files : []; - } - - getBrowsersForFile(file) { - return _.includes(this._set.files, file) ? this._set.browsers : []; - } - - useFiles(files) { - if (_.isEmpty(files)) { - return; - } - - this._set.files = _.isEmpty(this._set.files) ? files : mm(files, this._set.files); - } - - useBrowsers(browsers) { - this._set.browsers = _.isEmpty(browsers) - ? this._set.browsers - : _.intersection(this._set.browsers, browsers); - } -}; diff --git a/lib/sets-builder/test-set.ts b/lib/sets-builder/test-set.ts new file mode 100644 index 0000000..95a355e --- /dev/null +++ b/lib/sets-builder/test-set.ts @@ -0,0 +1,87 @@ +import * as globExtra from 'glob-extra'; +import _ from 'lodash'; +import mm from 'micromatch'; +import path from 'path'; +import Bluebird from 'bluebird'; +import baseFs from 'fs'; + +const fs = Bluebird.promisifyAll(baseFs); + +import type { SetConfig } from '../config/options'; + +export default class TestSet { + private _set: SetConfig; + + static create(set: SetConfig): TestSet { + return new TestSet(set); + } + + constructor(set: SetConfig) { + this._set = _.clone(set); + } + + public async expandFiles(expandOpts: globExtra.ExpandOpts, globOpts: globExtra.GlobOpts = {}): Promise { + const {files, ignoreFiles = []} = this._set; + + globOpts = _.clone(globOpts); + globOpts.ignore = ([] as Array) + .concat(globOpts.ignore || [], ignoreFiles) + .map((p) => path.resolve(expandOpts.root, p)); + + const expandedFiles = await globExtra.expandPaths(files, expandOpts, globOpts); + + return this._set = _.extend(this._set, {files: expandedFiles}); + } + + public async transformDirsToMasks(): Promise> { + const files = await Bluebird.map(this._set.files, async (file) => { + if (globExtra.isMask(file)) { + return file; + } + + try { + const stat = await fs.statAsync(file); + + return stat.isDirectory() ? path.join(file, '**') : file; + } catch { + return Bluebird.reject(new Error(`Cannot read such file or directory: '${file}'`)); + } + }); + + return this._set.files = files; + } + + public resolveFiles(projectRoot: string): void { + this._set.files = this._set.files.map((file) => path.resolve(projectRoot, file)); + } + + public getFiles(): Array { + return this._set.files; + } + + public getBrowsers(): Array { + return this._set.browsers; + } + + public getFilesForBrowser(browser: string): Array { + return _.includes(this._set.browsers, browser) ? this._set.files : []; + } + + public getBrowsersForFile(file: string): Array { + return _.includes(this._set.files, file) ? this._set.browsers : []; + } + + public useFiles(files: Array): void { + if (_.isEmpty(files)) { + return; + } + + this._set.files = _.isEmpty(this._set.files) ? files : mm(files, this._set.files); + } + + public useBrowsers(browsers: Array): void { + this._set.browsers = _.isEmpty(browsers) + ? this._set.browsers + : _.intersection(this._set.browsers, browsers); + } +}; diff --git a/lib/temp/index.js b/lib/temp/index.js deleted file mode 100644 index be542d8..0000000 --- a/lib/temp/index.js +++ /dev/null @@ -1,46 +0,0 @@ -'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() -}; diff --git a/lib/temp/index.ts b/lib/temp/index.ts new file mode 100644 index 0000000..8e7c1ba --- /dev/null +++ b/lib/temp/index.ts @@ -0,0 +1,54 @@ +import temp from 'temp'; +import { resolve as resolvePath } from 'path'; +import _ from 'lodash'; + +temp.track(); + +type TempConstructorOpts = { + attach?: boolean; +}; +type SerializedTemp = { + dir: string; +}; + +class Temp { + private _tempDir: string; + + constructor(dir: string, opts: TempConstructorOpts = {}) { + this._tempDir = opts.attach + ? dir + : temp.mkdirSync({ + dir: dir && resolvePath(dir), + prefix: '.screenshots.tmp.' + }); + } + + path(opts: temp.AffixOptions = {}): string { + return temp.path(_.extend(opts, { + dir: this._tempDir + })); + } + + serialize(): SerializedTemp { + return {dir: this._tempDir}; + } +} + +let tempInstance: Temp; + +export function init(dir: string): void { + if (!tempInstance) { + tempInstance = new Temp(dir); + } +} +export function attach(serializedTemp: SerializedTemp): void { + if (!tempInstance) { + tempInstance = new Temp(serializedTemp.dir, {attach: true}); + } +} +export function path(opts: temp.AffixOptions): string { + return tempInstance.path(opts); +} +export function serialize(): SerializedTemp { + return tempInstance.serialize(); +} diff --git a/lib/types/browser.ts b/lib/types/browser.ts new file mode 100644 index 0000000..9cbeaa2 --- /dev/null +++ b/lib/types/browser.ts @@ -0,0 +1,26 @@ +import type { Capabilities, Options } from '@wdio/types'; +import type { Browser as Session } from 'webdriverio'; + +import type { Config } from './config'; + +type BrowserState = { + isBroken: boolean; +} + +export interface Browser { + id: string; + version: string; + + attach(sessionId: string, sessionCaps: Capabilities.DesiredCapabilities, sessionOpts: Options.WebdriverIO): void; + setHttpTimeout(timeout: number): void; + restoreHttpTimeout(): void; + + applyState(state: BrowserState): void; + + fullId: string; + publicAPI: Session<'async'>; + sessionId: string; + config: Config; + state: BrowserState; + capabilities: Capabilities.RemoteCapability; +} diff --git a/lib/types/calibrator.ts b/lib/types/calibrator.ts new file mode 100644 index 0000000..113be24 --- /dev/null +++ b/lib/types/calibrator.ts @@ -0,0 +1,11 @@ +export type Features = { + needsCompatLib: boolean; + pixelRatio: Window['devicePixelRatio']; + innerWidth: Window['innerWidth'] | Element['clientWidth']; +}; + +export type CalibrationResult = Features & { + top: number; + left: number; + usePixelRatio: boolean; +}; diff --git a/lib/types/config.ts b/lib/types/config.ts new file mode 100644 index 0000000..9f1e21c --- /dev/null +++ b/lib/types/config.ts @@ -0,0 +1,12 @@ +interface BrowserConfig { + parallelLimit: number; + sessionUseLimit: number; +} + +export interface Config { + forBrowser(id: string): BrowserConfig; + getBrowserIds(): Array; + system: { + parallelLimit: number; + }; +} diff --git a/lib/types/coverage.ts b/lib/types/coverage.ts new file mode 100644 index 0000000..540bcf5 --- /dev/null +++ b/lib/types/coverage.ts @@ -0,0 +1,14 @@ +import type { CoverageValue } from '../coverage/coverage-level'; + +export interface CoverageError { + ignored: boolean; + message: string; +} + +export interface CoverageByUrl { + [url: string]: CoverageValue; +} + +export interface Coverage { + [prop: string]: CoverageError | CoverageByUrl; +} diff --git a/lib/types/existing-browser.ts b/lib/types/existing-browser.ts new file mode 100644 index 0000000..2904423 --- /dev/null +++ b/lib/types/existing-browser.ts @@ -0,0 +1,41 @@ +import type { Capabilities, Options } from '@wdio/types'; + +import type { Browser } from "./browser"; +import type { Page } from './page'; +import type Calibrator from '../calibrator'; +import type { AsyncEmitter } from '../events'; +import type Image from '../image'; + +type BrowserMeta = { + pid: NodeJS.Process['pid']; + browserVersion: string; +}; + +type ScrollParams = { + selector?: string; + x: number; + y: number; +}; + +export interface ExistingBrowser extends Browser { + init( + options: { + sessionId: string, + sessionCaps: Capabilities.DesiredCapabilities, + sessionOpts: Options.WebdriverIO + }, + calibrator: Calibrator + ): Promise; + reinit(sessionId: string, sessionOpts: Options.WebdriverIO): Promise; + markAsBroken(): void; + quit(): void; + prepareScreenshot(selectors: Array, opts: Object): Promise; + open(url: string): Promise; + evalScript(script: string): Promise; + injectScript(script: string): Promise; + captureViewportImage(page?: Page, screenshotDelay?: number): Promise; + scrollBy(params: ScrollParams): Promise; + + meta: BrowserMeta; + emitter: AsyncEmitter; +} diff --git a/lib/types/new-browser.ts b/lib/types/new-browser.ts new file mode 100644 index 0000000..f3e6bc6 --- /dev/null +++ b/lib/types/new-browser.ts @@ -0,0 +1,9 @@ +import type Bluebird from "bluebird"; + +import type { Browser } from "./browser"; + +export interface NewBrowser extends Browser { + init(): Bluebird; + reset(): Bluebird; + quit(): Bluebird; +} diff --git a/lib/types/page.ts b/lib/types/page.ts new file mode 100644 index 0000000..732f212 --- /dev/null +++ b/lib/types/page.ts @@ -0,0 +1,13 @@ +import type { Coverage } from "./coverage"; +import type { SerializedRect } from "./rect"; + +export interface Page { + captureArea: SerializedRect; + ignoreAreas: Array; + viewport: SerializedRect; + documentHeight: number; + documentWidth: number; + coverage: Coverage; + canHaveCaret: boolean; + pixelRatio: number; +} diff --git a/lib/types/pool.ts b/lib/types/pool.ts new file mode 100644 index 0000000..edddc7f --- /dev/null +++ b/lib/types/pool.ts @@ -0,0 +1,9 @@ +import type Bluebird from 'bluebird'; + +import type { NewBrowser } from "./new-browser"; + +export interface Pool { + getBrowser(id: string, opts?: any): Bluebird; + freeBrowser(browser: NewBrowser, opts?: any): Bluebird; + cancel(): void; +}; diff --git a/lib/types/rect.ts b/lib/types/rect.ts new file mode 100644 index 0000000..ea34255 --- /dev/null +++ b/lib/types/rect.ts @@ -0,0 +1,6 @@ +export interface SerializedRect { + top: number; + left: number; + width: number; + height: number; +} diff --git a/lib/utils.js b/lib/utils.ts similarity index 51% rename from lib/utils.js rename to lib/utils.ts index e12b963..c517dae 100644 --- a/lib/utils.js +++ b/lib/utils.ts @@ -1,6 +1,5 @@ -'use strict'; - -exports.requireWithNoCache = function(moduleName) { +export function requireWithNoCache(moduleName: string): NodeRequire { delete require.cache[moduleName]; + return require(moduleName); }; diff --git a/package-lock.json b/package-lock.json index ca3913a..7fc7b9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,12 +13,12 @@ "bluebird": "^3.4.6", "browserify": "^13.3.0", "debug": "^2.2.0", - "gemini-configparser": "^1.0.0", - "glob-extra": "^5.0.1", + "gemini-configparser": "github:gemini-testing/configparser#FEI-17917", + "glob-extra": "github:gemini-testing/glob-extra#FEI-24748", "lodash": "^4.17.15", - "looks-same": "^7.3.0", + "looks-same": "github:gemini-testing/looks-same#FEI-17919", "micromatch": "^4.0.2", - "png-img": "^3.3.6", + "png-img": "github:gemini-testing/png-img#FEI-17920", "sizzle": "^2.3.3", "temp": "^0.8.3", "uglify-js": "^2.8.29", @@ -26,6 +26,18 @@ "yallist": "^3.0.3" }, "devDependencies": { + "@tsconfig/recommended": "^1.0.1", + "@types/bluebird": "^3.5.36", + "@types/browserify": "^12.0.37", + "@types/color-diff": "^1.2.1", + "@types/debug": "^4.1.7", + "@types/lodash": "^4.14.178", + "@types/micromatch": "^4.0.2", + "@types/node": "^8.10.66", + "@types/sizzle": "^2.3.3", + "@types/temp": "^0.9.1", + "@types/webdriverio": "^5.0.0", + "@types/yallist": "^4.0.1", "app-module-path": "^1.1.0", "chai": "^3.4.1", "chai-as-promised": "^5.3.0", @@ -33,8 +45,10 @@ "eslint": "^3.1.1", "eslint-config-gemini-testing": "^2.2.0", "mocha": "^7.1.2", + "npm-run-all": "^4.1.5", "proxyquire": "^1.7.3", - "sinon": "^2.2.0" + "sinon": "^2.2.0", + "typescript": "^4.5.5" }, "engines": { "node": ">= 8" @@ -72,6 +86,30 @@ "node": ">= 8" } }, + "node_modules/@sindresorhus/is": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.4.0.tgz", + "integrity": "sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@textlint/ast-node-types": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-4.2.1.tgz", @@ -93,6 +131,355 @@ "unified": "^6.1.6" } }, + "node_modules/@tsconfig/recommended": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/recommended/-/recommended-1.0.1.tgz", + "integrity": "sha512-2xN+iGTbPBEzGSnVp/Hd64vKJCJWxsi9gfs88x4PPMyEjHJoA3o5BY9r5OLPHIZU2pAQxkSAsJFqn6itClP8mQ==", + "dev": true + }, + "node_modules/@types/aria-query": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.0.tgz", + "integrity": "sha512-P+dkdFu0n08PDIvw+9nT9ByQnd+Udc8DaWPb9HKfaPwCvWvQpC5XaMRx2xLWECm9x1VKNps6vEAlirjA6+uNrQ==", + "dev": true + }, + "node_modules/@types/bluebird": { + "version": "3.5.36", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz", + "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==", + "dev": true + }, + "node_modules/@types/braces": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/braces/-/braces-3.0.1.tgz", + "integrity": "sha512-+euflG6ygo4bn0JHtn4pYqcXwRtLvElQ7/nnjDu7iYG56H0+OhCd7d6Ug0IE3WcFpZozBKW2+80FUbv5QGk5AQ==", + "dev": true + }, + "node_modules/@types/browserify": { + "version": "12.0.37", + "resolved": "https://registry.npmjs.org/@types/browserify/-/browserify-12.0.37.tgz", + "integrity": "sha512-rGVZQhqlBMdnU0Wcq/RDO6+I1tppM42SqVq5ZEXiw2ft/A55Ro+dz4aKTy28gniwOIxZhRFqb5N+qnbg7J040g==", + "dev": true, + "dependencies": { + "@types/insert-module-globals": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "dev": true, + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "node_modules/@types/color-diff": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/color-diff/-/color-diff-1.2.1.tgz", + "integrity": "sha512-iemOGPqMODUJyDbd8TVV9vdaHfbO1Z7rQhql1umt75Z7NUminF7MXvWaNxh5+aizZpeei2WFGGrpmOocuqh8oQ==", + "dev": true + }, + "node_modules/@types/debug": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", + "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "dev": true, + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "dev": true + }, + "node_modules/@types/insert-module-globals": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/insert-module-globals/-/insert-module-globals-7.0.2.tgz", + "integrity": "sha512-b+XCUBUioZoveg4e8+D/wGVIvQcuV6TNHPy53aeY0YBydOOZhAtX2Sdr4x97uWKKy9Xrt0SUKsPxbT9e0u/x9Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/keyv": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", + "integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.14.178", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz", + "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==", + "dev": true + }, + "node_modules/@types/micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-oqXqVb0ci19GtH0vOA/U2TmHTcRY9kuZl4mqUxe0QmJAlIW13kzhuK5pi1i9+ngav8FjpSb9FVS/GE00GLX1VA==", + "dev": true, + "dependencies": { + "@types/braces": "*" + } + }, + "node_modules/@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "8.10.66", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", + "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", + "dev": true + }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "dev": true + }, + "node_modules/@types/temp": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@types/temp/-/temp-0.9.1.tgz", + "integrity": "sha512-yDQ8Y+oQi9V7VkexwE6NBSVyNuyNFeGI275yWXASc2DjmxNicMi9O50KxDpNlST1kBbV9jKYBHGXhgNYFMPqtA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ua-parser-js": { + "version": "0.7.36", + "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz", + "integrity": "sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==", + "dev": true + }, + "node_modules/@types/webdriverio": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/webdriverio/-/webdriverio-5.0.0.tgz", + "integrity": "sha512-x4XylDdijSMmhvpyFdQ6/Ow1CvJBY1Z38MnK3gAtGDy3MnR3AnI8CW9O5B8Q0PNLgLAMA466ghsolhb7+xaZ/Q==", + "deprecated": "This is a stub types definition. webdriverio provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "webdriverio": "*" + } + }, + "node_modules/@types/which": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/which/-/which-1.3.2.tgz", + "integrity": "sha512-8oDqyLC7eD4HM307boe2QWKyuzdzWBj56xI/imSl2cpL+U3tCMaTAkMJ4ee5JBZ/FsOJlvRGeIShiZDAl1qERA==", + "dev": true + }, + "node_modules/@types/yallist": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/yallist/-/yallist-4.0.1.tgz", + "integrity": "sha512-G3FNJfaYtN8URU6wd6+uwFI62KO79j7n3XTYcwcFncP8gkfoi0b821GoVVt0oqKVnCqKYOMNKIGpakPoFhzAGA==", + "dev": true + }, + "node_modules/@types/yauzl": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", + "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@wdio/config": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-7.16.14.tgz", + "integrity": "sha512-CdB8F4XFbuH9W3JaLYQoJMPRzM+GQirg9Ay1dW4xNcmJk7m3TJbk3/L78oz8ey1TpCLjQTG8aNqI4SZlFO4JRg==", + "dev": true, + "dependencies": { + "@wdio/logger": "7.16.0", + "@wdio/types": "7.16.14", + "deepmerge": "^4.0.0", + "glob": "^7.1.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@wdio/logger": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.16.0.tgz", + "integrity": "sha512-/6lOGb2Iow5eSsy7RJOl1kCwsP4eMlG+/QKro5zUJsuyNJSQXf2ejhpkzyKWLgQbHu83WX6cM1014AZuLkzoQg==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "loglevel": "^1.6.0", + "loglevel-plugin-prefix": "^0.8.4", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@wdio/logger/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wdio/logger/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@wdio/logger/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@wdio/logger/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@wdio/logger/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@wdio/logger/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wdio/logger/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wdio/logger/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wdio/protocols": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-7.16.7.tgz", + "integrity": "sha512-Wv40pNQcLiPzQ3o98Mv4A8T1EBQ6k4khglz/e2r16CTm+F3DDYh8eLMAsU5cgnmuwwDKX1EyOiFwieykBn5MCg==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@wdio/repl": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-7.16.14.tgz", + "integrity": "sha512-Ezih0Y+lsGkKv3H3U56hdWgZiQGA3VaAYguSLd9+g1xbQq+zMKqSmfqECD9bAy+OgCCiVTRstES6lHZxJVPhAg==", + "dev": true, + "dependencies": { + "@wdio/utils": "7.16.14" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@wdio/types": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-7.16.14.tgz", + "integrity": "sha512-AyNI9iBSos9xWBmiFAF3sBs6AJXO/55VppU/eeF4HRdbZMtMarnvMuahM+jlUrA3vJSmDW+ufelG0MT//6vrnw==", + "dev": true, + "dependencies": { + "@types/node": "^17.0.4", + "got": "^11.8.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@wdio/types/node_modules/@types/node": { + "version": "17.0.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz", + "integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==", + "dev": true + }, + "node_modules/@wdio/utils": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-7.16.14.tgz", + "integrity": "sha512-wwin8nVpIlhmXJkq6GJw9aDDzgLOJKgXTcEua0T2sdXjoW78u5Ly/GZrFXTjMGhacFvoZfitTrjyfyy4CxMVvw==", + "dev": true, + "dependencies": { + "@wdio/logger": "7.16.0", + "@wdio/types": "7.16.14", + "p-iteration": "^1.1.8" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/acorn": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz", @@ -163,6 +550,41 @@ "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "node_modules/ajv": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", @@ -291,6 +713,108 @@ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, + "node_modules/archiver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.0.tgz", + "integrity": "sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==", + "dev": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.0", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver-utils/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/archiver/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/archiver/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/are-we-there-yet": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", @@ -309,6 +833,15 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/aria-query": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", + "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, "node_modules/array-filter": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", @@ -364,6 +897,12 @@ "node": "*" } }, + "node_modules/async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", + "dev": true + }, "node_modules/babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -710,6 +1249,15 @@ "isarray": "^1.0.0" } }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -730,11 +1278,51 @@ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/cached-path-relative": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==" }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caller-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", @@ -871,6 +1459,36 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, + "node_modules/chrome-launcher": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.0.tgz", + "integrity": "sha512-ZQqX5kb9H0+jy1OqLnWampfocrtSZaGl7Ny3F9GRha85o4odbL8x55paUzh51UC7cEmZ5obp3H2Mm70uC2PpRA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0" + }, + "bin": { + "print-chrome-path": "bin/print-chrome-path.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/chrome-launcher/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -915,6 +1533,24 @@ "wordwrap": "0.0.2" } }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/clone-response/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -966,6 +1602,64 @@ "source-map": "~0.5.3" } }, + "node_modules/compress-commons": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "dev": true, + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/compress-commons/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/compress-commons/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/compress-commons/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1035,6 +1729,78 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "node_modules/crc-32": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.1.tgz", + "integrity": "sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w==", + "dev": true, + "dependencies": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.3.1" + }, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "dev": true, + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/crc32-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/crc32-stream/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/crc32-stream/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", @@ -1069,6 +1835,31 @@ "sha.js": "^2.4.8" } }, + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dev": true, + "dependencies": { + "node-fetch": "2.6.7" + } + }, + "node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, "node_modules/crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -1090,6 +1881,18 @@ "node": "*" } }, + "node_modules/css-shorthand-properties": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/css-shorthand-properties/-/css-shorthand-properties-1.1.1.tgz", + "integrity": "sha512-Md+Juc7M3uOdbAFwOYlTrccIZ7oCFuzrhKYQjdeUEW/sE1hv17Jp/Bws+ReOPpGVBTYCBoYo+G17V5Qo8QQ75A==", + "dev": true + }, + "node_modules/css-value": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", + "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", + "dev": true + }, "node_modules/d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", @@ -1174,6 +1977,24 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -1250,6 +2071,42 @@ "node": ">=0.4.0" } }, + "node_modules/devtools": { + "version": "7.16.15", + "resolved": "https://registry.npmjs.org/devtools/-/devtools-7.16.15.tgz", + "integrity": "sha512-34WOK2tzeFiIvu1nln0Gwjxwo0slt75ATloI9cNnEtW21NM5PrWwcMUjn6Gl2kLl0eqtLVH+uHhBgInbT4qvFg==", + "dev": true, + "dependencies": { + "@types/node": "^17.0.4", + "@types/ua-parser-js": "^0.7.33", + "@wdio/config": "7.16.14", + "@wdio/logger": "7.16.0", + "@wdio/protocols": "7.16.7", + "@wdio/types": "7.16.14", + "@wdio/utils": "7.16.14", + "chrome-launcher": "^0.15.0", + "edge-paths": "^2.1.0", + "puppeteer-core": "^13.1.3", + "query-selector-shadow-dom": "^1.0.0", + "ua-parser-js": "^1.0.1", + "uuid": "^8.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/devtools-protocol": { + "version": "0.0.966116", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.966116.tgz", + "integrity": "sha512-uCqUDw5Y4ajQoFqGdYbvjrVdsXqlDb54JcmEPO4kpXjSU+Szyisi2BQDfnSVLeHRDELmzOcm9reZ959slDwD7g==", + "dev": true + }, + "node_modules/devtools/node_modules/@types/node": { + "version": "17.0.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz", + "integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==", + "dev": true + }, "node_modules/diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -1353,6 +2210,31 @@ "readable-stream": "^2.0.2" } }, + "node_modules/edge-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/edge-paths/-/edge-paths-2.2.1.tgz", + "integrity": "sha512-AI5fC7dfDmCdKo3m5y7PkYE8m6bMqR6pvVpgtrZkkhcJXFLelUgkjrhk3kXXx8Kbw2cRaTT4LkOR7hqf39KJdw==", + "dev": true, + "dependencies": { + "@types/which": "^1.3.2", + "which": "^2.0.2" + } + }, + "node_modules/edge-paths/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/elliptic": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", @@ -1387,23 +2269,41 @@ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", "dev": true }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-abstract": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", - "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", "dev": true, "dependencies": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -1421,6 +2321,24 @@ "node": ">= 0.4" } }, + "node_modules/es-abstract/node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -1713,6 +2631,15 @@ "node": ">=0.10.0" } }, + "node_modules/exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -1726,6 +2653,49 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-1.3.0.tgz", "integrity": "sha1-0VFvsP9WJNLr+RI+odrFoZlABPg=" }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extract-zip/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/extract-zip/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "node_modules/falafel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/falafel/-/falafel-1.2.0.tgz", @@ -1740,6 +2710,12 @@ "node": ">=0.4.0" } }, + "node_modules/fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, "node_modules/fast-glob": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.6.tgz", @@ -1801,6 +2777,15 @@ "format": "^0.2.2" } }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, "node_modules/figures": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", @@ -1954,11 +2939,6 @@ "node": ">=6 <7 || >=8" } }, - "node_modules/fs-extra/node_modules/graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2000,9 +2980,9 @@ } }, "node_modules/gemini-configparser": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gemini-configparser/-/gemini-configparser-1.0.0.tgz", - "integrity": "sha1-lKjZTqTqESh9nEChnHSSFo7toCA=", + "version": "1.1.0", + "resolved": "git+ssh://git@github.com/gemini-testing/configparser.git#41ef2f1d239445e20d4f35d6b864e2bb6c50f535", + "license": "MIT", "dependencies": { "lodash": "^4.17.4" } @@ -2039,6 +3019,63 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", @@ -2062,8 +3099,8 @@ }, "node_modules/glob-extra": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/glob-extra/-/glob-extra-5.0.1.tgz", - "integrity": "sha512-GUHn8P6idLsg69F2Trsy+9ZuafapcSbJ+rr4I7Ge9dwt85z6gAndiFdtaI6nOJ+d/vGNnbKFNkQYTRfVSbVJlA==", + "resolved": "git+ssh://git@github.com/gemini-testing/glob-extra.git#3a444cc836096139573b8770b52de98dc7532308", + "license": "MIT", "dependencies": { "bluebird": "^3.5.1", "fast-glob": "^3.2.4", @@ -2073,7 +3110,7 @@ "normalize-path": "^3.0.0" }, "engines": { - "node": ">= 6" + "node": ">= 8" } }, "node_modules/glob-parent": { @@ -2096,11 +3133,41 @@ "node": ">=0.10.0" } }, + "node_modules/got": { + "version": "11.8.3", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.3.tgz", + "integrity": "sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, "node_modules/graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", - "devOptional": true + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true }, "node_modules/growl": { "version": "1.10.5", @@ -2134,6 +3201,15 @@ "node": ">=0.10.0" } }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -2144,10 +3220,25 @@ } }, "node_modules/has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, "engines": { "node": ">= 0.4" }, @@ -2200,6 +3291,12 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, "node_modules/htmlescape": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", @@ -2222,11 +3319,66 @@ "readable-stream": "^2.0.2" } }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, "node_modules/https-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=" }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -2348,6 +3500,20 @@ "typedarray": "^0.0.6" } }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/interpret": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", @@ -2373,6 +3539,24 @@ "is-decimal": "^1.0.0" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -2385,15 +3569,31 @@ "node": ">=8" } }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "node_modules/is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true, "engines": { "node": ">= 0.4" @@ -2420,6 +3620,21 @@ "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", "dev": true }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2475,6 +3690,18 @@ "xtend": "^4.0.0" } }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -2483,6 +3710,21 @@ "node": ">=0.12.0" } }, + "node_modules/is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", @@ -2505,12 +3747,13 @@ "dev": true }, "node_modules/is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "dependencies": { - "has": "^1.0.3" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -2525,6 +3768,30 @@ "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", "dev": true }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-symbol": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", @@ -2540,6 +3807,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-whitespace-character": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", @@ -2552,6 +3831,18 @@ "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==", "dev": true }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -2590,6 +3881,18 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, "node_modules/json-stable-stringify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", @@ -2646,6 +3949,27 @@ "node": "*" } }, + "node_modules/keyv": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.1.1.tgz", + "integrity": "sha512-tGv1yP6snQVDSM4X6yxrv2zzq/EvpW+oYiUz6aueW1u9CtS8RzUQYxxmFwgZlO2jSgCxQbchhxaqXXp2hnKGpQ==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/ky": { + "version": "0.28.7", + "resolved": "https://registry.npmjs.org/ky/-/ky-0.28.7.tgz", + "integrity": "sha512-a23i6qSr/ep15vdtw/zyEQIDLoUaKDg9Jf04CYl/0ns/wXNYna26zJpI+MeIFaPeDvkrjLPrKtKOiiI3IE53RQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/ky?sponsor=1" + } + }, "node_modules/labeled-stream-splicer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz", @@ -2669,6 +3993,18 @@ "node": ">=0.10.0" } }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, "node_modules/levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -2682,6 +4018,31 @@ "node": ">= 0.8.0" } }, + "node_modules/lighthouse-logger": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.3.0.tgz", + "integrity": "sha512-BbqAKApLb9ywUli+0a+PcV04SyJ/N1q/8qgCNe6U97KbPCS1BTksEuHFLYdvc8DltuhfxIUBqDZsC0bBGtl3lA==", + "dev": true, + "dependencies": { + "debug": "^2.6.9", + "marky": "^1.2.2" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -2695,16 +4056,70 @@ "node": ">=6" } }, - "node_modules/lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + "node_modules/lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", + "dev": true + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, + "node_modules/lodash.isobject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", + "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true }, "node_modules/lodash.memoize": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=", + "dev": true + }, + "node_modules/lodash.zip": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", + "integrity": "sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=", + "dev": true + }, "node_modules/log-symbols": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", @@ -2764,6 +4179,25 @@ "node": ">=4" } }, + "node_modules/loglevel": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", + "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, + "node_modules/loglevel-plugin-prefix": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.8.4.tgz", + "integrity": "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==", + "dev": true + }, "node_modules/lolex": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", @@ -2780,8 +4214,8 @@ }, "node_modules/looks-same": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/looks-same/-/looks-same-7.3.0.tgz", - "integrity": "sha512-pOfwX2d0frSt7H1cuBjDbw9Kry5QwkrFri0qJvLwV1sI0cbWkwYkpd7fF7SqSIfYKAZhgeB8PM3fyhUYz7xgqA==", + "resolved": "git+ssh://git@github.com/gemini-testing/looks-same.git#29b03617e39ad1d866576d7b8ce4717181fb00e9", + "license": "MIT", "dependencies": { "color-diff": "^1.1.0", "concat-stream": "^1.6.2", @@ -2810,6 +4244,15 @@ "typedarray": "^0.0.6" } }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -2832,6 +4275,12 @@ "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", "dev": true }, + "node_modules/marky": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.2.tgz", + "integrity": "sha512-k1dB2HNeaNyORco8ulVEhctyEGkKHb2YWAhDsxeFlW2nROIirsctBYzKwwS3Vza+sKTS1zO4Z+n9/+9WbGLIxQ==", + "dev": true + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -2842,6 +4291,15 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -3203,6 +4661,12 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "node_modules/node-abi": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.5.0.tgz", @@ -3238,6 +4702,38 @@ "semver": "^5.7.0" } }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -3246,6 +4742,90 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm-run-all/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/npm-run-all/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", @@ -3274,9 +4854,9 @@ } }, "node_modules/object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3383,6 +4963,24 @@ "node": ">=0.10.0" } }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-iteration": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/p-iteration/-/p-iteration-1.1.8.tgz", + "integrity": "sha512-IMFBSDIYcPNnW7uWYGrBqmvTiq7W0uB0fJn6shQZs7dlF3OvrHOre+JT9ikSZ7gZS3vWqclVgoQSvToJrns7uQ==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -3467,6 +5065,19 @@ "is-hexadecimal": "^1.0.0" } }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/path-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", @@ -3495,6 +5106,15 @@ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", @@ -3517,6 +5137,18 @@ "isarray": "0.0.1" } }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", @@ -3532,6 +5164,12 @@ "node": ">=0.12" } }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, "node_modules/picomatch": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.5.tgz", @@ -3540,6 +5178,85 @@ "node": ">=8" } }, + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/pluralize": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", @@ -3548,9 +5265,9 @@ }, "node_modules/png-img": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/png-img/-/png-img-3.3.6.tgz", - "integrity": "sha512-Izy7Cgr39ufFG8q6kL2pIz1XknMyqbRJ7GrD4lnr3vKgyJvZA8RkkQBzGpq07kuBghiQjSdQHi4gCr6X2gck5Q==", + "resolved": "git+ssh://git@github.com/gemini-testing/png-img.git#02782729cd295c6e2acfd618520d70e94c2c6846", "hasInstallScript": true, + "license": "MIT", "dependencies": { "nan": "^2.14.0", "prebuild-install": "^7.0.0" @@ -3602,6 +5319,18 @@ "node": ">= 0.8.0" } }, + "node_modules/printj": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.3.1.tgz", + "integrity": "sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==", + "dev": true, + "bin": { + "printj": "bin/printj.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -3624,6 +5353,12 @@ "node": ">=0.4.0" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, "node_modules/proxyquire": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", @@ -3654,19 +5389,101 @@ "safe-buffer": "^5.1.2" } }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "node_modules/puppeteer-core": { + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-13.3.1.tgz", + "integrity": "sha512-II9uo5MFh+otoJSoYp/kfY3jf1iWt0ySKyK8vFVfdbn3rl+k3SLh9nQRdINyoO1Kt6Tk4dPp6GZipD9jgU9wmw==", + "dev": true, + "dependencies": { + "cross-fetch": "3.1.5", + "debug": "4.3.3", + "devtools-protocol": "0.0.960912", + "extract-zip": "2.0.1", + "https-proxy-agent": "5.0.0", + "pkg-dir": "4.2.0", + "progress": "2.0.3", + "proxy-from-env": "1.1.0", + "rimraf": "3.0.2", + "tar-fs": "2.1.1", + "unbzip2-stream": "1.4.3", + "ws": "8.5.0" + }, + "engines": { + "node": ">=10.18.1" + } + }, + "node_modules/puppeteer-core/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/puppeteer-core/node_modules/devtools-protocol": { + "version": "0.0.960912", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.960912.tgz", + "integrity": "sha512-I3hWmV9rWHbdnUdmMKHF2NuYutIM2kXz2mdXW8ha7TbRlGTVs+PF+PsB5QWvpCek4Fy9B+msiispCfwlhG5Sqg==", + "dev": true + }, + "node_modules/puppeteer-core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/puppeteer-core/node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/puppeteer-core/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "node_modules/query-selector-shadow-dom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.0.tgz", + "integrity": "sha512-bK0/0cCI+R8ZmOF1QjT7HupDUYCxbf/9TJgAmSXQxZpftXmTAeil9DRoCnTDkWbvOyZzhcMBwKpptWcdkGFIMg==", + "dev": true }, "node_modules/querystring": { "version": "0.2.0", @@ -3704,6 +5521,18 @@ } ] }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -3743,6 +5572,20 @@ "readable-stream": "^2.0.2" } }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", @@ -3770,6 +5613,15 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/readdir-glob": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz", + "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.4" + } + }, "node_modules/readdirp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", @@ -3891,6 +5743,12 @@ "path-parse": "^1.0.6" } }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, "node_modules/resolve-from": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", @@ -3900,6 +5758,24 @@ "node": ">=0.10.0" } }, + "node_modules/responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "dev": true, + "dependencies": { + "lowercase-keys": "^2.0.0" + } + }, + "node_modules/resq": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/resq/-/resq-1.10.2.tgz", + "integrity": "sha512-HmgVS3j+FLrEDBTDYysPdPVF9/hioDMJ/otOiQDKqk77YfZeeLOj0qi34yObumcud1gBpk+wpBTEg4kMicD++A==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^2.0.1" + } + }, "node_modules/restore-cursor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", @@ -3922,6 +5798,12 @@ "node": ">=0.10.0" } }, + "node_modules/rgb2hex": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.5.tgz", + "integrity": "sha512-22MOP1Rh7sAo1BZpDG6R5RFYzR2lYEgwq7HEmyW2qcsOqR2lQKmn+O//xV3YG/0rrhMC6KVX2hU+ZXuaw9a5bw==", + "dev": true + }, "node_modules/right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -4008,6 +5890,21 @@ "semver": "bin/semver" } }, + "node_modules/serialize-error": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", + "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -4034,6 +5931,27 @@ "sha.js": "~2.4.4" } }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/shell-quote": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", @@ -4063,6 +5981,20 @@ "node": ">=0.11.0" } }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", @@ -4156,6 +6088,38 @@ "node": ">=0.10.0" } }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "dev": true + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -4225,28 +6189,15 @@ "node": ">=0.10.0" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimleft": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", - "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", + "node_modules/string.prototype.padend": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz", + "integrity": "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==", "dev": true, "dependencies": { + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "string.prototype.trimstart": "^1.0.0" + "es-abstract": "^1.19.1" }, "engines": { "node": ">= 0.4" @@ -4255,31 +6206,27 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.trimright": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", - "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "string.prototype.trimend": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dev": true, "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4536,6 +6483,12 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, "node_modules/traverse": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", @@ -4597,11 +6550,55 @@ "node": "*" } }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, + "node_modules/typescript": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ua-parser-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.2.tgz", + "integrity": "sha512-00y/AXhx0/SsnI51fTc0rLRmafiGOM4/O+ny10Ps7f+j/b8p/ZY11ytMgznXkOVo4GQ+KwQG5UQLkLGirsACRg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "engines": { + "node": "*" + } + }, "node_modules/uglify-js": { "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", @@ -4646,6 +6643,55 @@ "umd": "bin/cli.js" } }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/unbzip2-stream/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/undeclared-identifiers": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", @@ -4789,6 +6835,25 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "node_modules/vfile": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", @@ -4824,6 +6889,128 @@ "indexof": "0.0.1" } }, + "node_modules/webdriver": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-7.16.14.tgz", + "integrity": "sha512-wfD3Okv+XJVMzrFVSTkhU381pJn2HlbKyURC7uY4E2QLaalhJLrrqekofBOUsr7WMf9nqoQwiVHQygnyt0afFw==", + "dev": true, + "dependencies": { + "@types/node": "^17.0.4", + "@wdio/config": "7.16.14", + "@wdio/logger": "7.16.0", + "@wdio/protocols": "7.16.7", + "@wdio/types": "7.16.14", + "@wdio/utils": "7.16.14", + "got": "^11.0.2", + "ky": "^0.28.5", + "lodash.merge": "^4.6.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/webdriver/node_modules/@types/node": { + "version": "17.0.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz", + "integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==", + "dev": true + }, + "node_modules/webdriverio": { + "version": "7.16.15", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-7.16.15.tgz", + "integrity": "sha512-f9Hdn0CTX2y1E3kbN/6QLUXo0JZlnnhPkuJbBlSJMV3+/xFj5MBcBszJBT5Frwzcs48YNikimPbR79VLxfX3AA==", + "dev": true, + "dependencies": { + "@types/aria-query": "^5.0.0", + "@types/node": "^17.0.4", + "@wdio/config": "7.16.14", + "@wdio/logger": "7.16.0", + "@wdio/protocols": "7.16.7", + "@wdio/repl": "7.16.14", + "@wdio/types": "7.16.14", + "@wdio/utils": "7.16.14", + "archiver": "^5.0.0", + "aria-query": "^5.0.0", + "css-shorthand-properties": "^1.1.1", + "css-value": "^0.0.1", + "devtools": "7.16.15", + "devtools-protocol": "^0.0.966116", + "fs-extra": "^10.0.0", + "get-port": "^5.1.1", + "grapheme-splitter": "^1.0.2", + "lodash.clonedeep": "^4.5.0", + "lodash.isobject": "^3.0.2", + "lodash.isplainobject": "^4.0.6", + "lodash.zip": "^4.2.0", + "minimatch": "^3.0.4", + "puppeteer-core": "^13.1.3", + "query-selector-shadow-dom": "^1.0.0", + "resq": "^1.9.1", + "rgb2hex": "0.2.5", + "serialize-error": "^8.0.0", + "webdriver": "7.16.14" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/webdriverio/node_modules/@types/node": { + "version": "17.0.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz", + "integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==", + "dev": true + }, + "node_modules/webdriverio/node_modules/fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/webdriverio/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/webdriverio/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -4836,6 +7023,22 @@ "which": "bin/which" } }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", @@ -4964,8 +7167,29 @@ "dependencies": { "mkdirp": "^0.5.1" }, - "engines": { - "node": ">=0.10.0" + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/x-is-string": { @@ -5115,6 +7339,73 @@ "y18n": "^4.0.0", "yargs-parser": "^13.1.2" } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/zip-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "dev": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/zip-stream/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/zip-stream/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } } }, "dependencies": { @@ -5141,6 +7432,21 @@ "fastq": "^1.6.0" } }, + "@sindresorhus/is": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.4.0.tgz", + "integrity": "sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "requires": { + "defer-to-connect": "^2.0.0" + } + }, "@textlint/ast-node-types": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-4.2.1.tgz", @@ -5162,6 +7468,313 @@ "unified": "^6.1.6" } }, + "@tsconfig/recommended": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/recommended/-/recommended-1.0.1.tgz", + "integrity": "sha512-2xN+iGTbPBEzGSnVp/Hd64vKJCJWxsi9gfs88x4PPMyEjHJoA3o5BY9r5OLPHIZU2pAQxkSAsJFqn6itClP8mQ==", + "dev": true + }, + "@types/aria-query": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.0.tgz", + "integrity": "sha512-P+dkdFu0n08PDIvw+9nT9ByQnd+Udc8DaWPb9HKfaPwCvWvQpC5XaMRx2xLWECm9x1VKNps6vEAlirjA6+uNrQ==", + "dev": true + }, + "@types/bluebird": { + "version": "3.5.36", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz", + "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==", + "dev": true + }, + "@types/braces": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/braces/-/braces-3.0.1.tgz", + "integrity": "sha512-+euflG6ygo4bn0JHtn4pYqcXwRtLvElQ7/nnjDu7iYG56H0+OhCd7d6Ug0IE3WcFpZozBKW2+80FUbv5QGk5AQ==", + "dev": true + }, + "@types/browserify": { + "version": "12.0.37", + "resolved": "https://registry.npmjs.org/@types/browserify/-/browserify-12.0.37.tgz", + "integrity": "sha512-rGVZQhqlBMdnU0Wcq/RDO6+I1tppM42SqVq5ZEXiw2ft/A55Ro+dz4aKTy28gniwOIxZhRFqb5N+qnbg7J040g==", + "dev": true, + "requires": { + "@types/insert-module-globals": "*", + "@types/node": "*" + } + }, + "@types/cacheable-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "dev": true, + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "@types/color-diff": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/color-diff/-/color-diff-1.2.1.tgz", + "integrity": "sha512-iemOGPqMODUJyDbd8TVV9vdaHfbO1Z7rQhql1umt75Z7NUminF7MXvWaNxh5+aizZpeei2WFGGrpmOocuqh8oQ==", + "dev": true + }, + "@types/debug": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", + "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "dev": true, + "requires": { + "@types/ms": "*" + } + }, + "@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "dev": true + }, + "@types/insert-module-globals": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/insert-module-globals/-/insert-module-globals-7.0.2.tgz", + "integrity": "sha512-b+XCUBUioZoveg4e8+D/wGVIvQcuV6TNHPy53aeY0YBydOOZhAtX2Sdr4x97uWKKy9Xrt0SUKsPxbT9e0u/x9Q==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/keyv": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", + "integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/lodash": { + "version": "4.14.178", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz", + "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==", + "dev": true + }, + "@types/micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-oqXqVb0ci19GtH0vOA/U2TmHTcRY9kuZl4mqUxe0QmJAlIW13kzhuK5pi1i9+ngav8FjpSb9FVS/GE00GLX1VA==", + "dev": true, + "requires": { + "@types/braces": "*" + } + }, + "@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "dev": true + }, + "@types/node": { + "version": "8.10.66", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", + "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", + "dev": true + }, + "@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "dev": true + }, + "@types/temp": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@types/temp/-/temp-0.9.1.tgz", + "integrity": "sha512-yDQ8Y+oQi9V7VkexwE6NBSVyNuyNFeGI275yWXASc2DjmxNicMi9O50KxDpNlST1kBbV9jKYBHGXhgNYFMPqtA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/ua-parser-js": { + "version": "0.7.36", + "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz", + "integrity": "sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==", + "dev": true + }, + "@types/webdriverio": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/webdriverio/-/webdriverio-5.0.0.tgz", + "integrity": "sha512-x4XylDdijSMmhvpyFdQ6/Ow1CvJBY1Z38MnK3gAtGDy3MnR3AnI8CW9O5B8Q0PNLgLAMA466ghsolhb7+xaZ/Q==", + "dev": true, + "requires": { + "webdriverio": "*" + } + }, + "@types/which": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/which/-/which-1.3.2.tgz", + "integrity": "sha512-8oDqyLC7eD4HM307boe2QWKyuzdzWBj56xI/imSl2cpL+U3tCMaTAkMJ4ee5JBZ/FsOJlvRGeIShiZDAl1qERA==", + "dev": true + }, + "@types/yallist": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/yallist/-/yallist-4.0.1.tgz", + "integrity": "sha512-G3FNJfaYtN8URU6wd6+uwFI62KO79j7n3XTYcwcFncP8gkfoi0b821GoVVt0oqKVnCqKYOMNKIGpakPoFhzAGA==", + "dev": true + }, + "@types/yauzl": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", + "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==", + "dev": true, + "optional": true, + "requires": { + "@types/node": "*" + } + }, + "@wdio/config": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-7.16.14.tgz", + "integrity": "sha512-CdB8F4XFbuH9W3JaLYQoJMPRzM+GQirg9Ay1dW4xNcmJk7m3TJbk3/L78oz8ey1TpCLjQTG8aNqI4SZlFO4JRg==", + "dev": true, + "requires": { + "@wdio/logger": "7.16.0", + "@wdio/types": "7.16.14", + "deepmerge": "^4.0.0", + "glob": "^7.1.2" + } + }, + "@wdio/logger": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.16.0.tgz", + "integrity": "sha512-/6lOGb2Iow5eSsy7RJOl1kCwsP4eMlG+/QKro5zUJsuyNJSQXf2ejhpkzyKWLgQbHu83WX6cM1014AZuLkzoQg==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "loglevel": "^1.6.0", + "loglevel-plugin-prefix": "^0.8.4", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@wdio/protocols": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-7.16.7.tgz", + "integrity": "sha512-Wv40pNQcLiPzQ3o98Mv4A8T1EBQ6k4khglz/e2r16CTm+F3DDYh8eLMAsU5cgnmuwwDKX1EyOiFwieykBn5MCg==", + "dev": true + }, + "@wdio/repl": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-7.16.14.tgz", + "integrity": "sha512-Ezih0Y+lsGkKv3H3U56hdWgZiQGA3VaAYguSLd9+g1xbQq+zMKqSmfqECD9bAy+OgCCiVTRstES6lHZxJVPhAg==", + "dev": true, + "requires": { + "@wdio/utils": "7.16.14" + } + }, + "@wdio/types": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-7.16.14.tgz", + "integrity": "sha512-AyNI9iBSos9xWBmiFAF3sBs6AJXO/55VppU/eeF4HRdbZMtMarnvMuahM+jlUrA3vJSmDW+ufelG0MT//6vrnw==", + "dev": true, + "requires": { + "@types/node": "^17.0.4", + "got": "^11.8.1" + }, + "dependencies": { + "@types/node": { + "version": "17.0.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz", + "integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==", + "dev": true + } + } + }, + "@wdio/utils": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-7.16.14.tgz", + "integrity": "sha512-wwin8nVpIlhmXJkq6GJw9aDDzgLOJKgXTcEua0T2sdXjoW78u5Ly/GZrFXTjMGhacFvoZfitTrjyfyy4CxMVvw==", + "dev": true, + "requires": { + "@wdio/logger": "7.16.0", + "@wdio/types": "7.16.14", + "p-iteration": "^1.1.8" + } + }, "acorn": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz", @@ -5213,6 +7826,32 @@ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==" }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "ajv": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", @@ -5301,27 +7940,104 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "app-module-path": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-1.1.0.tgz", + "integrity": "sha1-pqxTaEUPIJufW4bpo+Smq2/nUxw=", + "dev": true + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "archiver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.0.tgz", + "integrity": "sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==", + "dev": true, + "requires": { + "archiver-utils": "^2.1.0", + "async": "^3.2.0", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", "dev": true, "requires": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "readable-stream": "^2.0.0" + }, + "dependencies": { + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } } }, - "app-module-path": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-1.1.0.tgz", - "integrity": "sha1-pqxTaEUPIJufW4bpo+Smq2/nUxw=", - "dev": true - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, "are-we-there-yet": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", @@ -5340,6 +8056,12 @@ "sprintf-js": "~1.0.2" } }, + "aria-query": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", + "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", + "dev": true + }, "array-filter": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", @@ -5394,6 +8116,12 @@ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, + "async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", + "dev": true + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -5693,6 +8421,12 @@ } } }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -5708,11 +8442,42 @@ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" }, + "cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true + }, + "cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + } + }, "cached-path-relative": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==" }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "caller-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", @@ -5823,6 +8588,26 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, + "chrome-launcher": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.0.tgz", + "integrity": "sha512-ZQqX5kb9H0+jy1OqLnWampfocrtSZaGl7Ny3F9GRha85o4odbL8x55paUzh51UC7cEmZ5obp3H2Mm70uC2PpRA==", + "dev": true, + "requires": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + } + } + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -5863,6 +8648,23 @@ "wordwrap": "0.0.2" } }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + }, + "dependencies": { + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + } + } + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -5907,6 +8709,46 @@ "source-map": "~0.5.3" } }, + "compress-commons": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "dev": true, + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5975,6 +8817,54 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "crc-32": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.1.tgz", + "integrity": "sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w==", + "dev": true, + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.3.1" + } + }, + "crc32-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "dev": true, + "requires": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", @@ -6009,6 +8899,28 @@ "sha.js": "^2.4.8" } }, + "cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dev": true, + "requires": { + "node-fetch": "2.6.7" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -6027,6 +8939,18 @@ "randomfill": "^1.0.3" } }, + "css-shorthand-properties": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/css-shorthand-properties/-/css-shorthand-properties-1.1.1.tgz", + "integrity": "sha512-Md+Juc7M3uOdbAFwOYlTrccIZ7oCFuzrhKYQjdeUEW/sE1hv17Jp/Bws+ReOPpGVBTYCBoYo+G17V5Qo8QQ75A==", + "dev": true + }, + "css-value": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", + "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=", + "dev": true + }, "d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", @@ -6095,6 +9019,18 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true + }, + "defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -6155,6 +9091,41 @@ } } }, + "devtools": { + "version": "7.16.15", + "resolved": "https://registry.npmjs.org/devtools/-/devtools-7.16.15.tgz", + "integrity": "sha512-34WOK2tzeFiIvu1nln0Gwjxwo0slt75ATloI9cNnEtW21NM5PrWwcMUjn6Gl2kLl0eqtLVH+uHhBgInbT4qvFg==", + "dev": true, + "requires": { + "@types/node": "^17.0.4", + "@types/ua-parser-js": "^0.7.33", + "@wdio/config": "7.16.14", + "@wdio/logger": "7.16.0", + "@wdio/protocols": "7.16.7", + "@wdio/types": "7.16.14", + "@wdio/utils": "7.16.14", + "chrome-launcher": "^0.15.0", + "edge-paths": "^2.1.0", + "puppeteer-core": "^13.1.3", + "query-selector-shadow-dom": "^1.0.0", + "ua-parser-js": "^1.0.1", + "uuid": "^8.0.0" + }, + "dependencies": { + "@types/node": { + "version": "17.0.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz", + "integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==", + "dev": true + } + } + }, + "devtools-protocol": { + "version": "0.0.966116", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.966116.tgz", + "integrity": "sha512-uCqUDw5Y4ajQoFqGdYbvjrVdsXqlDb54JcmEPO4kpXjSU+Szyisi2BQDfnSVLeHRDELmzOcm9reZ959slDwD7g==", + "dev": true + }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -6242,6 +9213,27 @@ "readable-stream": "^2.0.2" } }, + "edge-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/edge-paths/-/edge-paths-2.2.1.tgz", + "integrity": "sha512-AI5fC7dfDmCdKo3m5y7PkYE8m6bMqR6pvVpgtrZkkhcJXFLelUgkjrhk3kXXx8Kbw2cRaTT4LkOR7hqf39KJdw==", + "dev": true, + "requires": { + "@types/which": "^1.3.2", + "which": "^2.0.2" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "elliptic": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", @@ -6276,23 +9268,41 @@ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", "dev": true }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, "es-abstract": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", - "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", "dev": true, "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" }, "dependencies": { "object-keys": { @@ -6300,6 +9310,18 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } } } }, @@ -6547,6 +9569,12 @@ "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", "dev": true }, + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", + "dev": true + }, "expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -6557,6 +9585,35 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-1.3.0.tgz", "integrity": "sha1-0VFvsP9WJNLr+RI+odrFoZlABPg=" }, + "extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "requires": { + "@types/yauzl": "^2.9.1", + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "falafel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/falafel/-/falafel-1.2.0.tgz", @@ -6568,6 +9625,12 @@ "object-keys": "^1.0.6" } }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, "fast-glob": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.6.tgz", @@ -6619,6 +9682,15 @@ "format": "^0.2.2" } }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, "figures": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", @@ -6739,13 +9811,6 @@ "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" - } } }, "fs.realpath": { @@ -6781,9 +9846,8 @@ } }, "gemini-configparser": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gemini-configparser/-/gemini-configparser-1.0.0.tgz", - "integrity": "sha1-lKjZTqTqESh9nEChnHSSFo7toCA=", + "version": "git+ssh://git@github.com/gemini-testing/configparser.git#41ef2f1d239445e20d4f35d6b864e2bb6c50f535", + "from": "gemini-configparser@github:gemini-testing/configparser#FEI-17917", "requires": { "lodash": "^4.17.4" } @@ -6803,19 +9867,55 @@ "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", "dev": true, "requires": { - "is-property": "^1.0.0" + "is-property": "^1.0.0" + } + }, + "get-assigned-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "dev": true + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" } }, - "get-assigned-identifiers": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", - "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } }, "github-from-package": { "version": "0.0.0", @@ -6836,9 +9936,8 @@ } }, "glob-extra": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/glob-extra/-/glob-extra-5.0.1.tgz", - "integrity": "sha512-GUHn8P6idLsg69F2Trsy+9ZuafapcSbJ+rr4I7Ge9dwt85z6gAndiFdtaI6nOJ+d/vGNnbKFNkQYTRfVSbVJlA==", + "version": "git+ssh://git@github.com/gemini-testing/glob-extra.git#3a444cc836096139573b8770b52de98dc7532308", + "from": "glob-extra@github:gemini-testing/glob-extra#FEI-24748", "requires": { "bluebird": "^3.5.1", "fast-glob": "^3.2.4", @@ -6862,11 +9961,35 @@ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", "dev": true }, + "got": { + "version": "11.8.3", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.3.tgz", + "integrity": "sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg==", + "dev": true, + "requires": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + } + }, "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", - "devOptional": true + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true }, "growl": { "version": "1.10.5", @@ -6891,6 +10014,12 @@ "ansi-regex": "^2.0.0" } }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -6898,11 +10027,20 @@ "dev": true }, "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "dev": true }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -6942,6 +10080,12 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, "htmlescape": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", @@ -6961,11 +10105,54 @@ "readable-stream": "^2.0.2" } }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + } + }, "https-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=" }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -7066,6 +10253,17 @@ } } }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, "interpret": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", @@ -7088,6 +10286,21 @@ "is-decimal": "^1.0.0" } }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -7097,15 +10310,25 @@ "binary-extensions": "^2.0.0" } }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true }, "is-date-object": { @@ -7120,6 +10343,12 @@ "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==", "dev": true }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -7166,11 +10395,26 @@ "xtend": "^4.0.0" } }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, + "is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", @@ -7190,12 +10434,13 @@ "dev": true }, "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "requires": { - "has": "^1.0.3" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, "is-resolvable": { @@ -7204,6 +10449,21 @@ "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", "dev": true }, + "is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "dev": true + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-symbol": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", @@ -7213,6 +10473,15 @@ "has-symbols": "^1.0.1" } }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, "is-whitespace-character": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", @@ -7225,6 +10494,15 @@ "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==", "dev": true }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -7257,6 +10535,18 @@ "esprima": "^4.0.0" } }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, "json-stable-stringify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", @@ -7298,6 +10588,21 @@ "through": ">=2.2.7 <3" } }, + "keyv": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.1.1.tgz", + "integrity": "sha512-tGv1yP6snQVDSM4X6yxrv2zzq/EvpW+oYiUz6aueW1u9CtS8RzUQYxxmFwgZlO2jSgCxQbchhxaqXXp2hnKGpQ==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "ky": { + "version": "0.28.7", + "resolved": "https://registry.npmjs.org/ky/-/ky-0.28.7.tgz", + "integrity": "sha512-a23i6qSr/ep15vdtw/zyEQIDLoUaKDg9Jf04CYl/0ns/wXNYna26zJpI+MeIFaPeDvkrjLPrKtKOiiI3IE53RQ==", + "dev": true + }, "labeled-stream-splicer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz", @@ -7320,6 +10625,15 @@ "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" }, + "lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -7330,6 +10644,28 @@ "type-check": "~0.3.2" } }, + "lighthouse-logger": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.3.0.tgz", + "integrity": "sha512-BbqAKApLb9ywUli+0a+PcV04SyJ/N1q/8qgCNe6U97KbPCS1BTksEuHFLYdvc8DltuhfxIUBqDZsC0bBGtl3lA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "marky": "^1.2.2" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -7345,11 +10681,65 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", + "dev": true + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, + "lodash.isobject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", + "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=", + "dev": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, "lodash.memoize": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=" }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=", + "dev": true + }, + "lodash.zip": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", + "integrity": "sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=", + "dev": true + }, "log-symbols": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", @@ -7399,6 +10789,18 @@ } } }, + "loglevel": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", + "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", + "dev": true + }, + "loglevel-plugin-prefix": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.8.4.tgz", + "integrity": "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==", + "dev": true + }, "lolex": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", @@ -7411,9 +10813,8 @@ "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" }, "looks-same": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/looks-same/-/looks-same-7.3.0.tgz", - "integrity": "sha512-pOfwX2d0frSt7H1cuBjDbw9Kry5QwkrFri0qJvLwV1sI0cbWkwYkpd7fF7SqSIfYKAZhgeB8PM3fyhUYz7xgqA==", + "version": "git+ssh://git@github.com/gemini-testing/looks-same.git#29b03617e39ad1d866576d7b8ce4717181fb00e9", + "from": "looks-same@github:gemini-testing/looks-same#FEI-17919", "requires": { "color-diff": "^1.1.0", "concat-stream": "^1.6.2", @@ -7438,6 +10839,12 @@ } } }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -7459,6 +10866,12 @@ "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==", "dev": true }, + "marky": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.2.tgz", + "integrity": "sha512-k1dB2HNeaNyORco8ulVEhctyEGkKHb2YWAhDsxeFlW2nROIirsctBYzKwwS3Vza+sKTS1zO4Z+n9/+9WbGLIxQ==", + "dev": true + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -7469,6 +10882,12 @@ "safe-buffer": "^5.1.2" } }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -7768,6 +11187,12 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "node-abi": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.5.0.tgz", @@ -7796,11 +11221,95 @@ "semver": "^5.7.0" } }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true + }, + "npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", @@ -7823,9 +11332,9 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", "dev": true }, "object-keys": { @@ -7907,6 +11416,18 @@ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, + "p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true + }, + "p-iteration": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/p-iteration/-/p-iteration-1.1.8.tgz", + "integrity": "sha512-IMFBSDIYcPNnW7uWYGrBqmvTiq7W0uB0fJn6shQZs7dlF3OvrHOre+JT9ikSZ7gZS3vWqclVgoQSvToJrns7uQ==", + "dev": true + }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -7979,6 +11500,16 @@ "is-hexadecimal": "^1.0.0" } }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, "path-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", @@ -8001,6 +11532,12 @@ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", @@ -8020,6 +11557,15 @@ "isarray": "0.0.1" } }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, "pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", @@ -8032,11 +11578,74 @@ "sha.js": "^2.4.8" } }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, "picomatch": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.5.tgz", "integrity": "sha512-Zisqgaq/4P05ZclrU/g5XrzFqVo7YiJx+EP4haeVI9S7kvtZmZgmQMZfcvjEus9JcMhqZfQZObimT5ZydvKJGA==" }, + "pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + } + } + }, "pluralize": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", @@ -8044,9 +11653,8 @@ "dev": true }, "png-img": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/png-img/-/png-img-3.3.6.tgz", - "integrity": "sha512-Izy7Cgr39ufFG8q6kL2pIz1XknMyqbRJ7GrD4lnr3vKgyJvZA8RkkQBzGpq07kuBghiQjSdQHi4gCr6X2gck5Q==", + "version": "git+ssh://git@github.com/gemini-testing/png-img.git#02782729cd295c6e2acfd618520d70e94c2c6846", + "from": "png-img@github:gemini-testing/png-img#FEI-17920", "requires": { "nan": "^2.14.0", "prebuild-install": "^7.0.0" @@ -8083,6 +11691,12 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "printj": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.3.1.tgz", + "integrity": "sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==", + "dev": true + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -8099,6 +11713,12 @@ "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", "dev": true }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, "proxyquire": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", @@ -8145,6 +11765,70 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" }, + "puppeteer-core": { + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-13.3.1.tgz", + "integrity": "sha512-II9uo5MFh+otoJSoYp/kfY3jf1iWt0ySKyK8vFVfdbn3rl+k3SLh9nQRdINyoO1Kt6Tk4dPp6GZipD9jgU9wmw==", + "dev": true, + "requires": { + "cross-fetch": "3.1.5", + "debug": "4.3.3", + "devtools-protocol": "0.0.960912", + "extract-zip": "2.0.1", + "https-proxy-agent": "5.0.0", + "pkg-dir": "4.2.0", + "progress": "2.0.3", + "proxy-from-env": "1.1.0", + "rimraf": "3.0.2", + "tar-fs": "2.1.1", + "unbzip2-stream": "1.4.3", + "ws": "8.5.0" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "devtools-protocol": { + "version": "0.0.960912", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.960912.tgz", + "integrity": "sha512-I3hWmV9rWHbdnUdmMKHF2NuYutIM2kXz2mdXW8ha7TbRlGTVs+PF+PsB5QWvpCek4Fy9B+msiispCfwlhG5Sqg==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "query-selector-shadow-dom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.0.tgz", + "integrity": "sha512-bK0/0cCI+R8ZmOF1QjT7HupDUYCxbf/9TJgAmSXQxZpftXmTAeil9DRoCnTDkWbvOyZzhcMBwKpptWcdkGFIMg==", + "dev": true + }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -8160,6 +11844,12 @@ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -8196,6 +11886,17 @@ "readable-stream": "^2.0.2" } }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", @@ -8225,6 +11926,15 @@ } } }, + "readdir-glob": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz", + "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, "readdirp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", @@ -8328,12 +12038,36 @@ "path-parse": "^1.0.6" } }, + "resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, "resolve-from": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", "dev": true }, + "responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "dev": true, + "requires": { + "lowercase-keys": "^2.0.0" + } + }, + "resq": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/resq/-/resq-1.10.2.tgz", + "integrity": "sha512-HmgVS3j+FLrEDBTDYysPdPVF9/hioDMJ/otOiQDKqk77YfZeeLOj0qi34yObumcud1gBpk+wpBTEg4kMicD++A==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1" + } + }, "restore-cursor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", @@ -8349,6 +12083,12 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" }, + "rgb2hex": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.5.tgz", + "integrity": "sha512-22MOP1Rh7sAo1BZpDG6R5RFYzR2lYEgwq7HEmyW2qcsOqR2lQKmn+O//xV3YG/0rrhMC6KVX2hU+ZXuaw9a5bw==", + "dev": true + }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -8411,6 +12151,15 @@ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, + "serialize-error": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", + "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -8434,6 +12183,21 @@ "sha.js": "~2.4.4" } }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, "shell-quote": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", @@ -8456,6 +12220,17 @@ "rechoir": "^0.6.2" } }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, "signal-exit": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", @@ -8522,6 +12297,38 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "dev": true + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -8588,46 +12395,35 @@ "strip-ansi": "^3.0.0" } }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string.prototype.trimleft": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", - "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", + "string.prototype.padend": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz", + "integrity": "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==", "dev": true, "requires": { + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "string.prototype.trimstart": "^1.0.0" + "es-abstract": "^1.19.1" } }, - "string.prototype.trimright": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", - "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "string.prototype.trimend": "^1.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "strip-ansi": { @@ -8831,6 +12627,12 @@ "is-number": "^7.0.0" } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, "traverse": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", @@ -8883,11 +12685,29 @@ "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", "dev": true }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, + "typescript": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "dev": true + }, + "ua-parser-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.2.tgz", + "integrity": "sha512-00y/AXhx0/SsnI51fTc0rLRmafiGOM4/O+ny10Ps7f+j/b8p/ZY11ytMgznXkOVo4GQ+KwQG5UQLkLGirsACRg==", + "dev": true + }, "uglify-js": { "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", @@ -8921,6 +12741,40 @@ "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==" }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, + "unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + } + } + }, "undeclared-identifiers": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", @@ -9059,6 +12913,22 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "vfile": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", @@ -9094,6 +12964,118 @@ "indexof": "0.0.1" } }, + "webdriver": { + "version": "7.16.14", + "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-7.16.14.tgz", + "integrity": "sha512-wfD3Okv+XJVMzrFVSTkhU381pJn2HlbKyURC7uY4E2QLaalhJLrrqekofBOUsr7WMf9nqoQwiVHQygnyt0afFw==", + "dev": true, + "requires": { + "@types/node": "^17.0.4", + "@wdio/config": "7.16.14", + "@wdio/logger": "7.16.0", + "@wdio/protocols": "7.16.7", + "@wdio/types": "7.16.14", + "@wdio/utils": "7.16.14", + "got": "^11.0.2", + "ky": "^0.28.5", + "lodash.merge": "^4.6.1" + }, + "dependencies": { + "@types/node": { + "version": "17.0.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz", + "integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==", + "dev": true + } + } + }, + "webdriverio": { + "version": "7.16.15", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-7.16.15.tgz", + "integrity": "sha512-f9Hdn0CTX2y1E3kbN/6QLUXo0JZlnnhPkuJbBlSJMV3+/xFj5MBcBszJBT5Frwzcs48YNikimPbR79VLxfX3AA==", + "dev": true, + "requires": { + "@types/aria-query": "^5.0.0", + "@types/node": "^17.0.4", + "@wdio/config": "7.16.14", + "@wdio/logger": "7.16.0", + "@wdio/protocols": "7.16.7", + "@wdio/repl": "7.16.14", + "@wdio/types": "7.16.14", + "@wdio/utils": "7.16.14", + "archiver": "^5.0.0", + "aria-query": "^5.0.0", + "css-shorthand-properties": "^1.1.1", + "css-value": "^0.0.1", + "devtools": "7.16.15", + "devtools-protocol": "^0.0.966116", + "fs-extra": "^10.0.0", + "get-port": "^5.1.1", + "grapheme-splitter": "^1.0.2", + "lodash.clonedeep": "^4.5.0", + "lodash.isobject": "^3.0.2", + "lodash.isplainobject": "^4.0.6", + "lodash.zip": "^4.2.0", + "minimatch": "^3.0.4", + "puppeteer-core": "^13.1.3", + "query-selector-shadow-dom": "^1.0.0", + "resq": "^1.9.1", + "rgb2hex": "0.2.5", + "serialize-error": "^8.0.0", + "webdriver": "7.16.14" + }, + "dependencies": { + "@types/node": { + "version": "17.0.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz", + "integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==", + "dev": true + }, + "fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -9103,6 +13085,19 @@ "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", @@ -9210,6 +13205,13 @@ "mkdirp": "^0.5.1" } }, + "ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "dev": true, + "requires": {} + }, "x-is-string": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", @@ -9340,6 +13342,55 @@ } } } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "zip-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "dev": true, + "requires": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + } + } } } } diff --git a/package.json b/package.json index 79b9171..1cf6974 100644 --- a/package.json +++ b/package.json @@ -6,10 +6,14 @@ "bugs": "https://github.com/gemini-testing/gemini-core/issues", "scripts": { "lint": "eslint .", - "prepublish": "npm run prepare-calibrate-script", - "prepare-calibrate-script": "uglifyjs ./lib/browser/client-scripts/calibrate.js -m > ./lib/browser/client-scripts/calibrate.min.js --support-ie8", + "build-core": "tsc -p tsconfig.json", + "build-client": "tsc -p ./lib/browser/client-scripts/tsconfig.json", + "build": "run-s build-core build-client", + "postbuild": "npm run prepare-calibrate-script", + "prepare-calibrate-script": "uglifyjs ./build/lib/browser/client-scripts/calibrate.js -m > ./build/lib/browser/client-scripts/calibrate.min.js --support-ie8", "test-unit": "mocha test", - "test": "npm run lint && npm run test-unit", + "pretest": "npm run build", + "test": "run-s lint test-unit", "toc": "doctoc README.md" }, "engines": { @@ -30,12 +34,12 @@ "bluebird": "^3.4.6", "browserify": "^13.3.0", "debug": "^2.2.0", - "gemini-configparser": "^1.0.0", - "glob-extra": "^5.0.1", + "gemini-configparser": "github:gemini-testing/configparser#FEI-17917", + "glob-extra": "github:gemini-testing/glob-extra#FEI-24748", "lodash": "^4.17.15", - "looks-same": "^7.3.0", + "looks-same": "github:gemini-testing/looks-same#FEI-17919", "micromatch": "^4.0.2", - "png-img": "^3.3.6", + "png-img": "github:gemini-testing/png-img#FEI-17920", "sizzle": "^2.3.3", "temp": "^0.8.3", "uglify-js": "^2.8.29", @@ -43,6 +47,18 @@ "yallist": "^3.0.3" }, "devDependencies": { + "@tsconfig/recommended": "^1.0.1", + "@types/bluebird": "^3.5.36", + "@types/browserify": "^12.0.37", + "@types/color-diff": "^1.2.1", + "@types/debug": "^4.1.7", + "@types/lodash": "^4.14.178", + "@types/micromatch": "^4.0.2", + "@types/node": "^8.10.66", + "@types/sizzle": "^2.3.3", + "@types/temp": "^0.9.1", + "@types/webdriverio": "^5.0.0", + "@types/yallist": "^4.0.1", "app-module-path": "^1.1.0", "chai": "^3.4.1", "chai-as-promised": "^5.3.0", @@ -50,7 +66,9 @@ "eslint": "^3.1.1", "eslint-config-gemini-testing": "^2.2.0", "mocha": "^7.1.2", + "npm-run-all": "^4.1.5", "proxyquire": "^1.7.3", - "sinon": "^2.2.0" + "sinon": "^2.2.0", + "typescript": "^4.5.5" } } diff --git a/test/lib/browser-agent/index.js b/test/lib/browser-agent/index.js index 6271d04..40afcf7 100644 --- a/test/lib/browser-agent/index.js +++ b/test/lib/browser-agent/index.js @@ -1,8 +1,8 @@ 'use strict'; const Promise = require('bluebird'); -const BrowserAgent = require('lib/browser-agent'); -const BasicPool = require('lib/browser-pool/basic-pool'); +const BrowserAgent = require('build/lib/browser-agent').default; +const BasicPool = require('build/lib/browser-pool/basic-pool').default; describe('browser-agent', () => { const sandbox = sinon.sandbox.create(); diff --git a/test/lib/browser-pool/basic-pool.js b/test/lib/browser-pool/basic-pool.js index 7ab7bd9..ee378e2 100644 --- a/test/lib/browser-pool/basic-pool.js +++ b/test/lib/browser-pool/basic-pool.js @@ -1,7 +1,7 @@ 'use strict'; -const BasicPool = require('lib/browser-pool/basic-pool'); -const CancelledError = require('lib/errors/cancelled-error'); +const BasicPool = require('build/lib/browser-pool/basic-pool').default; +const CancelledError = require('build/lib/errors/cancelled-error'); const stubBrowser = require('./util').stubBrowser; const _ = require('lodash'); const Promise = require('bluebird'); diff --git a/test/lib/browser-pool/caching-pool.js b/test/lib/browser-pool/caching-pool.js index 54c80fd..bbeb2fa 100644 --- a/test/lib/browser-pool/caching-pool.js +++ b/test/lib/browser-pool/caching-pool.js @@ -1,8 +1,8 @@ 'use strict'; const Promise = require('bluebird'); -const Pool = require('lib/browser-pool/caching-pool'); -const {buildCompositeBrowserId} = require('lib/browser-pool/utils'); +const Pool = require('build/lib/browser-pool/caching-pool').default; +const {buildCompositeBrowserId} = require('build/lib/browser-pool/utils'); const stubBrowser = require('./util').stubBrowser; describe('browser-pool/caching-pool', () => { diff --git a/test/lib/browser-pool/index.js b/test/lib/browser-pool/index.js index 60ba793..bb36d76 100644 --- a/test/lib/browser-pool/index.js +++ b/test/lib/browser-pool/index.js @@ -1,9 +1,9 @@ 'use strict'; -const BasicPool = require('lib/browser-pool/basic-pool'); -const LimitedPool = require('lib/browser-pool/limited-pool'); -const PerBrowserLimitedPool = require('lib/browser-pool/per-browser-limited-pool'); -const pool = require('lib/browser-pool'); +const BasicPool = require('build/lib/browser-pool/basic-pool').default; +const LimitedPool = require('build/lib/browser-pool/limited-pool').default; +const PerBrowserLimitedPool = require('build/lib/browser-pool/per-browser-limited-pool').default; +const pool = require('build/lib/browser-pool'); const _ = require('lodash'); describe('browser-pool', () => { diff --git a/test/lib/browser-pool/limited-pool.js b/test/lib/browser-pool/limited-pool.js index 4eee8a7..4eff1a2 100644 --- a/test/lib/browser-pool/limited-pool.js +++ b/test/lib/browser-pool/limited-pool.js @@ -1,8 +1,8 @@ 'use strict'; const Promise = require('bluebird'); -const LimitedPool = require('lib/browser-pool/limited-pool'); -const CancelledError = require('lib/errors/cancelled-error'); +const LimitedPool = require('build/lib/browser-pool/limited-pool').default; +const CancelledError = require('build/lib/errors/cancelled-error'); const stubBrowser = require('./util').stubBrowser; describe('browser-pool/limited-pool', () => { diff --git a/test/lib/browser-pool/per-browser-limited-pool.js b/test/lib/browser-pool/per-browser-limited-pool.js index 1404aa2..d779edb 100644 --- a/test/lib/browser-pool/per-browser-limited-pool.js +++ b/test/lib/browser-pool/per-browser-limited-pool.js @@ -1,9 +1,9 @@ 'use strict'; const _ = require('lodash'); -const PerBrowserLimitedPool = require('lib/browser-pool/per-browser-limited-pool'); -const LimitedPool = require('lib/browser-pool/limited-pool'); -const BasicPool = require('lib/browser-pool/basic-pool'); +const PerBrowserLimitedPool = require('build/lib/browser-pool/per-browser-limited-pool').default; +const LimitedPool = require('build/lib/browser-pool/limited-pool').default; +const BasicPool = require('build/lib/browser-pool/basic-pool').default; const stubBrowser = require('./util').stubBrowser; describe('browser-pool/per-browser-limited-pool', () => { diff --git a/test/lib/browser-pool/utils.js b/test/lib/browser-pool/utils.js index 127a3db..0025722 100644 --- a/test/lib/browser-pool/utils.js +++ b/test/lib/browser-pool/utils.js @@ -1,6 +1,6 @@ 'use strict'; -const utils = require('lib/browser-pool/utils'); +const utils = require('build/lib/browser-pool/utils'); describe('browser-pool/utils', () => { describe('buildCompositeBrowserId', () => { diff --git a/test/lib/browser/camera/index.js b/test/lib/browser/camera/index.js index b3c2a0e..c3add92 100644 --- a/test/lib/browser/camera/index.js +++ b/test/lib/browser/camera/index.js @@ -1,8 +1,8 @@ 'use strict'; -const Camera = require('lib/browser/camera'); -const Image = require('lib/image'); -const utils = require('lib/browser/camera/utils'); +const Camera = require('build/lib/browser/camera').default; +const Image = require('build/lib/image').default; +const utils = require('build/lib/browser/camera/utils'); describe('browser/camera', () => { const sandbox = sinon.sandbox.create(); diff --git a/test/lib/browser/camera/utils.js b/test/lib/browser/camera/utils.js index c41828d..9f0ce93 100644 --- a/test/lib/browser/camera/utils.js +++ b/test/lib/browser/camera/utils.js @@ -1,8 +1,8 @@ 'use strict'; const _ = require('lodash'); -const Image = require('lib/image'); -const utils = require('lib/browser/camera/utils'); +const Image = require('build/lib/image').default; +const utils = require('build/lib/browser/camera/utils'); describe('camera utils.isFullPage', () => { const sandbox = sinon.sandbox.create(); diff --git a/test/lib/browser/client-scripts/rect.js b/test/lib/browser/client-scripts/rect.js index ba764e4..876cbf5 100644 --- a/test/lib/browser/client-scripts/rect.js +++ b/test/lib/browser/client-scripts/rect.js @@ -1,6 +1,6 @@ 'use strict'; -const Rect = require('lib/browser/client-scripts/rect').Rect; +const Rect = require('build/lib/browser/client-scripts/rect').default; describe('Rect', () => { const rect = new Rect({ diff --git a/test/lib/calibrator/index.js b/test/lib/calibrator/index.js index 20245ab..7729b87 100644 --- a/test/lib/calibrator/index.js +++ b/test/lib/calibrator/index.js @@ -3,9 +3,9 @@ const path = require('path'); const fs = require('fs'); const Promise = require('bluebird'); -const Image = require('lib/image'); -const Calibrator = require('lib/calibrator'); -const {CoreError} = require('lib/errors'); +const Image = require('build/lib/image').default; +const Calibrator = require('build/lib/calibrator').default; +const {CoreError} = require('build/lib/errors'); describe('calibrator', () => { let browser, calibrator; diff --git a/test/lib/client-bridge/client-bridge.js b/test/lib/client-bridge/client-bridge.js index 291029a..a4d1298 100644 --- a/test/lib/client-bridge/client-bridge.js +++ b/test/lib/client-bridge/client-bridge.js @@ -1,7 +1,7 @@ 'use strict'; const Promise = require('bluebird'); -const ClientBridge = require('lib/client-bridge/client-bridge'); -const ClientBridgeError = require('lib/errors/client-bridge-error'); +const ClientBridge = require('build/lib/client-bridge/client-bridge').default; +const ClientBridgeError = require('build/lib/errors/client-bridge-error'); const CALL = '__geminiCore.example(1, "two")'; diff --git a/test/lib/client-bridge/index.js b/test/lib/client-bridge/index.js index 8e1d947..8fa281f 100644 --- a/test/lib/client-bridge/index.js +++ b/test/lib/client-bridge/index.js @@ -1,7 +1,7 @@ 'use strict'; const proxyquire = require('proxyquire'); -const ClientBridge = require('lib/client-bridge/client-bridge'); +const ClientBridge = require('build/lib/client-bridge/client-bridge').default; describe('clientBridge', () => { const sandbox = sinon.sandbox.create(); @@ -17,7 +17,7 @@ describe('clientBridge', () => { browserify = sandbox.stub().returns(script); - clientBridge = proxyquire('lib/client-bridge', {browserify}); + clientBridge = proxyquire('build/lib/client-bridge', {browserify}); sandbox.stub(ClientBridge, 'create'); }); @@ -43,13 +43,13 @@ describe('clientBridge', () => { it('should transform client scripts', () => { return clientBridge.build() .then(() => { - assert.calledWith(script.transform, { + assert.calledWith(script.transform, 'uglifyify', { 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'); + }); }); }); @@ -61,7 +61,7 @@ describe('clientBridge', () => { it('should transform client scripts using native library', () => { return clientBridge.build(null, {calibration: {needsCompatLib: false}}) .then(() => { - assert.calledWith(script.transform, sinon.match({ + assert.calledWith(script.transform, 'aliasify', sinon.match({ aliases: { './lib': {relative: './lib.native.js'} }, @@ -73,7 +73,7 @@ describe('clientBridge', () => { it('should transform client scripts using compat library', () => { return clientBridge.build(null, {calibration: {needsCompatLib: true}}) .then(() => { - assert.calledWith(script.transform, sinon.match({ + assert.calledWith(script.transform, 'aliasify', sinon.match({ aliases: { './lib': {relative: './lib.compat.js'} }, @@ -85,7 +85,7 @@ describe('clientBridge', () => { it('should transform client scripts NOT for deprecated mode', () => { return clientBridge.build(null, {supportDeprecated: false}) .then(() => { - assert.calledWith(script.transform, sinon.match({ + assert.calledWith(script.transform, 'aliasify', sinon.match({ aliases: { './ignore-areas': {relative: './ignore-areas.js'} }, @@ -97,7 +97,7 @@ describe('clientBridge', () => { it('should transform client scripts for deprecated mode', () => { return clientBridge.build(null, {supportDeprecated: true}) .then(() => { - assert.calledWith(script.transform, sinon.match({ + assert.calledWith(script.transform, 'aliasify', sinon.match({ aliases: { './ignore-areas': {relative: './ignore-areas.deprecated.js'} }, diff --git a/test/lib/config/options.js b/test/lib/config/options.js index 338f2ab..8130be4 100644 --- a/test/lib/config/options.js +++ b/test/lib/config/options.js @@ -5,7 +5,7 @@ const _ = require('lodash'); const MissingOptionError = require('gemini-configparser').MissingOptionError; -const configOptions = require('lib/config/options'); +const configOptions = require('build/lib/config/options').default; const section = configparser.section; const option = configparser.option; diff --git a/test/lib/coverage/coverage-level.js b/test/lib/coverage/coverage-level.js index b25fa19..c7a0a1f 100644 --- a/test/lib/coverage/coverage-level.js +++ b/test/lib/coverage/coverage-level.js @@ -1,6 +1,6 @@ 'use strict'; -const level = require('lib/coverage/coverage-level'); +const level = require('build/lib/coverage/coverage-level'); describe('coverage level', () => { describe('merge', () => { diff --git a/test/lib/events/async-emitter/index.js b/test/lib/events/async-emitter/index.js index 6cdc064..d616736 100644 --- a/test/lib/events/async-emitter/index.js +++ b/test/lib/events/async-emitter/index.js @@ -1,6 +1,6 @@ 'use strict'; -const AsyncEmitter = require('lib/events/async-emitter'); +const AsyncEmitter = require('build/lib/events/async-emitter').default; const Promise = require('bluebird'); describe('async-emitter', () => { diff --git a/test/lib/events/utils.js b/test/lib/events/utils.js index 0c7b4a5..9c4fc0b 100644 --- a/test/lib/events/utils.js +++ b/test/lib/events/utils.js @@ -2,8 +2,8 @@ const Promise = require('bluebird'); -const AsyncEmitter = require('lib/events/async-emitter'); -const utils = require('lib/events/utils'); +const AsyncEmitter = require('build/lib/events/async-emitter').default; +const utils = require('build/lib/events/utils'); describe('events/utils', () => { describe('passthroughEvent', () => { diff --git a/test/lib/image/index.js b/test/lib/image/index.js index e7ae5e0..73e1c8f 100644 --- a/test/lib/image/index.js +++ b/test/lib/image/index.js @@ -1,14 +1,14 @@ 'use strict'; -const PngImg = require('png-img'); +const PngImg = require('png-img').default; const utils = require('png-img/utils'); const proxyquire = require('proxyquire'); const looksSameStub = sinon.stub(); -const Image = proxyquire('lib/image', { +const Image = proxyquire('build/lib/image', { 'looks-same': looksSameStub -}); -const SafeRect = require('lib/image/safe-rect'); +}).default; +const SafeRect = require('build/lib/image/safe-rect').default; describe('Image', () => { const sandbox = sinon.sandbox.create(); diff --git a/test/lib/image/safe-rect.js b/test/lib/image/safe-rect.js index 71211e3..90790df 100644 --- a/test/lib/image/safe-rect.js +++ b/test/lib/image/safe-rect.js @@ -1,6 +1,6 @@ 'use strict'; -const SafeRect = require('lib/image/safe-rect'); +const SafeRect = require('build/lib/image/safe-rect').default; describe('SafeRect', () => { describe('left', () => { diff --git a/test/lib/promise-utils/index.js b/test/lib/promise-utils/index.js index 1165c61..1131230 100644 --- a/test/lib/promise-utils/index.js +++ b/test/lib/promise-utils/index.js @@ -1,7 +1,7 @@ 'use strict'; const Promise = require('bluebird'); -const utils = require('lib/promise-utils'); +const utils = require('build/lib/promise-utils'); describe('promise-utils', () => { describe('waitForResults', () => { diff --git a/test/lib/screen-shooter/index.js b/test/lib/screen-shooter/index.js index 171c55d..1512722 100644 --- a/test/lib/screen-shooter/index.js +++ b/test/lib/screen-shooter/index.js @@ -1,8 +1,8 @@ 'use strict'; -const Image = require('lib/image'); -const ScreenShooter = require('lib/screen-shooter'); -const Viewport = require('lib/screen-shooter/viewport'); +const Image = require('build/lib/image').default; +const ScreenShooter = require('build/lib/screen-shooter').default; +const Viewport = require('build/lib/screen-shooter/viewport').default; describe('screen-shooter', () => { const sandbox = sinon.sandbox.create(); diff --git a/test/lib/screen-shooter/viewport/coord-validator.js b/test/lib/screen-shooter/viewport/coord-validator.js index 79e505a..56d8e6c 100644 --- a/test/lib/screen-shooter/viewport/coord-validator.js +++ b/test/lib/screen-shooter/viewport/coord-validator.js @@ -2,9 +2,9 @@ const _ = require('lodash'); -const CoordValidator = require('lib/screen-shooter/viewport/coord-validator'); -const HeightViewportError = require('lib/screen-shooter/viewport/coord-validator/errors/height-viewport-error'); -const OffsetViewportError = require('lib/screen-shooter/viewport/coord-validator/errors/offset-viewport-error'); +const CoordValidator = require('build/lib/screen-shooter/viewport/coord-validator').default; +const HeightViewportError = require('build/lib/screen-shooter/viewport/coord-validator/errors/height-viewport-error'); +const OffsetViewportError = require('build/lib/screen-shooter/viewport/coord-validator/errors/offset-viewport-error'); describe('CoordValidator', () => { let coordValidator; diff --git a/test/lib/screen-shooter/viewport/index.js b/test/lib/screen-shooter/viewport/index.js index 340ae96..55a9b20 100644 --- a/test/lib/screen-shooter/viewport/index.js +++ b/test/lib/screen-shooter/viewport/index.js @@ -3,9 +3,9 @@ const _ = require('lodash'); const Promise = require('bluebird'); -const Image = require('lib/image'); -const Viewport = require('lib/screen-shooter/viewport'); -const CoordValidator = require('lib/screen-shooter/viewport/coord-validator'); +const Image = require('build/lib/image').default; +const Viewport = require('build/lib/screen-shooter/viewport').default; +const CoordValidator = require('build/lib/screen-shooter/viewport/coord-validator').default; describe('Viewport', () => { const sandbox = sinon.sandbox.create(); diff --git a/test/lib/sets-builder/index.js b/test/lib/sets-builder/index.js index a5d4050..585a09a 100644 --- a/test/lib/sets-builder/index.js +++ b/test/lib/sets-builder/index.js @@ -3,9 +3,9 @@ const Promise = require('bluebird'); const globExtra = require('glob-extra'); const fs = require('fs'); -const SetBuilder = require('lib/sets-builder'); -const SetCollection = require('lib/sets-builder/set-collection'); -const TestSet = require('lib/sets-builder/test-set'); +const SetBuilder = require('build/lib/sets-builder').default; +const SetCollection = require('build/lib/sets-builder/set-collection').default; +const TestSet = require('build/lib/sets-builder/test-set').default; describe('sets-builder', () => { const sandbox = sinon.sandbox.create(); diff --git a/test/lib/sets-builder/set-collection.js b/test/lib/sets-builder/set-collection.js index 6cea891..c881cf0 100644 --- a/test/lib/sets-builder/set-collection.js +++ b/test/lib/sets-builder/set-collection.js @@ -1,7 +1,7 @@ 'use strict'; -const SetCollection = require('lib/sets-builder/set-collection'); -const TestSet = require('lib/sets-builder/test-set'); +const SetCollection = require('build/lib/sets-builder/set-collection').default; +const TestSet = require('build/lib/sets-builder/test-set').default; describe('set-collection', () => { const sandbox = sinon.sandbox.create(); diff --git a/test/lib/sets-builder/test-set.js b/test/lib/sets-builder/test-set.js index 62faac5..cb9e67e 100644 --- a/test/lib/sets-builder/test-set.js +++ b/test/lib/sets-builder/test-set.js @@ -11,9 +11,9 @@ describe('TestSet', () => { globExtraStub = { expandPaths: sinon.stub() }; - TestSet = proxyquire('lib/sets-builder/test-set', { + TestSet = proxyquire('build/lib/sets-builder/test-set', { 'glob-extra': globExtraStub - }); + }).default; }); afterEach(() => sandbox.restore()); diff --git a/test/lib/temp/index.js b/test/lib/temp/index.js index a286aac..e718053 100644 --- a/test/lib/temp/index.js +++ b/test/lib/temp/index.js @@ -1,7 +1,7 @@ 'use strict'; const nodeTemp = require('temp'); -const {requireWithNoCache} = require('lib/utils'); +const {requireWithNoCache} = require('build/lib/utils'); describe('temp', () => { const sandbox = sinon.sandbox.create(); @@ -9,7 +9,7 @@ describe('temp', () => { beforeEach(() => { sandbox.stub(nodeTemp); - temp = requireWithNoCache(require.resolve('lib/temp')); + temp = requireWithNoCache(require.resolve('build/lib/temp')); }); afterEach(() => sandbox.restore()); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1d28ac3 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "@tsconfig/recommended/tsconfig.json", + "include": ["**/*"], + "exclude": ["lib/browser/client-scripts", "test", "build"], + "compilerOptions": { + "outDir": "build", + "types": ["node"], + "allowJs": true, + "checkJs": false, + "noImplicitReturns": true, + "noUnusedLocals": true, + "noUnusedParameters": true + } + }