From 49ebecabdb5ddc03a865e0be53c7f431b35ecf6d Mon Sep 17 00:00:00 2001 From: Miguel Medeiros Date: Fri, 20 May 2022 07:20:35 -0300 Subject: [PATCH] chore: add integration tests using Playwright and Puppeteer (#627) * feat: add integration tests * fix: add readme test instructions * fix: add jest types * fix: normalize await calls * fix: development readme instructions * fix: use getByLabel instead of ids * fix: remove try/catch * feat: add playwright testing tool * fix: update readme test command * fix: removing args from Puppeteer launch fix: removing setViewport * fix: puppeteer args tags * fix: yarn installation at playwright gh workflow * fix: playwright commands * fix: playwright headfull image * docs: formatting #556 * test: change default wallet create url * chore: remove conflicts * chore: exclude playwright tests from default jest run * chore: adjusted playwirght setup - reduced to one browser and one test for now to first make it run again - adjusted readme - minor changes * test: update to match current UI * chore(ci): run playwright tests on open PRs * chore(deps): minor deps * chore: comment out tests for now * chore(playwright): get extension-id via test #556 * test(e2e): add exec path accpring to mujo-code/puppeteer-headful docs #556 * test(e2e): switch path to use prod #556 * test(alby): adjust create wallet test #556 * chore(e2e): adjust playwright setup #556 * test(albywallet): simplify test for now #556 also adjust extension path for CI * chore: split up test scripts #556 * docs: add tool links and chrome-only info #556 * chore: add info why on-fail screenshots etc are not working #556 * chore: cleanup #556 * chore(e2e): move extension-load code to helpers #556 * chore(e2e): make page var more descriptive #556 * test(albywallet): reduce test for now #556 * chore: fix test commands #556 Co-authored-by: escapedcat Co-authored-by: kiwiidb --- .github/workflows/playwright.yml | 48 ++++ .github/workflows/unit-tests.yml | 2 +- .gitignore | 13 +- README.md | 29 ++- jest.config.ts | 1 + package.json | 10 +- playwright.config.ts | 112 +++++++++ .../screens/connectors/NewWallet/index.tsx | 2 +- tests/e2e/createWallets.spec.ts | 171 +++++++++++++ tests/e2e/helpers/loadExtension.ts | 54 +++++ tsconfig.spec.json | 5 + yarn.lock | 226 ++++++++++++++---- 12 files changed, 620 insertions(+), 53 deletions(-) create mode 100644 .github/workflows/playwright.yml create mode 100644 playwright.config.ts create mode 100644 tests/e2e/createWallets.spec.ts create mode 100644 tests/e2e/helpers/loadExtension.ts create mode 100644 tsconfig.spec.json diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000000..67ef999883 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,48 @@ +name: E2E Tests + +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize] + +jobs: + e2e-tests: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + env: + PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true" + with: + node-version: "14.x" + args: install + + - name: Install dependencies + uses: borales/actions-yarn@v2.3.0 + with: + cmd: install # will run `yarn install` command + + - name: Build + uses: borales/actions-yarn@v2.3.0 + with: + cmd: build:chrome # will run `yarn build` command + + - name: Test Code + uses: mujo-code/puppeteer-headful@v2 + env: + CI: "true" + with: + args: npx playwright test + + - name: Artifact + uses: actions/upload-artifact@v2 + if: always() + with: + name: playwright-artifcats + path: | + playwright-report/ + test-results/ + retention-days: 30 diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index b9c09cf322..7fcaf97f99 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -21,4 +21,4 @@ jobs: - run: yarn install - name: Testing - run: yarn test + run: yarn test:unit diff --git a/.gitignore b/.gitignore index cb972f4679..827152972b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ yarn-debug.log* yarn-error.log* lerna-debug.log* - # Diagnostic reports (https://nodejs.org/api/report.html) report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json @@ -25,6 +24,11 @@ lib-cov coverage *.lcov +# unit/integration tets +test-results/ +playwright-report/ +trace.zip + # nyc test coverage .nyc_output @@ -43,6 +47,7 @@ build/Release # Dependency directories node_modules/ jspm_packages/ +.pnp.* # Snowpack dependency directory (https://snowpack.dev/) web_modules/ @@ -126,12 +131,10 @@ dist # OS files .DS_Store -## Build directory +# Build directory dist/ .awcache -.pnp.* - # Editor directories and files .idea .nova @@ -140,4 +143,4 @@ dist/ *.suo *.ntvs* *.njsproj -*.sln \ No newline at end of file +*.sln diff --git a/README.md b/README.md index 345666318c..0106ce0fc0 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Add Alby to your browser - [Add to Chrome, Opera, Brave, and all Chromium based browsers](https://chrome.google.com/webstore/detail/alby/iokeahhehimjnekafflcihljlcjccdbe) - [Add to Firefox](https://addons.mozilla.org/en-US/firefox/addon/alby/) -Try out the most recent version of Alby (Nightly Releases) +### Try out the most recent version of Alby (Nightly Releases) - [Firefox Nightly](https://alby-releases-public.s3.eu-central-1.amazonaws.com/alby-firefox-nightly-master.xpi) - best to install it as a temporary add-on as discussed in the "Load extension into browser" section - [Chrome Nightly](https://alby-releases-public.s3.eu-central-1.amazonaws.com/alby-chrome-nightly-master.zip) - go to `chrome://extensions/`, enable "Developer mode" (top right) and drag & drop the file in the browser @@ -60,7 +60,7 @@ Try out the most recent version of Alby (Nightly Releases) ## Project Structure -``` +```bash ./lightning-browser-extension ├── src # Source Code │   ├── app # React UI App @@ -127,6 +127,29 @@ If this is not reachable please let us know. We have a working [Storybook](https://storybook.js.org)-setup and some components have stories. You can find the deployed Storybook here: https://lbe-stories.netlify.app +### :heavy_check_mark: Tests + +#### E2E tests via [playwright](https://playwright.dev) ([using testing-library](https://testing-library.com/docs/pptr-testing-library/intro/)) + +```bash +yarn run dev:chrome +yarn test:e2e +``` + +:tipping_hand_woman: For now we only do E2E tests for Chrome + +#### Unit tests tests via [Jest](https://jestjs.io) + +```bash +yarn test:unit +``` + +#### Run all tests + +```bash +yarn test +``` + ### 💻 Load extension into browser - **Chrome** @@ -161,7 +184,7 @@ Most logs are written to the background script. Make sure to "inspect" the backg You can also use a Docker container and run the yarn commands within a container: -``` +```bash docker run --rm --volume="$(pwd):/app" --workdir="/app" -t -i node:lts "yarn install && yarn run package" ``` diff --git a/jest.config.ts b/jest.config.ts index f7becf54f4..7577daf844 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -13,4 +13,5 @@ module.exports = { setupFiles: ["jest-webextension-mock"], testEnvironment: "./jest.custom-test-environment.ts", setupFilesAfterEnv: ["./jest.setup.ts"], + modulePathIgnorePatterns: ["/tests"], }; diff --git a/package.json b/package.json index 555531746c..ce986414c7 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,9 @@ "lint:js:fix": "eslint src --ext .js,.jsx,.ts,.tsx --fix", "tsc:compile": "tsc --noEmit", "format": "prettier --loglevel silent --write 'src/**/*.(js|ts|jsx|tsx)'", - "test-ext": "jest ./src/extension", - "test-app": "jest ./src/app", - "test": "jest", + "test:unit": "jest", + "test:e2e": "npx playwright test", + "test": "yarn test:unit && yarn test:e2e", "test:coverage": "jest --coverage --collectCoverageFrom='src/**/*.(js|ts|jsx|tsx)'", "storybook": "start-storybook -p 6006", "build-storybook": "build-storybook", @@ -80,6 +80,7 @@ "@babel/preset-typescript": "^7.16.7", "@commitlint/cli": "^17.0.0", "@commitlint/config-conventional": "^17.0.0", + "@playwright/test": "^1.19.1", "@storybook/addon-actions": "^6.4.22", "@storybook/addon-essentials": "^6.4.22", "@storybook/addon-links": "^6.4.22", @@ -107,6 +108,7 @@ "babel-plugin-import": "^1.13.5", "buffer": "^6.0.3", "clean-webpack-plugin": "^4.0.0", + "complete-randomer": "^1.9.1", "copy-webpack-plugin": "^11.0.0", "cross-env": "^7.0.3", "css-loader": "^6.7.1", @@ -127,8 +129,10 @@ "postcss": "^8.4.13", "postcss-cli": "^9.1.0", "postcss-loader": "^6.2.1", + "pptr-testing-library": "^0.7.0", "prettier": "^2.6.2", "process": "^0.11.10", + "puppeteer": "^13.3.2", "resolve-url-loader": "^5.0.0", "sass": "^1.51.0", "sass-loader": "^12.6.0", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000000..c36f65f21d --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,112 @@ +import type { PlaywrightTestConfig } from "@playwright/test"; +import { devices } from "@playwright/test"; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +const config: PlaywrightTestConfig = { + testDir: "./tests/e2e", + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000, + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: process.env.CI ? "github" : "list", + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + // actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://localhost:3000', + // + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + // Not working because (electron relate dbut same issue): + // - https://github.com/microsoft/playwright/issues/8208 + // - https://github.com/microsoft/playwright/issues/12774 + // - https://github.com/microsoft/playwright/issues/12125 + // + // trace: "on", + // video: "on", + // screenshot: "on", + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: "chromium", + use: { + ...devices["Desktop Chrome"], + }, + }, + + // { + // name: "firefox", + // use: { + // ...devices["Desktop Firefox"], + // }, + // }, + + // { + // name: "webkit", + // use: { + // ...devices["Desktop Safari"], + // }, + // }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: "Microsoft Edge", + // use: { + // channel: "msedge", + // }, + // }, + // { + // name: "Google Chrome", + // use: { + // channel: "chrome", + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + outputDir: "test-results/", + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // port: 3000, + // }, +}; + +export default config; diff --git a/src/app/screens/connectors/NewWallet/index.tsx b/src/app/screens/connectors/NewWallet/index.tsx index 9734c459d6..2d5c629992 100644 --- a/src/app/screens/connectors/NewWallet/index.tsx +++ b/src/app/screens/connectors/NewWallet/index.tsx @@ -8,7 +8,7 @@ import TextField from "@components/form/TextField"; import ConnectorForm from "@components/ConnectorForm"; const walletCreateUrl = - process.env.WALLET_CREATE_URL || "https://getalby.com/api/users"; + process.env.WALLET_CREATE_URL || "https://app.regtest.getalby.com/api/users"; export default function NewWallet() { const [lndHubData, setLndHubData] = useState({ diff --git a/tests/e2e/createWallets.spec.ts b/tests/e2e/createWallets.spec.ts new file mode 100644 index 0000000000..3c48bd8cd1 --- /dev/null +++ b/tests/e2e/createWallets.spec.ts @@ -0,0 +1,171 @@ +import { test } from "@playwright/test"; +import { USER } from "complete-randomer"; +import { getDocument, queries, waitFor } from "pptr-testing-library"; +const { getByText, getByLabelText } = queries; + +import { loadExtension } from "./helpers/loadExtension"; + +test.describe("Create or connect wallets", () => { + test("successfully creates an Alby wallet", async () => { + const user = USER.SINGLE(); + + const { page: welcomePage } = await loadExtension(); + + // go through welcome page + const $document = await getDocument(welcomePage); + + const startedButton = await getByText($document, "Get Started"); + startedButton.click(); + + await waitFor(() => getByText($document, "Protect your wallet")); + + // type user password and confirm password + const passwordField = await getByLabelText($document, "Choose a password:"); + await passwordField.type(user.password); + + const passwordConfirmationField = await getByLabelText( + $document, + "Let's confirm you typed it correct:" + ); + await passwordConfirmationField.type(user.password); + + // submit password form + const passwordFormNextButton = await getByText($document, "Next"); + passwordFormNextButton.click(); + + await waitFor(() => + getByText($document, "Do you have a lightning wallet?") + ); + + // click at "Create Alby Wallet" + const createNewWalletButton = await getByText($document, "Alby Wallet"); + createNewWalletButton.click(); + + await waitFor(() => getByText($document, "Your Alby Lightning Wallet")); + + // type user email + const emailField = await getByLabelText($document, "Email Address"); + await emailField.type(user.email); + + // type user password and confirm password + const walletPasswordField = await getByLabelText($document, "Password"); + await walletPasswordField.type(user.password); + + // click create a wallet button + const createWalletButton = await getByText($document, "Continue"); + createWalletButton.click(); + + // @TODO: we have an DNS issue + // a ticket was opened at DigitalOcean + + // await welcomePage.waitForResponse(() => true); + + // await waitFor(() => getByText($document, "Your Alby account is ready.")); + + // submit form + // const nextButton = await getByText($document, "Continue"); + // nextButton.click(); + + // await wait(() => getByText($document, "Success!")); + }); + + // test("successfully connects to LNBits wallet", async () => { + // const user = USER.SINGLE(); + // const { page, browser } = await loadExtension(); + + // // go through welcome page + // const $document = await getDocument(page); + + // // go through welcome page + // const startedButton = await getByText($document, "Get Started"); + // startedButton.click(); + + // await wait(() => getByText($document, "Protect your wallet")); + + // // type user password and confirm password + // const passwordField = await getByLabelText($document, "Choose a password:"); + // await passwordField.type(user.password); + + // const passwordConfirmationField = await getByLabelText( + // $document, + // "Let's confirm you typed it correct:" + // ); + // await passwordConfirmationField.type(user.password); + + // // submit password form + // const passwordFormNextButton = await getByText($document, "Next"); + // passwordFormNextButton.click(); + + // await wait(() => getByText($document, "Do you have a lightning wallet?")); + + // // click at "Create LNbits Wallet" + // const createNewWalletButton = await getByText($document, "LNbits"); + // createNewWalletButton.click(); + + // await wait(() => getByText($document, "Connect to LNbits")); + + // const lnBitsAdminKey = "d8de4f373561446aa298cae2b9424325"; + // const adminKeyField = await getByLabelText($document, "LNbits Admin Key"); + // await adminKeyField.type(lnBitsAdminKey); + + // // submit form + // const continueButton = await getByText($document, "Continue"); + // continueButton.click(); + + // await page.waitForResponse(() => true); + + // await browser.close(); + // }); + + // test("successfully connects to BlueWallet", async () => { + // const user = USER.SINGLE(); + // const { page, browser } = await loadExtension(); + + // // go through welcome page + // const $document = await getDocument(page); + + // // go through welcome page + // const startedButton = await getByText($document, "Get Started"); + // startedButton.click(); + + // await wait(() => getByText($document, "Protect your wallet")); + + // // type user password and confirm password + // const passwordField = await getByLabelText($document, "Choose a password:"); + // await passwordField.type(user.password); + + // const passwordConfirmationField = await getByLabelText( + // $document, + // "Let's confirm you typed it correct:" + // ); + // await passwordConfirmationField.type(user.password); + + // // submit password form + // const passwordFormNextButton = await getByText($document, "Next"); + // passwordFormNextButton.click(); + + // await wait(() => getByText($document, "Do you have a lightning wallet?")); + + // // click at "LNDHub (BlueWallet)" + // const createNewWalletButton = await getByText( + // $document, + // "LNDHub (Bluewallet)" + // ); + // createNewWalletButton.click(); + + // await wait(() => getByText($document, "Connect to LNDHub (BlueWallet)")); + + // const lndHubUrl = + // "lndhub://c269ebb962f1a94f9c29:f6f16f35e935edc05ee7@https://lndhub.io"; + // const lndUrlField = await getByLabelText($document, "LNDHub Export URI"); + // await lndUrlField.type(lndHubUrl); + + // // submit form + // const continueButton = await getByText($document, "Continue"); + // continueButton.click(); + + // await page.waitForResponse(() => true); + + // await browser.close(); + // }); +}); diff --git a/tests/e2e/helpers/loadExtension.ts b/tests/e2e/helpers/loadExtension.ts new file mode 100644 index 0000000000..7f2092e532 --- /dev/null +++ b/tests/e2e/helpers/loadExtension.ts @@ -0,0 +1,54 @@ +import puppeteer from "puppeteer"; + +const delay = async (time) => { + return new Promise(function (resolve) { + setTimeout(resolve, time); + }); +}; + +export const loadExtension = async () => { + const extensionPath = process.env.CI + ? "./dist/production/chrome" + : "./dist/development/chrome"; + + const browser = await puppeteer.launch({ + headless: false, // https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#working-with-chrome-extensions + executablePath: process.env.PUPPETEER_EXEC_PATH, // set by docker container - https://github.com/mujo-code/puppeteer-headful + args: [ + `--disable-extensions-except=${extensionPath}`, + `--load-extension=${extensionPath}`, + "--disable-gpu", + "--disable-dev-shm-usage", + "--no-sandbox", + "--disable-setuid-sandbox", + ], + }); + + // trick to bring the new welcome page to the front + await delay(1000); + const page = await browser.newPage(); + await page.setViewport({ width: 1366, height: 768 }); + + // get extensionId + // https://github.com/microsoft/playwright/issues/5593#issuecomment-949813218 + await page.goto("chrome://inspect/#extensions"); + // https://techoverflow.net/2019/01/26/puppeteer-get-text-content-inner-html-of-an-element/ + // TODO: check if just `page.$('...') will work because it should: + // https://puppeteer.github.io/puppeteer/docs/puppeteer.elementhandle + const url = await page.evaluate( + () => + ( + document.querySelector( + '#extensions-list div[class="url"]' + ) as HTMLElement + ).innerText + ); + const [, , extensionId] = url.split("/"); + + const extensionOptionHtml = "welcome.html"; + const extPage = `chrome-extension://${extensionId}/${extensionOptionHtml}`; + + await page.goto(extPage); + + return { page, browser }; +}; diff --git a/tsconfig.spec.json b/tsconfig.spec.json new file mode 100644 index 0000000000..a607ee7f7a --- /dev/null +++ b/tsconfig.spec.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "types": ["jest", "node"] + } +} diff --git a/yarn.lock b/yarn.lock index eb296e44ff..1e2a822ede 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1997,6 +1997,14 @@ pirates "^4.0.5" source-map-support "^0.5.16" +"@babel/runtime-corejs3@^7.10.2": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.18.0.tgz#eed03023c5226b1e2b2ba32b8b6af5cb0518a6c7" + integrity sha512-G5FaGZOWORq9zthDjIrjib5XlcddeqLbIiDO3YQsut6j7aGf76xn0umUC/pA6+nApk3hQJF4JzLzg5PCl6ewJg== + dependencies: + core-js-pure "^3.20.2" + regenerator-runtime "^0.13.4" + "@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6": version "7.14.6" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz" @@ -2890,6 +2898,13 @@ mkdirp "^1.0.4" rimraf "^3.0.2" +"@playwright/test@^1.19.1": + version "1.22.1" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.22.1.tgz#78b4a7c13d8a7a0c6432672571d70c4d3963f027" + integrity sha512-8ouMBUboYslHom41W8bnSEn0TwlAMHhCACwOZeuiAgzukj7KobpZ+UBwrGE0jJ0UblJbKAQNRHXL+z7sDSkb6g== + dependencies: + playwright-core "1.22.1" + "@pmmmwh/react-refresh-webpack-plugin@^0.5.1": version "0.5.1" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.1.tgz#7e98d6f22c360e1dd00909f5fa9d0f6ecc263292" @@ -3974,6 +3989,20 @@ resolved "https://registry.yarnpkg.com/@tailwindcss/line-clamp/-/line-clamp-0.4.0.tgz#03353e31e77636b785f2336e8c978502cec1de81" integrity sha512-HQZo6gfx1D0+DU3nWlNLD5iA6Ef4JAXh0LeD8lOGrJwEDBwwJNKQza6WoXhhY1uQrxOuU8ROxV7CqiQV4CoiLw== +"@testing-library/dom@^7.31.0": + version "7.31.2" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.31.2.tgz#df361db38f5212b88555068ab8119f5d841a8c4a" + integrity sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^4.2.0" + aria-query "^4.2.2" + chalk "^4.1.0" + dom-accessibility-api "^0.5.6" + lz-string "^1.4.4" + pretty-format "^26.6.2" + "@testing-library/dom@^8.5.0": version "8.13.0" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.13.0.tgz#bc00bdd64c7d8b40841e27a70211399ad3af46f5" @@ -4647,6 +4676,13 @@ dependencies: "@types/yargs-parser" "*" +"@types/yauzl@^2.9.1": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599" + integrity sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw== + dependencies: + "@types/node" "*" + "@typescript-eslint/eslint-plugin@^5.22.0": version "5.25.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.25.0.tgz#e8ce050990e4d36cc200f2de71ca0d3eb5e77a31" @@ -5381,7 +5417,7 @@ ansi-regex@^4.1.0: resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== -ansi-regex@^5.0.1: +ansi-regex@^5.0.0, ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== @@ -5525,6 +5561,14 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +aria-query@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" + integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA== + dependencies: + "@babel/runtime" "^7.10.2" + "@babel/runtime-corejs3" "^7.10.2" + aria-query@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.0.0.tgz#210c21aaf469613ee8c9a62c7f86525e058db52c" @@ -6417,7 +6461,7 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.2.0, buffer@^5.5.0: +buffer@^5.2.0, buffer@^5.2.1, buffer@^5.5.0: version "5.7.1" resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -7024,6 +7068,11 @@ compare-func@^2.0.0: array-ify "^1.0.0" dot-prop "^5.1.0" +complete-randomer@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/complete-randomer/-/complete-randomer-1.9.1.tgz#9b087f1f38472a91754116f82c2d74d2f3f70abc" + integrity sha512-ukBE8A1EA5cBqSvxNVvm37qZA7nLvTOk04KMZvnXEwHI2UjoiZWQBjS62UZrHBDvo1EWhBaryAV8kIg4HNajvA== + component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz" @@ -7233,6 +7282,11 @@ core-js-compat@^3.21.0, core-js-compat@^3.22.1: browserslist "^4.20.3" semver "7.0.0" +core-js-pure@^3.20.2: + version "3.22.5" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.22.5.tgz#bdee0ed2f9b78f2862cda4338a07b13a49b6c9a9" + integrity sha512-8xo9R00iYD7TcV7OrC98GwxiUEAabVWO3dix+uyWjnYrx9fyASLlIX+f/3p5dW5qByaP2bcZ8X/T47s55et/tA== + core-js-pure@^3.8.1: version "3.18.1" resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.18.1.tgz#097d34d24484be45cea700a448d1e74622646c80" @@ -7367,6 +7421,13 @@ cross-env@^7.0.3: dependencies: cross-spawn "^7.0.1" +cross-fetch@3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== + dependencies: + node-fetch "2.6.7" + cross-spawn@^6.0.0: version "6.0.5" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz" @@ -7672,6 +7733,13 @@ debug@4: dependencies: ms "2.1.2" +debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + debug@^3.0.0, debug@^3.2.7: version "3.2.7" resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" @@ -7679,13 +7747,6 @@ debug@^3.0.0, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - decamelize-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" @@ -7899,6 +7960,11 @@ detective@^5.2.0: defined "^1.0.0" minimist "^1.1.1" +devtools-protocol@0.0.981744: + version "0.0.981744" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.981744.tgz#9960da0370284577d46c28979a0b32651022bacf" + integrity sha512-0cuGS8+jhR67Fy7qG3i3Pc7Aw494sb9yG9QgpG97SFVWwolgYjlhJg7n+UaHxOQT30d1TYu/EYe9k01ivLErIg== + dexie@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/dexie/-/dexie-3.2.2.tgz#fa6f2a3c0d6ed0766f8d97a03720056f88fe0e01" @@ -8806,6 +8872,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" + extract-zip@^1.6.6: version "1.7.0" resolved "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz" @@ -10097,6 +10174,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.1, https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + https-proxy-agent@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz" @@ -10105,14 +10190,6 @@ https-proxy-agent@^4.0.0: agent-base "5" debug "4" -https-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -12354,6 +12431,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@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4: version "0.5.5" resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" @@ -12483,7 +12565,7 @@ node-dir@^0.1.10, node-dir@^0.1.17: dependencies: minimatch "^3.0.2" -node-fetch@^2.6.1: +node-fetch@2.6.7, node-fetch@^2.6.1: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== @@ -13298,6 +13380,13 @@ pixelmatch@^4.0.2: dependencies: pngjs "^3.0.0" +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@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz" @@ -13305,13 +13394,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-dir@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz" @@ -13319,6 +13401,11 @@ pkg-dir@^5.0.0: dependencies: find-up "^5.0.0" +playwright-core@1.22.1: + version "1.22.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.22.1.tgz#59ddf903546171fdfd9c3dc189630c883619667c" + integrity sha512-H+ZUVYnceWNXrRf3oxTEKAr81QzFsCKu5Fp//fEjQvqgKkfA1iX3E9DBrPJpPNOrgVzcE+IqeI0fDmYJe6Ynnw== + pngjs@^3.0.0, pngjs@^3.3.3: version "3.4.0" resolved "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz" @@ -13780,6 +13867,14 @@ postcss@^8.4.7: picocolors "^1.0.0" source-map-js "^1.0.2" +pptr-testing-library@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/pptr-testing-library/-/pptr-testing-library-0.7.0.tgz#5676a4394df3958cc2ee5722a3c4fa72520369a8" + integrity sha512-NYt6XQzAoWCC/WKkBWW40Uth+MBRKmdYr+3NdrF4gTgBeK31zNQN6gFvmTubjZY5mUVdHmPns60jTs7PZuwg2A== + dependencies: + "@testing-library/dom" "^7.31.0" + wait-for-expect "^3.0.2" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" @@ -13829,6 +13924,16 @@ pretty-error@^4.0.0: lodash "^4.17.20" renderkid "^3.0.0" +pretty-format@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== + dependencies: + "@jest/types" "^26.6.2" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^17.0.1" + pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" @@ -13880,7 +13985,7 @@ process@^0.11.10: resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= -progress@^2.0.1: +progress@2.0.3, progress@^2.0.1: version "2.0.3" resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -13952,7 +14057,7 @@ proxy-addr@~2.0.5, proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" -proxy-from-env@^1.0.0: +proxy-from-env@1.1.0, proxy-from-env@^1.0.0: version "1.1.0" resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== @@ -14047,6 +14152,24 @@ puppeteer-core@^2.1.1: rimraf "^2.6.1" ws "^6.1.0" +puppeteer@^13.3.2: + version "13.7.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-13.7.0.tgz#18e16f83e397cf02f7a0804c67c1603d381cfb0b" + integrity sha512-U1uufzBjz3+PkpCxFrWzh4OrMIdIb2ztzCu0YEPfRHjHswcSwHZswnK+WdsOQJsRV8WeTg3jLhJR4D867+fjsA== + dependencies: + cross-fetch "3.1.5" + debug "4.3.4" + devtools-protocol "0.0.981744" + extract-zip "2.0.1" + https-proxy-agent "5.0.1" + 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" + q@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -14869,6 +14992,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.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" @@ -14876,13 +15006,6 @@ rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, 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.6.2: version "2.6.3" resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz" @@ -16032,7 +16155,17 @@ tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz" integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw== -tar-stream@^2.2.0: +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, tar-stream@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz" integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== @@ -16559,6 +16692,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" + undici@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/undici/-/undici-5.0.0.tgz#3c1e08c7f0df90c485d5d8dbb0517e11e34f2090" @@ -16973,6 +17114,11 @@ w3c-xmlserializer@^3.0.0: dependencies: xml-name-validator "^4.0.0" +wait-for-expect@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/wait-for-expect/-/wait-for-expect-3.0.2.tgz#d2f14b2f7b778c9b82144109c8fa89ceaadaa463" + integrity sha512-cfS1+DZxuav1aBYbaO/kE06EOS8yRw7qOFoD3XtjTkYvCvh3zUvNST8DXK/nPaeqIzIv3P3kL3lRJn8iwOiSag== + walker@^1.0.7, walker@~1.0.5: version "1.0.7" resolved "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz" @@ -17483,6 +17629,11 @@ write-file-atomic@^4.0.1: imurmurhash "^0.1.4" signal-exit "^3.0.7" +ws@8.5.0, ws@^8.4.2: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + ws@^6.1.0: version "6.2.2" resolved "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz" @@ -17495,11 +17646,6 @@ ws@^8.2.3: resolved "https://registry.yarnpkg.com/ws/-/ws-8.3.0.tgz#7185e252c8973a60d57170175ff55fdbd116070d" integrity sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw== -ws@^8.4.2: - version "8.5.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" - integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== - xdg-basedir@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz"