diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2b57b7c5d..4309b9950 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,8 +26,36 @@ jobs: directory: ./packages/upscalerjs/coverage verbose: true - integration-browser: - name: 'Tests: Integration / Browser' + integration-browser-browserstack: + name: 'Tests: Integration / Browser / Browserstack' + runs-on: ubuntu-latest + steps: + - name: 'BrowserStack Env Setup' # Invokes the setup-env action + uses: browserstack/github-actions/setup-env@master + with: + username: ${{ secrets.BROWSERSTACK_USERNAME }} + access-key: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} + + - name: 'Checkout repository' + uses: actions/checkout@v2 + + - uses: actions/cache@v2 + with: + path: '**/node_modules' + key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }} + + - name: 'Installing' + env: + NODE_OPTIONS: --max_old_space_size=8192 + run: yarn + + - name: 'Integration Tests' + run: yarn test:integration:browserstack --ci + env: + NODE_OPTIONS: --max_old_space_size=8192 + + integration-browser-local: + name: 'Tests: Integration / Browser / Local' runs-on: ubuntu-latest steps: - name: 'BrowserStack Env Setup' # Invokes the setup-env action @@ -55,8 +83,8 @@ jobs: NODE_OPTIONS: --max_old_space_size=8192 - integration-node: - name: 'Tests: Integration / Node' + integration-node-local: + name: 'Tests: Integration / Node / Local' runs-on: ubuntu-latest steps: - name: 'Checkout repository' diff --git a/package.json b/package.json index a9eaa1f53..a6d69aa43 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "scaffold:platform": "yarn lerna run scaffold:platform -- --", "test": "yarn test:unit", "test:unit": "yarn scaffold:platform 'browser' && jest --config packages/upscalerjs/jestconfig.json", + "test:integration:browserstack": "ts-node scripts/test.ts --platform browser --kind browserstack", "test:integration:browser": "ts-node scripts/test.ts --platform browser", "test:integration:node": "ts-node scripts/test.ts --platform node", "test:startTestServer": "ts-node test/lib/startServer.ts" @@ -68,6 +69,7 @@ "@types/jest": "^26.0.7", "@types/jsdom": "^16.2.14", "@types/pngjs": "^6.0.1", + "@types/puppeteer": "^5.4.4", "@types/rimraf": "^3.0.2", "@types/serve-handler": "^6.1.1", "@types/yargs": "^17.0.5", @@ -86,6 +88,7 @@ "pixelmatch": "^5.2.1", "pngjs": "^6.0.0", "prettier": "^2.0.5", + "puppeteer": "^13.1.3", "rimraf": "^3.0.2", "rollup": "^2.66.1", "rollup-plugin-commonjs": "^10.1.0", diff --git a/scripts/test.ts b/scripts/test.ts index ac348b87a..457411a9c 100644 --- a/scripts/test.ts +++ b/scripts/test.ts @@ -51,16 +51,30 @@ const getPlatform = (argPlatform: string) => { throw new Error(`Unsupported platform provided: ${platform}. You must pass either 'browser' or 'node'.`) } +const isValidRunner = (runner?: string): runner is undefined | 'local' | 'browserstack' => { + return runner === undefined ? true : ['local', 'browserstack'].includes(runner); +} + +const getRunner = (runner?: string): 'local' | 'browserstack' => { + if (isValidRunner(runner)) { + return runner === undefined ? 'local' : runner; + + } + throw new Error(`Unsupported runner provided: ${runner}. You must pass either 'local' or 'browserstack'.`) +} + (async function main() { const argv = await yargs(process.argv.slice(2)).options({ watch: { type: 'boolean' }, platform: { type: 'string', demandOption: true }, skipBuild: { type: 'boolean' }, + runner: { type: 'string' } }).argv; let bsLocal: undefined | browserstack.Local; const platform = getPlatform(argv.platform); - if (platform === 'browser') { + const runner = getRunner(argv.runner); + if (runner === 'browserstack') { bsLocal = await startBrowserstack(); process.on('exit', async () => { if (bsLocal !== undefined && bsLocal.isRunning()) { @@ -79,7 +93,7 @@ const getPlatform = (argPlatform: string) => { 'yarn', 'jest', '--config', - `test/jestconfig.${platform}.js`, + `test/jestconfig.${platform}.${runner}.js`, '--detectOpenHandles', argv.watch ? '--watch' : undefined, ...argv._, diff --git a/test/integration/browser/build.ts b/test/integration/browser/build.ts index 832aaee2e..71bcd7c71 100644 --- a/test/integration/browser/build.ts +++ b/test/integration/browser/build.ts @@ -1,64 +1,23 @@ /**** * Tests that different build outputs all function correctly */ -import * as browserstack from 'browserstack-local'; -import * as webdriver from 'selenium-webdriver'; import { checkImage } from '../../lib/utils/checkImage'; import { prepareScriptBundleForUMD, DIST as SCRIPT_DIST } from '../../lib/umd/prepare'; import { startServer } from '../../lib/shared/server'; import { prepareScriptBundleForESM, bundleWebpack, DIST as WEBPACK_DIST } from '../../lib/esm-webpack/prepare'; +import puppeteer from 'puppeteer'; -const DEFAULT_CAPABILITIES = { - 'build': process.env.BROWSERSTACK_BUILD_NAME, - 'project': process.env.BROWSERSTACK_PROJECT_NAME, - 'browserstack.local': true, - os: 'windows', - os_version: '11', - browserName: 'chrome', - browser_version: 'latest' -} - -const TRACK_TIME = false; -const username = process.env.BROWSERSTACK_USERNAME; -const accessKey = process.env.BROWSERSTACK_ACCESS_KEY; -const serverURL = `http://${username}:${accessKey}@hub-cloud.browserstack.com/wd/hub`; - -const JEST_TIMEOUT = 60 * 1000; -jest.setTimeout(JEST_TIMEOUT * 1); // 60 seconds timeout +const JEST_TIMEOUT_IN_SECONDS = 60; +jest.setTimeout(JEST_TIMEOUT_IN_SECONDS * 1000); jest.retryTimes(1); -let server; -let driver; describe('Build Integration Tests', () => { + let server; + let browser; + let page; const PORT = 8099; - beforeAll(async function beforeAll() { - const start = new Date().getTime(); - - driver = new webdriver.Builder() - .usingServer(serverURL) - .withCapabilities(DEFAULT_CAPABILITIES) - .build(); - - const end = new Date().getTime(); - if (TRACK_TIME) { - console.log(`Completed pre-test scaffolding in ${Math.round((end - start) / 1000)} seconds`); - } - }, 20000); - - afterAll(async function buildAfterAll() { - const start = new Date().getTime(); - - await Promise.all([ - driver.quit(), - ]); - const end = new Date().getTime(); - if (TRACK_TIME) { - console.log(`Completed post-test clean up in ${Math.round((end - start) / 1000)} seconds`); - } - }, 10000); - afterEach(async function afterEach() { const stopServer = () => new Promise((resolve) => { if (server) { @@ -69,14 +28,23 @@ describe('Build Integration Tests', () => { }); await Promise.all([ stopServer(), + browser ? browser.close() : undefined, ]); + browser = undefined; + page = undefined; }); + const startBrowser = async () => { + browser = await puppeteer.launch(); + page = await browser.newPage(); + await page.goto(`http://localhost:${PORT}`); + } + it("upscales using a UMD build via a script tag", async () => { await prepareScriptBundleForUMD(); server = await startServer(PORT, SCRIPT_DIST); - await driver.get(`http://localhost:${PORT}`); - const result = await driver.executeScript(() => { + await startBrowser(); + const result = await page.evaluate(() => { const Upscaler = window['Upscaler']; const upscaler = new Upscaler({ model: '/pixelator/pixelator.json', @@ -91,9 +59,9 @@ describe('Build Integration Tests', () => { await prepareScriptBundleForESM(); await bundleWebpack(); server = await startServer(PORT, WEBPACK_DIST); - await driver.get(`http://localhost:${PORT}`); - await driver.wait(() => driver.getTitle().then(title => title.endsWith('| Loaded'), 3000)); - const result = await driver.executeScript(() => { + await startBrowser(); + await page.waitForFunction('document.title.endsWith("| Loaded")'); + const result = await page.evaluate(() => { const Upscaler = window['Upscaler']; const upscaler = new Upscaler({ model: '/pixelator/pixelator.json', diff --git a/test/integration/browser/image.ts b/test/integration/browser/image.ts index b2acafc60..67ce94dd4 100644 --- a/test/integration/browser/image.ts +++ b/test/integration/browser/image.ts @@ -3,54 +3,28 @@ */ import * as fs from 'fs'; import * as path from 'path'; -import * as browserstack from 'browserstack-local'; -import * as webdriver from 'selenium-webdriver'; import { checkImage } from '../../lib/utils/checkImage'; import { bundle, DIST } from '../../lib/esm-esbuild/prepare'; import { startServer } from '../../lib/shared/server'; - -const DEFAULT_CAPABILITIES = { - 'build': process.env.BROWSERSTACK_BUILD_NAME, - 'project': process.env.BROWSERSTACK_PROJECT_NAME, - 'browserstack.local': true, - // 'browserstack.localIdentifier': process.env.BROWSERSTACK_LOCAL_IDENTIFIER, - os: 'windows', - os_version: '11', - browserName: 'chrome', - browser_version: 'latest' -} +import puppeteer from 'puppeteer'; const TRACK_TIME = false; -const username = process.env.BROWSERSTACK_USERNAME; -const accessKey = process.env.BROWSERSTACK_ACCESS_KEY; -const serverURL = `http://${username}:${accessKey}@hub-cloud.browserstack.com/wd/hub`; - const JEST_TIMEOUT = 60 * 1000; jest.setTimeout(JEST_TIMEOUT); // 60 seconds timeout jest.retryTimes(1); describe('Image Format Integration Tests', () => { let server; - let driver; + let browser; + let page; const PORT = 8099; beforeAll(async function beforeAll() { const start = new Date().getTime(); - const startServerWrapper = async () => { - await bundle(); - server = await startServer(PORT, DIST); - }; - - await Promise.all([ - startServerWrapper(), - ]); - - driver = new webdriver.Builder() - .usingServer(serverURL) - .withCapabilities(DEFAULT_CAPABILITIES) - .build(); + await bundle(); + server = await startServer(PORT, DIST); const end = new Date().getTime(); if (TRACK_TIME) { @@ -71,7 +45,6 @@ describe('Image Format Integration Tests', () => { }); await Promise.all([ stopServer(), - driver.quit(), ]); const end = new Date().getTime(); if (TRACK_TIME) { @@ -80,11 +53,20 @@ describe('Image Format Integration Tests', () => { }, 10000); beforeEach(async function beforeEach() { - await driver.get(`http://localhost:${PORT}`); + browser = await puppeteer.launch(); + page = await browser.newPage(); + await page.goto(`http://localhost:${PORT}`); + await page.waitForFunction('document.title.endsWith("| Loaded")'); + }); + + afterEach(async function afterEach() { + await browser.close(); + browser = undefined; + page = undefined; }); it("upscales an imported local image path", async () => { - const result = await driver.executeScript(() => { + const result = await page.evaluate(() => { const upscaler = new window['Upscaler']({ model: '/pixelator/pixelator.json', scale: 4, @@ -95,7 +77,7 @@ describe('Image Format Integration Tests', () => { }); it("upscales an HTML Image", async () => { - const upscaledSrc = await driver.executeScript(() => new Promise(resolve => { + const upscaledSrc = await page.evaluate(() => new Promise(resolve => { const upscaler = new window['Upscaler']({ model: '/pixelator/pixelator.json', scale: 4, @@ -109,68 +91,68 @@ describe('Image Format Integration Tests', () => { checkImage(upscaledSrc, "upscaled-4x-pixelator.png", 'diff.png'); }); - it("upscales an HTML Image from the page", async () => { - const upscaledSrc = await driver.executeScript(() => new Promise(resolve => { - const upscaler = new window['Upscaler']({ - model: '/pixelator/pixelator.json', - scale: 4, - }); - const img = document.createElement('img'); - img.id = 'img'; - img.src = window['flower']; - document.body.append(img); - img.onload = () => { - upscaler.upscale(document.getElementById('img')).then(resolve); - } - })); - checkImage(upscaledSrc, "upscaled-4x-pixelator.png", 'diff.png'); - }); + it("upscales an HTML Image from the page", async () => { + const upscaledSrc = await page.evaluate(() => new Promise(resolve => { + const upscaler = new window['Upscaler']({ + model: '/pixelator/pixelator.json', + scale: 4, + }); + const img = document.createElement('img'); + img.id = 'img'; + img.src = window['flower']; + document.body.append(img); + img.onload = () => { + upscaler.upscale(document.getElementById('img')).then(resolve); + } + })); + checkImage(upscaledSrc, "upscaled-4x-pixelator.png", 'diff.png'); + }); - it("upscales a tensor", async () => { - const upscaledSrc = await driver.executeScript(() => new Promise(resolve => { - const upscaler = new window['Upscaler']({ - model: '/pixelator/pixelator.json', - scale: 4, - }); - const img = new Image(); - img.src = window['flower']; - img.crossOrigin = 'anonymous'; - img.onload = function () { - const tensor = window['tf'].browser.fromPixels(img); - upscaler.upscale(tensor).then(resolve); - } - })); - checkImage(upscaledSrc, "upscaled-4x-pixelator.png", 'diff.png'); - }); + it("upscales a tensor", async () => { + const upscaledSrc = await page.evaluate(() => new Promise(resolve => { + const upscaler = new window['Upscaler']({ + model: '/pixelator/pixelator.json', + scale: 4, + }); + const img = new Image(); + img.src = window['flower']; + img.crossOrigin = 'anonymous'; + img.onload = function () { + const tensor = window['tf'].browser.fromPixels(img); + upscaler.upscale(tensor).then(resolve); + } + })); + checkImage(upscaledSrc, "upscaled-4x-pixelator.png", 'diff.png'); + }); - it("upscales a rank 4 tensor", async () => { - const upscaledSrc = await driver.executeScript(() => new Promise(resolve => { - const upscaler = new window['Upscaler']({ - model: '/pixelator/pixelator.json', - scale: 4, - }); - const img = new Image(); - img.src = window['flower']; - img.crossOrigin = 'anonymous'; - img.onload = function () { - const tensor = window['tf'].browser.fromPixels(img).expandDims(0); - upscaler.upscale(tensor).then(resolve); - } - })); - checkImage(upscaledSrc, "upscaled-4x-pixelator.png", 'diff.png'); - }); + it("upscales a rank 4 tensor", async () => { + const upscaledSrc = await page.evaluate(() => new Promise(resolve => { + const upscaler = new window['Upscaler']({ + model: '/pixelator/pixelator.json', + scale: 4, + }); + const img = new Image(); + img.src = window['flower']; + img.crossOrigin = 'anonymous'; + img.onload = function () { + const tensor = window['tf'].browser.fromPixels(img).expandDims(0); + upscaler.upscale(tensor).then(resolve); + } + })); + checkImage(upscaledSrc, "upscaled-4x-pixelator.png", 'diff.png'); + }); - it("upscales a base64 png path", async () => { - const data = fs.readFileSync(path.resolve(__dirname, "../../__fixtures__", 'flower-small.png')).toString('base64'); - const originalImage = `data:image/png;base64,${data}`; - const upscaledSrc = await driver.executeScript(src => { - const upscaler = new window['Upscaler']({ - model: '/pixelator/pixelator.json', - scale: 4, - }); - return upscaler.upscale(src); - }, originalImage); - checkImage(upscaledSrc, "upscaled-4x-pixelator.png", 'diff.png'); - }); + it("upscales a base64 png path", async () => { + const data = fs.readFileSync(path.resolve(__dirname, "../../__fixtures__", 'flower-small.png')).toString('base64'); + const originalImage = `data:image/png;base64,${data}`; + const upscaledSrc = await page.evaluate(src => { + const upscaler = new window['Upscaler']({ + model: '/pixelator/pixelator.json', + scale: 4, + }); + return upscaler.upscale(src); + }, originalImage); + checkImage(upscaledSrc, "upscaled-4x-pixelator.png", 'diff.png'); + }); }); diff --git a/test/integration/browser/model.ts b/test/integration/browser/model.ts index 069e8ae77..cadeaae8b 100644 --- a/test/integration/browser/model.ts +++ b/test/integration/browser/model.ts @@ -1,25 +1,12 @@ /**** * Tests that different approaches to loading a model all load correctly */ -import * as webdriver from 'selenium-webdriver'; import { checkImage } from '../../lib/utils/checkImage'; import { bundle, DIST } from '../../lib/esm-esbuild/prepare'; import { startServer } from '../../lib/shared/server'; - -const DEFAULT_CAPABILITIES = { - 'build': process.env.BROWSERSTACK_BUILD_NAME, - 'project': process.env.BROWSERSTACK_PROJECT_NAME, - 'browserstack.local': true, - os: 'windows', - os_version: '11', - browserName: 'chrome', - browser_version: 'latest' -} +import puppeteer from 'puppeteer'; const TRACK_TIME = false; -const username = process.env.BROWSERSTACK_USERNAME; -const accessKey = process.env.BROWSERSTACK_ACCESS_KEY; -const serverURL = `http://${username}:${accessKey}@hub-cloud.browserstack.com/wd/hub`; const JEST_TIMEOUT = 60 * 1000; jest.setTimeout(JEST_TIMEOUT); // 60 seconds timeout @@ -27,24 +14,16 @@ jest.retryTimes(1); describe('Model Loading Integration Tests', () => { let server; - let driver; + let browser; + let page; const PORT = 8099; beforeAll(async function beforeAll() { const start = new Date().getTime(); - const startServerWrapper = async () => { - await bundle(); - server = await startServer(PORT, DIST); - }; - - await startServerWrapper(); - - driver = new webdriver.Builder() - .usingServer(serverURL) - .withCapabilities(DEFAULT_CAPABILITIES) - .build(); + await bundle(); + server = await startServer(PORT, DIST); const end = new Date().getTime(); if (TRACK_TIME) { @@ -64,7 +43,6 @@ describe('Model Loading Integration Tests', () => { }); await Promise.all([ stopServer(), - driver.quit(), ]); const end = new Date().getTime(); if (TRACK_TIME) { @@ -73,11 +51,20 @@ describe('Model Loading Integration Tests', () => { }, 10000); beforeEach(async function beforeEach() { - await driver.get(`http://localhost:${PORT}`); - }, 10000); + browser = await puppeteer.launch(); + page = await browser.newPage(); + await page.goto(`http://localhost:${PORT}`); + await page.waitForFunction('document.title.endsWith("| Loaded")'); + }); + + afterEach(async function afterEach() { + await browser.close(); + browser = undefined; + page = undefined; + }); it("loads a locally exposed model via implied HTTP", async () => { - const result = await driver.executeScript(() => { + const result = await page.evaluate(() => { const upscaler = new window['Upscaler']({ model: '/pixelator/pixelator.json', scale: 4, @@ -88,7 +75,7 @@ describe('Model Loading Integration Tests', () => { }); it("loads a locally exposed model via absolute HTTP", async () => { - const result = await driver.executeScript(() => { + const result = await page.evaluate(() => { const upscaler = new window['Upscaler']({ model: `${window.location.origin}/pixelator/pixelator.json`, scale: 4, @@ -99,7 +86,7 @@ describe('Model Loading Integration Tests', () => { }); it("can load model definitions in the browser", async () => { - const result = await driver.executeScript(() => { + const result = await page.evaluate(() => { const upscaler = new window['Upscaler'](); return upscaler.getModelDefinitions(); }); diff --git a/test/integration/browser/browser.ts b/test/integration/browserstack/browser.ts similarity index 100% rename from test/integration/browser/browser.ts rename to test/integration/browserstack/browser.ts diff --git a/test/integration/browser/config/browserOptions.json b/test/integration/browserstack/config/browserOptions.json similarity index 100% rename from test/integration/browser/config/browserOptions.json rename to test/integration/browserstack/config/browserOptions.json diff --git a/test/jestconfig.browser.browserstack.js b/test/jestconfig.browser.browserstack.js new file mode 100644 index 000000000..344582f10 --- /dev/null +++ b/test/jestconfig.browser.browserstack.js @@ -0,0 +1,7 @@ +const jestconfig = require('./jestconfig.json'); +module.exports = { + ...jestconfig, + roots: [ + "/integration/browserstack", + ], +}; diff --git a/test/jestconfig.browser.js b/test/jestconfig.browser.local.js similarity index 100% rename from test/jestconfig.browser.js rename to test/jestconfig.browser.local.js diff --git a/test/jestconfig.node.js b/test/jestconfig.node.local.js similarity index 100% rename from test/jestconfig.node.js rename to test/jestconfig.node.local.js diff --git a/yarn.lock b/yarn.lock index 05a0698fc..f56a2633a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3408,6 +3408,13 @@ resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.0.2.tgz" integrity sha512-IkVfat549ggtkZUthUzEX49562eGikhSYeVGX97SkMFn+sTZrgRewXjQ4tPKFPCykZHkX1Zfd9OoELGqKU2jJA== +"@types/puppeteer@^5.4.4": + version "5.4.4" + resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-5.4.4.tgz#e92abeccc4f46207c3e1b38934a1246be080ccd0" + integrity sha512-3Nau+qi69CN55VwZb0ATtdUAlYlqOOQ3OfQfq0Hqgc4JMFXiQT/XInlwQ9g6LbicDslE6loIFsXFklGh5XmI6Q== + dependencies: + "@types/node" "*" + "@types/q@^1.5.1": version "1.5.5" resolved "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz" @@ -3524,6 +3531,13 @@ dependencies: "@types/yargs-parser" "*" +"@types/yauzl@^2.9.1": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.2.tgz#c48e5d56aff1444409e39fa164b0b4d4552a7b7a" + integrity sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA== + dependencies: + "@types/node" "*" + "@typescript-eslint/eslint-plugin@^4.5.0": version "4.33.0" resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz" @@ -4798,7 +4812,7 @@ balanced-match@^1.0.0: resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= -base64-js@^1.0.2: +base64-js@^1.0.2, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -4865,6 +4879,15 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.5.5: version "3.7.2" resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" @@ -5118,6 +5141,11 @@ btoa-lite@^1.0.0: resolved "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz" integrity sha1-M3dm2hWAEhD92VbCLpxokaudAzc= +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= + buffer-equal@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz" @@ -5152,6 +5180,14 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" +buffer@^5.2.1, buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz" @@ -6683,7 +6719,7 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@4, debug@^4.0.1, debug@^4.3.1, debug@^4.3.2: +debug@4, debug@4.3.2, debug@^4.0.1, debug@^4.3.1, debug@^4.3.2: version "4.3.2" resolved "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz" integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== @@ -6911,6 +6947,11 @@ detect-port-alt@1.1.6: address "^1.0.1" debug "^2.6.0" +devtools-protocol@0.0.948846: + version "0.0.948846" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.948846.tgz#bff47e2d1dba060130fa40ed2e5f78b916ba285f" + integrity sha512-5fGyt9xmMqUl2VI7+rnUkKCiAQIpLns8sfQtTENy5L70ktbNw0Z3TFJ1JoFNYdx/jffz4YXU45VF75wKZD7sZQ== + dezalgo@^1.0.0: version "1.0.3" resolved "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz" @@ -7296,7 +7337,7 @@ encoding@^0.1.11: dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.0.0, end-of-stream@^1.1.0: +end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -8086,6 +8127,17 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +extract-zip@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== + dependencies: + debug "^4.1.1" + get-stream "^5.1.0" + yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" @@ -8182,6 +8234,13 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= + dependencies: + pend "~1.2.0" + figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: version "3.5.2" resolved "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz" @@ -8456,6 +8515,11 @@ from@~0: resolved "https://registry.npmjs.org/from/-/from-0.1.7.tgz" integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fs-extra@^7.0.0: version "7.0.1" resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz" @@ -9527,6 +9591,14 @@ https-browserify@^1.0.0: resolved "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +https-proxy-agent@5.0.0, https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + https-proxy-agent@^2.2.1, https-proxy-agent@^2.2.3: version "2.2.4" resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz" @@ -9543,14 +9615,6 @@ https-proxy-agent@^4.0.0: agent-base "5" debug "4" -https-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== - dependencies: - agent-base "6" - debug "4" - human-signals@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz" @@ -9608,7 +9672,7 @@ identity-obj-proxy@3.0.0: dependencies: harmony-reflect "^1.4.6" -ieee754@^1.1.4: +ieee754@^1.1.13, ieee754@^1.1.4: version "1.2.1" resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -12087,6 +12151,11 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" +mkdirp-classic@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz" @@ -12278,6 +12347,13 @@ node-fetch-npm@^2.0.2: json-parse-better-errors "^1.0.0" safe-buffer "^5.1.1" +node-fetch@2.6.7, node-fetch@^2.6.5: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + node-fetch@^2.5.0, node-fetch@^2.6.0, node-fetch@^2.6.1: version "2.6.6" resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz" @@ -12285,13 +12361,6 @@ node-fetch@^2.5.0, node-fetch@^2.6.0, node-fetch@^2.6.1: dependencies: whatwg-url "^5.0.0" -node-fetch@^2.6.5: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - node-fetch@~2.6.1: version "2.6.1" resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz" @@ -13331,6 +13400,11 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz" @@ -13402,6 +13476,13 @@ pixelmatch@^5.2.1: dependencies: pngjs "^4.0.1" +pkg-dir@4.2.0, pkg-dir@^4.1.0, pkg-dir@^4.2.0: + 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== + dependencies: + find-up "^4.0.0" + pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz" @@ -13416,13 +13497,6 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" -pkg-dir@^4.1.0, pkg-dir@^4.2.0: - 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== - dependencies: - find-up "^4.0.0" - pkg-up@3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz" @@ -14305,7 +14379,7 @@ process@^0.11.10: resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= -progress@^2.0.0: +progress@2.0.3, progress@^2.0.0: version "2.0.3" resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -14387,6 +14461,11 @@ proxy-addr@~2.0.4, proxy-addr@~2.0.5: forwarded "0.2.0" ipaddr.js "1.9.1" +proxy-from-env@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + prr@~1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz" @@ -14473,6 +14552,24 @@ pupa@^2.0.1: dependencies: escape-goat "^2.0.0" +puppeteer@^13.1.3: + version "13.1.3" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-13.1.3.tgz#46b1e3f7577e59c08088b449c6fa161dbc78c680" + integrity sha512-nqcJNThLUG0Dgo++2mMtGR2FCyg7olJJhj/rm0A65muyN3nrH6lGvnNRzEaNmSnHWvjaDIG9ox5kxQB+nXTg5A== + dependencies: + debug "4.3.2" + devtools-protocol "0.0.948846" + extract-zip "2.0.1" + https-proxy-agent "5.0.0" + node-fetch "2.6.7" + 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.2.3" + purgecss@^2.3.0: version "2.3.0" resolved "https://registry.npmjs.org/purgecss/-/purgecss-2.3.0.tgz" @@ -14892,7 +14989,7 @@ read@1, read@~1.0.1: string_decoder "~1.1.1" util-deprecate "~1.0.1" -"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.6.0: +"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -15339,6 +15436,13 @@ rgba-regex@^1.0.0: resolved "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= +rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" @@ -15346,13 +15450,6 @@ rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: dependencies: glob "^7.1.3" -rimraf@^3.0.0, rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - rimraf@~2.2.1, rimraf@~2.2.8: version "2.2.8" resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" @@ -16697,6 +16794,27 @@ tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tar-fs@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + tar@^4.4.10, tar@^4.4.12, tar@^4.4.6, tar@^4.4.8: version "4.4.19" resolved "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz" @@ -16920,7 +17038,7 @@ through2@^4.0.0: dependencies: readable-stream "3" -through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@~2.3, through@~2.3.1: +through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@^2.3.8, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -17401,6 +17519,14 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" +unbzip2-stream@1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" + integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== + dependencies: + buffer "^5.2.1" + through "^2.3.8" + uncss@^0.17.3: version "0.17.3" resolved "https://registry.npmjs.org/uncss/-/uncss-0.17.3.tgz" @@ -18469,7 +18595,7 @@ write-pkg@^3.1.0: sort-keys "^2.0.0" write-json-file "^2.2.0" -ws@>=7.4.6: +ws@8.2.3, ws@>=7.4.6: version "8.2.3" resolved "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz" integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== @@ -18686,6 +18812,14 @@ yargs@~3.5.4: window-size "0.1.0" wordwrap "0.0.2" +yauzl@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + yn@3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz"