diff --git a/.circleci/config.yml b/.circleci/config.yml index b5da1369..0cbddf2f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -65,7 +65,7 @@ commands: default: "" steps: - run: wget -qO - https://download.opensuse.org/repositories/Emulators:/Wine:/Debian/xUbuntu_18.04/Release.key | apt-key add - - - run: apt-get update || true && apt-get install ca-certificates && apt-get update && apt-get -y install << parameters.apt_opts >> + - run: apt-get update || true && apt-get install -y ca-certificates libxtst-dev libpng++-dev && apt-get update && apt-get -y install << parameters.apt_opts >> update_image: description: "Update image" @@ -76,7 +76,7 @@ commands: steps: - update_base_image: apt_opts: << parameters.apt_opts >> - - run: npm ci + - run: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm ci win_make: description: "Run mattermost's makefile.ps1 on ./scripts/" diff --git a/package-lock.json b/package-lock.json index a4564bf4..78042c09 100644 --- a/package-lock.json +++ b/package-lock.json @@ -89,9 +89,10 @@ "mocha": "^5.2.0", "mocha-circleci-reporter": "0.0.3", "npm-run-all": "^4.1.5", + "playwright": "^1.15.2", + "robotjs": "^0.6.0", "sass-loader": "^10.2.0", "shebang-loader": "^0.0.1", - "spectron": "^15.0.0", "style-loader": "^2.0.0", "typescript": "^4.3.4", "url-loader": "^1.1.2", @@ -2135,12 +2136,6 @@ "semver": "bin/semver.js" } }, - "node_modules/@electron/remote": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@electron/remote/-/remote-1.1.0.tgz", - "integrity": "sha512-yr8gZTkIgJYKbFqExI4QZqMSjn1kL/us9Dl46+TH1EZdhgRtsJ6HDfdsIxu0QEc6Hv+DMAXs69rgquH+8FDk4w==", - "dev": true - }, "node_modules/@electron/universal": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.0.5.tgz", @@ -5129,18 +5124,6 @@ "integrity": "sha512-TbH79tcyi9FHwbyboOKeRachRq63mSuWYXOflsNO9ZyE5ClQ/JaozNKl+aWUq87qPNsXasXxi2AbgfwIJ+8GQw==", "dev": true }, - "node_modules/@types/cacheable-request": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz", - "integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==", - "dev": true, - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "*", - "@types/node": "*", - "@types/responselike": "*" - } - }, "node_modules/@types/color-convert": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.0.tgz", @@ -5226,12 +5209,6 @@ "integrity": "sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA==", "dev": true }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz", - "integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==", - "dev": true - }, "node_modules/@types/invariant": { "version": "2.2.34", "resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.34.tgz", @@ -5261,15 +5238,6 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, - "node_modules/@types/keyv": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz", - "integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/markdown-to-jsx": { "version": "6.11.3", "resolved": "https://registry.npmjs.org/@types/markdown-to-jsx/-/markdown-to-jsx-6.11.3.tgz", @@ -5362,24 +5330,6 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" }, - "node_modules/@types/puppeteer": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-5.4.3.tgz", - "integrity": "sha512-3nE8YgR9DIsgttLW+eJf6mnXxq8Ge+27m5SU3knWmrlfl6+KOG0Bf9f7Ua7K+C4BnaTMAh3/UpySqdAYvrsvjg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/puppeteer-core": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@types/puppeteer-core/-/puppeteer-core-5.4.0.tgz", - "integrity": "sha512-yqRPuv4EFcSkTyin6Yy17pN6Qz2vwVwTCJIDYMXbE3j8vTPhv0nCQlZOl5xfi0WHUkqvQsjAR8hAfjeMCoetwg==", - "dev": true, - "dependencies": { - "@types/puppeteer": "*" - } - }, "node_modules/@types/q": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", @@ -5489,15 +5439,6 @@ "@types/react": "*" } }, - "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/scheduler": { "version": "0.16.1", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz", @@ -5599,12 +5540,6 @@ "node": ">= 8" } }, - "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/winreg": { "version": "1.2.30", "resolved": "https://registry.npmjs.org/@types/winreg/-/winreg-1.2.30.tgz", @@ -6067,105 +6002,6 @@ "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, - "node_modules/@wdio/config": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-6.12.1.tgz", - "integrity": "sha512-V5hTIW5FNlZ1W33smHF4Rd5BKjGW2KeYhyXDQfXHjqLCeRiirZ9fABCo9plaVQDnwWSUMWYaAaIAifV82/oJCQ==", - "dev": true, - "dependencies": { - "@wdio/logger": "6.10.10", - "deepmerge": "^4.0.0", - "glob": "^7.1.2" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@wdio/logger": { - "version": "6.10.10", - "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-6.10.10.tgz", - "integrity": "sha512-2nh0hJz9HeZE0VIEMI+oPgjr/Q37ohrR9iqsl7f7GW5ik+PnKYCT9Eab5mR1GNMG60askwbskgGC1S9ygtvrSw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "loglevel": "^1.6.0", - "loglevel-plugin-prefix": "^0.8.4", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "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/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/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": "6.12.0", - "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-6.12.0.tgz", - "integrity": "sha512-UhTBZxClCsM3VjaiDp4DoSCnsa7D1QNmI2kqEBfIpyNkT3GcZhJb7L+nL0fTkzCwi7+/uLastb3/aOwH99gt0A==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@wdio/repl": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-6.11.0.tgz", - "integrity": "sha512-FxrFKiTkFyELNGGVEH1uijyvNY7lUpmff6x+FGskFGZB4uSRs0rxkOMaEjxnxw7QP1zgQKr2xC7GyO03gIGRGg==", - "dev": true, - "dependencies": { - "@wdio/utils": "6.11.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@wdio/utils": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-6.11.0.tgz", - "integrity": "sha512-vf0sOQzd28WbI26d6/ORrQ4XKWTzSlWLm9W/K/eJO0NASKPEzR+E+Q2kaa+MJ4FKXUpjbt+Lxfo+C26TzBk7tg==", - "dev": true, - "dependencies": { - "@wdio/logger": "6.10.10" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/@webassemblyjs/ast": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", @@ -6405,15 +6241,6 @@ "node": ">= 0.12.0" } }, - "node_modules/agent-base": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", - "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", - "dev": true, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/aggregate-error": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", @@ -6836,102 +6663,6 @@ "node": ">=4" } }, - "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/node_modules/async": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.1.tgz", - "integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==", - "dev": true - }, - "node_modules/archiver/node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/archiver/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "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/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "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" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/are-we-there-yet": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", @@ -9104,15 +8835,6 @@ "node": ">=0.10.0" } }, - "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": "6.1.0", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", @@ -9458,44 +9180,6 @@ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, - "node_modules/chrome-launcher": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.13.4.tgz", - "integrity": "sha512-nnzXiDbGKjDSK6t2I+35OAPBy5Pw/39bgkb/ZAFwMhwJbdYBp6aH+vW28ZgtjdU890Q7D+3wN/tB8N66q5Gi2A==", - "dev": true, - "dependencies": { - "@types/node": "*", - "escape-string-regexp": "^1.0.5", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0", - "mkdirp": "^0.5.3", - "rimraf": "^3.0.2" - } - }, - "node_modules/chrome-launcher/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/chrome-launcher/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": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/chrome-trace-event": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", @@ -9777,35 +9461,6 @@ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", "dev": true }, - "node_modules/compress-commons": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.0.tgz", - "integrity": "sha512-ofaaLqfraD1YRTkrRKPCrGJ1pFeDG/MVCkVVV2FNGeWquSlqw5wOrwOfPQ1xF2u+blpeWASie5EubHz+vsNIgA==", - "dev": true, - "dependencies": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^4.0.1", - "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/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -10639,22 +10294,6 @@ "buffer": "^5.1.0" } }, - "node_modules/crc-32": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", - "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", - "dev": true, - "dependencies": { - "exit-on-epipe": "~1.0.1", - "printj": "~1.1.0" - }, - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/crc/node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -10680,33 +10319,6 @@ "ieee754": "^1.1.13" } }, - "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/create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", @@ -10943,12 +10555,6 @@ "fastparse": "^1.1.2" } }, - "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-tree": { "version": "1.0.0-alpha.37", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", @@ -10963,12 +10569,6 @@ "node": ">=8.0.0" } }, - "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/css-what": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", @@ -11602,6 +11202,18 @@ "node": ">=0.10.0" } }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "dev": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/detect-node": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", @@ -11672,47 +11284,6 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "node_modules/dev-null": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dev-null/-/dev-null-0.1.1.tgz", - "integrity": "sha1-WiBc48Ky73e2I41roXnrdMag6Bg=", - "dev": true - }, - "node_modules/devtools": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/devtools/-/devtools-6.12.1.tgz", - "integrity": "sha512-JyG46suEiZmld7/UVeogkCWM0zYGt+2ML/TI+SkEp+bTv9cs46cDb0pKF3glYZJA7wVVL2gC07Ic0iCxyJEnCQ==", - "dev": true, - "dependencies": { - "@wdio/config": "6.12.1", - "@wdio/logger": "6.10.10", - "@wdio/protocols": "6.12.0", - "@wdio/utils": "6.11.0", - "chrome-launcher": "^0.13.1", - "edge-paths": "^2.1.0", - "puppeteer-core": "^5.1.0", - "ua-parser-js": "^0.7.21", - "uuid": "^8.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/devtools-protocol": { - "version": "0.0.818844", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.818844.tgz", - "integrity": "sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg==", - "dev": true - }, - "node_modules/devtools/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/devtron": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/devtron/-/devtron-1.4.0.tgz", @@ -12412,31 +11983,6 @@ "stream-shift": "^1.0.0" } }, - "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/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -12687,58 +12233,6 @@ "node": ">=10" } }, - "node_modules/electron-chromedriver": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-13.0.0.tgz", - "integrity": "sha512-fID1ms8wT7qNfoKkXHNpH0ZE8/Nclb5YmkF3O0w57OxsR8S9PxgE9CJAgaSGroxBgZ+ge1i2OU0Aq/WE/e/Neg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@electron/get": "^1.12.4", - "extract-zip": "^2.0.0" - }, - "bin": { - "chromedriver": "chromedriver.js" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/electron-chromedriver/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/electron-chromedriver/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/electron-connect": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/electron-connect/-/electron-connect-0.6.3.tgz", @@ -14595,15 +14089,6 @@ "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-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -14661,6 +14146,15 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -15832,15 +15326,6 @@ "has-symbols": "^1.0.1" } }, - "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" - } - }, "node_modules/get-proxy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", @@ -15952,6 +15437,12 @@ "node": ">=6" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", + "dev": true + }, "node_modules/glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -16323,12 +15814,6 @@ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", "dev": true }, - "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", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -16863,38 +16348,12 @@ "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", "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": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, - "node_modules/https-proxy-agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", - "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", - "dev": true, - "dependencies": { - "agent-base": "5", - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/humanize-plus": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/humanize-plus/-/humanize-plus-1.8.2.tgz", @@ -18336,6 +17795,12 @@ "node": ">=8" } }, + "node_modules/jpeg-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.3.tgz", + "integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==", + "dev": true + }, "node_modules/jquery": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", @@ -18567,18 +18032,6 @@ "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==" }, - "node_modules/lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -18600,31 +18053,6 @@ "immediate": "~3.0.5" } }, - "node_modules/lighthouse-logger": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.2.0.tgz", - "integrity": "sha512-wzUvdIeJZhRsG6gpZfmSCfysaxNEr43i+QT+Hie94wvHDKFLi4n7C2GqZ4sTC+PH5b5iktmXJvU87rWvhP3lHw==", - "dev": true, - "dependencies": { - "debug": "^2.6.8", - "marky": "^1.2.0" - } - }, - "node_modules/lighthouse-logger/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/lighthouse-logger/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, "node_modules/lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -18728,76 +18156,22 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "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.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "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.escaperegexp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" }, - "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.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" }, - "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.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/logalot": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz", @@ -18835,12 +18209,6 @@ "node": ">= 0.6.0" } }, - "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/longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -19031,12 +18399,6 @@ "react": ">= 0.14.0" } }, - "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/matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", @@ -19865,8 +19227,7 @@ "version": "2.14.1", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "dev": true, - "optional": true + "dev": true }, "node_modules/nanoid": { "version": "3.1.20", @@ -19902,6 +19263,12 @@ "node": ">=0.10.0" } }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, "node_modules/native-url": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/native-url/-/native-url-0.2.6.tgz", @@ -19960,6 +19327,15 @@ "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", "dev": true }, + "node_modules/node-abi": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "dev": true, + "dependencies": { + "semver": "^5.4.1" + } + }, "node_modules/node-addon-api": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", @@ -20049,6 +19425,12 @@ "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", "devOptional": true }, + "node_modules/noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", + "dev": 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", @@ -21239,6 +20621,152 @@ "node": ">=6" } }, + "node_modules/playwright": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.15.2.tgz", + "integrity": "sha512-+Z+7ckihyxR6rK5q8DWC6eUbKARfXpyxpjNcoJfgwSr64lAOzjhyFQiPC/JkdIqhsLgZjxpWfl1S7fLb+wPkgA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "commander": "^6.1.0", + "debug": "^4.1.1", + "extract-zip": "^2.0.1", + "https-proxy-agent": "^5.0.0", + "jpeg-js": "^0.4.2", + "mime": "^2.4.6", + "pngjs": "^5.0.0", + "progress": "^2.0.3", + "proper-lockfile": "^4.1.1", + "proxy-from-env": "^1.1.0", + "rimraf": "^3.0.2", + "stack-utils": "^2.0.3", + "ws": "^7.4.6", + "yazl": "^2.5.1" + }, + "bin": { + "playwright": "lib/cli/cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/playwright/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/playwright/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/playwright/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/playwright/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/playwright/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/playwright/node_modules/mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/playwright/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": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/playwright/node_modules/ws": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", + "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/plist": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.2.tgz", @@ -21264,6 +20792,15 @@ "node": ">=4.0" } }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/pngquant-bin": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/pngquant-bin/-/pngquant-bin-5.0.2.tgz", @@ -21629,6 +21166,35 @@ "node": ">=6" } }, + "node_modules/prebuild-install": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz", + "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==", + "dev": true, + "dependencies": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.7.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -21666,18 +21232,6 @@ "node": ">= 0.8" } }, - "node_modules/printj": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", - "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==", - "dev": true, - "bin": { - "printj": "bin/printj.njs" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/prismjs": { "version": "1.23.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz", @@ -21788,6 +21342,17 @@ "react": ">=0.14.0" } }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, "node_modules/property-information": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", @@ -21910,106 +21475,6 @@ "node": ">=8" } }, - "node_modules/puppeteer-core": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-5.5.0.tgz", - "integrity": "sha512-tlA+1n+ziW/Db03hVV+bAecDKse8ihFRXYiEypBe9IlLRvOCzYFG6qrCMBYK34HO/Q/Ecjc+tvkHRAfLVH+NgQ==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "devtools-protocol": "0.0.818844", - "extract-zip": "^2.0.0", - "https-proxy-agent": "^4.0.0", - "node-fetch": "^2.6.1", - "pkg-dir": "^4.2.0", - "progress": "^2.0.1", - "proxy-from-env": "^1.0.0", - "rimraf": "^3.0.2", - "tar-fs": "^2.0.0", - "unbzip2-stream": "^1.3.3", - "ws": "^7.2.3" - }, - "engines": { - "node": ">=10.18.1" - } - }, - "node_modules/puppeteer-core/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/puppeteer-core/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" - } - }, - "node_modules/puppeteer-core/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/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": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/puppeteer-core/node_modules/ws": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", - "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -22060,15 +21525,6 @@ "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", "dev": true }, - "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" - } - }, "node_modules/raf-schd": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", @@ -23303,15 +22759,6 @@ "util-deprecate": "~1.0.1" } }, - "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": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", @@ -23653,12 +23100,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-alpn": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.1.2.tgz", - "integrity": "sha512-8OyfzhAtA32LVUsJSke3auIyINcwdh5l3cvYKdKO0nvsYSKuiLfTM5i78PJswFPT8y6cPW+L1v6/hE95chcpDA==", - "dev": true - }, "node_modules/resolve-cwd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", @@ -23717,21 +23158,6 @@ "lowercase-keys": "^1.0.0" } }, - "node_modules/resq": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/resq/-/resq-1.10.0.tgz", - "integrity": "sha512-hCUd0xMalqtPDz4jXIqs0M5Wnv/LZXN8h7unFOo4/nvExT9dDPbhwd3udRxLlp0HgBnHcV009UlduE9NZi7A6w==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^2.0.1" - } - }, - "node_modules/resq/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/ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", @@ -23760,12 +23186,6 @@ "node": ">=0.10.0" } }, - "node_modules/rgb2hex": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.3.tgz", - "integrity": "sha512-clEe0m1xv+Tva1B/TOepuIcvLAxP0U+sCDfgt1SX1HmI2Ahr5/Cd/nzJM1e78NKVtWdoo0s33YehpFA8UfIShQ==", - "dev": true - }, "node_modules/rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -23813,6 +23233,18 @@ "dev": true, "optional": true }, + "node_modules/robotjs": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/robotjs/-/robotjs-0.6.0.tgz", + "integrity": "sha512-6pRWI3d+CBZqCXT/rsJfabbZoELua+jTeXilG27F8Jvix/J2BYZ0O7Tly2WCmXyqw5xYdCvOwvCeLRHEtXkt4w==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "nan": "^2.14.0", + "node-abi": "^2.13.0", + "prebuild-install": "^5.3.3" + } + }, "node_modules/run-parallel": { "version": "1.1.10", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", @@ -24415,6 +23847,61 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "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/simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "dev": true, + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-get/node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "dev": true, + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/simple-get/node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -24784,193 +24271,6 @@ "node": ">= 6" } }, - "node_modules/spectron": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/spectron/-/spectron-15.0.0.tgz", - "integrity": "sha512-eErHqymkEVb6H+LPZQoDYvWEv93o3nhxL7HXXdmC61ncV0jBckh8x3Qt6j+As2c1n0C/hKG9A2H1NnwGwD6agg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@electron/remote": "^1.1.0", - "dev-null": "^0.1.1", - "electron-chromedriver": "^13.0.0", - "got": "^11.8.0", - "split": "^1.0.1", - "webdriverio": "^6.9.1" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/spectron/node_modules/@sindresorhus/is": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", - "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/spectron/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/spectron/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/spectron/node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/spectron/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/spectron/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" - } - }, - "node_modules/spectron/node_modules/got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", - "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.1", - "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" - } - }, - "node_modules/spectron/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/spectron/node_modules/keyv": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", - "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/spectron/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/spectron/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/spectron/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/spectron/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/spectron/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/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, "node_modules/split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -25079,6 +24379,27 @@ "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", "dev": true }, + "node_modules/stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/stackframe": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", @@ -25624,6 +24945,20 @@ "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" @@ -25884,7 +25219,8 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "dev": true, + "optional": true }, "node_modules/through2": { "version": "2.0.5", @@ -26215,7 +25551,6 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, - "optional": true, "dependencies": { "safe-buffer": "^5.0.1" }, @@ -26295,15 +25630,6 @@ "node": ">=4.2.0" } }, - "node_modules/ua-parser-js": { - "version": "0.7.21", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz", - "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", @@ -26330,6 +25656,7 @@ "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "dev": true, + "optional": true, "dependencies": { "buffer": "^5.2.1", "through": "^2.3.8" @@ -26354,6 +25681,7 @@ "url": "https://feross.org/support" } ], + "optional": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -27157,235 +26485,6 @@ "minimalistic-assert": "^1.0.0" } }, - "node_modules/webdriver": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-6.12.1.tgz", - "integrity": "sha512-3rZgAj9o2XHp16FDTzvUYaHelPMSPbO1TpLIMUT06DfdZjNYIzZiItpIb/NbQDTPmNhzd9cuGmdI56WFBGY2BA==", - "dev": true, - "dependencies": { - "@wdio/config": "6.12.1", - "@wdio/logger": "6.10.10", - "@wdio/protocols": "6.12.0", - "@wdio/utils": "6.11.0", - "got": "^11.0.2", - "lodash.merge": "^4.6.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webdriver/node_modules/@sindresorhus/is": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", - "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/webdriver/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/webdriver/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/webdriver/node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/webdriver/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/webdriver/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" - } - }, - "node_modules/webdriver/node_modules/got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", - "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.1", - "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" - } - }, - "node_modules/webdriver/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/webdriver/node_modules/keyv": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", - "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/webdriver/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/webdriver/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/webdriver/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/webdriver/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/webdriver/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/webdriverio": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-6.12.1.tgz", - "integrity": "sha512-Nx7ge0vTWHVIRUbZCT+IuMwB5Q0Q5nLlYdgnmmJviUKLuc3XtaEBkYPTbhHWHgSBXsPZMIc023vZKNkn+6iyeQ==", - "dev": true, - "dependencies": { - "@types/puppeteer-core": "^5.4.0", - "@wdio/config": "6.12.1", - "@wdio/logger": "6.10.10", - "@wdio/repl": "6.11.0", - "@wdio/utils": "6.11.0", - "archiver": "^5.0.0", - "atob": "^2.1.2", - "css-shorthand-properties": "^1.1.1", - "css-value": "^0.0.1", - "devtools": "6.12.1", - "fs-extra": "^9.0.1", - "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": "^5.1.0", - "resq": "^1.9.1", - "rgb2hex": "0.2.3", - "serialize-error": "^8.0.0", - "webdriver": "6.12.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webdriverio/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" - } - }, - "node_modules/webdriverio/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" - } - }, "node_modules/webpack": { "version": "4.44.2", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", @@ -28274,6 +27373,12 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, + "node_modules/which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "dev": true + }, "node_modules/wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", @@ -28576,6 +27681,15 @@ "fd-slicer": "~1.1.0" } }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -28584,34 +27698,6 @@ "engines": { "node": ">=10" } - }, - "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" - } } }, "dependencies": { @@ -30031,12 +29117,6 @@ } } }, - "@electron/remote": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@electron/remote/-/remote-1.1.0.tgz", - "integrity": "sha512-yr8gZTkIgJYKbFqExI4QZqMSjn1kL/us9Dl46+TH1EZdhgRtsJ6HDfdsIxu0QEc6Hv+DMAXs69rgquH+8FDk4w==", - "dev": true - }, "@electron/universal": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.0.5.tgz", @@ -32263,18 +31343,6 @@ "integrity": "sha512-TbH79tcyi9FHwbyboOKeRachRq63mSuWYXOflsNO9ZyE5ClQ/JaozNKl+aWUq87qPNsXasXxi2AbgfwIJ+8GQw==", "dev": true }, - "@types/cacheable-request": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz", - "integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==", - "dev": true, - "requires": { - "@types/http-cache-semantics": "*", - "@types/keyv": "*", - "@types/node": "*", - "@types/responselike": "*" - } - }, "@types/color-convert": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.0.tgz", @@ -32360,12 +31428,6 @@ "integrity": "sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA==", "dev": true }, - "@types/http-cache-semantics": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz", - "integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==", - "dev": true - }, "@types/invariant": { "version": "2.2.34", "resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.34.tgz", @@ -32395,15 +31457,6 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, - "@types/keyv": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz", - "integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, "@types/markdown-to-jsx": { "version": "6.11.3", "resolved": "https://registry.npmjs.org/@types/markdown-to-jsx/-/markdown-to-jsx-6.11.3.tgz", @@ -32496,24 +31549,6 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" }, - "@types/puppeteer": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-5.4.3.tgz", - "integrity": "sha512-3nE8YgR9DIsgttLW+eJf6mnXxq8Ge+27m5SU3knWmrlfl6+KOG0Bf9f7Ua7K+C4BnaTMAh3/UpySqdAYvrsvjg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/puppeteer-core": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@types/puppeteer-core/-/puppeteer-core-5.4.0.tgz", - "integrity": "sha512-yqRPuv4EFcSkTyin6Yy17pN6Qz2vwVwTCJIDYMXbE3j8vTPhv0nCQlZOl5xfi0WHUkqvQsjAR8hAfjeMCoetwg==", - "dev": true, - "requires": { - "@types/puppeteer": "*" - } - }, "@types/q": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", @@ -32625,15 +31660,6 @@ "@types/react": "*" } }, - "@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/scheduler": { "version": "0.16.1", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz", @@ -32734,12 +31760,6 @@ } } }, - "@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/winreg": { "version": "1.2.30", "resolved": "https://registry.npmjs.org/@types/winreg/-/winreg-1.2.30.tgz", @@ -33058,80 +32078,6 @@ "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, - "@wdio/config": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-6.12.1.tgz", - "integrity": "sha512-V5hTIW5FNlZ1W33smHF4Rd5BKjGW2KeYhyXDQfXHjqLCeRiirZ9fABCo9plaVQDnwWSUMWYaAaIAifV82/oJCQ==", - "dev": true, - "requires": { - "@wdio/logger": "6.10.10", - "deepmerge": "^4.0.0", - "glob": "^7.1.2" - } - }, - "@wdio/logger": { - "version": "6.10.10", - "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-6.10.10.tgz", - "integrity": "sha512-2nh0hJz9HeZE0VIEMI+oPgjr/Q37ohrR9iqsl7f7GW5ik+PnKYCT9Eab5mR1GNMG60askwbskgGC1S9ygtvrSw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "loglevel": "^1.6.0", - "loglevel-plugin-prefix": "^0.8.4", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "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" - } - }, - "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 - }, - "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": "6.12.0", - "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-6.12.0.tgz", - "integrity": "sha512-UhTBZxClCsM3VjaiDp4DoSCnsa7D1QNmI2kqEBfIpyNkT3GcZhJb7L+nL0fTkzCwi7+/uLastb3/aOwH99gt0A==", - "dev": true - }, - "@wdio/repl": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-6.11.0.tgz", - "integrity": "sha512-FxrFKiTkFyELNGGVEH1uijyvNY7lUpmff6x+FGskFGZB4uSRs0rxkOMaEjxnxw7QP1zgQKr2xC7GyO03gIGRGg==", - "dev": true, - "requires": { - "@wdio/utils": "6.11.0" - } - }, - "@wdio/utils": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-6.11.0.tgz", - "integrity": "sha512-vf0sOQzd28WbI26d6/ORrQ4XKWTzSlWLm9W/K/eJO0NASKPEzR+E+Q2kaa+MJ4FKXUpjbt+Lxfo+C26TzBk7tg==", - "dev": true, - "requires": { - "@wdio/logger": "6.10.10" - } - }, "@webassemblyjs/ast": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", @@ -33359,12 +32305,6 @@ "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", "dev": true }, - "agent-base": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", - "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", - "dev": true - }, "aggregate-error": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", @@ -33704,92 +32644,6 @@ } } }, - "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": { - "async": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.1.tgz", - "integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==", - "dev": true - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "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" - } - }, - "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" - } - }, - "tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "requires": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - } - } - } - }, - "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", - "readable-stream": "^2.0.0" - } - }, "are-we-there-yet": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", @@ -35565,12 +34419,6 @@ "unset-value": "^1.0.0" } }, - "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": "6.1.0", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", @@ -35842,40 +34690,6 @@ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, - "chrome-launcher": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.13.4.tgz", - "integrity": "sha512-nnzXiDbGKjDSK6t2I+35OAPBy5Pw/39bgkb/ZAFwMhwJbdYBp6aH+vW28ZgtjdU890Q7D+3wN/tB8N66q5Gi2A==", - "dev": true, - "requires": { - "@types/node": "*", - "escape-string-regexp": "^1.0.5", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0", - "mkdirp": "^0.5.3", - "rimraf": "^3.0.2" - }, - "dependencies": { - "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" - } - }, - "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" - } - } - } - }, "chrome-trace-event": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", @@ -36105,31 +34919,6 @@ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", "dev": true }, - "compress-commons": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.0.tgz", - "integrity": "sha512-ofaaLqfraD1YRTkrRKPCrGJ1pFeDG/MVCkVVV2FNGeWquSlqw5wOrwOfPQ1xF2u+blpeWASie5EubHz+vsNIgA==", - "dev": true, - "requires": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^4.0.1", - "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" - } - } - } - }, "compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -36796,39 +35585,6 @@ } } }, - "crc-32": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", - "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", - "dev": true, - "requires": { - "exit-on-epipe": "~1.0.1", - "printj": "~1.1.0" - } - }, - "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" - } - } - } - }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", @@ -37038,12 +35794,6 @@ "fastparse": "^1.1.2" } }, - "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-tree": { "version": "1.0.0-alpha.37", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", @@ -37055,12 +35805,6 @@ "source-map": "^0.6.1" } }, - "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 - }, "css-what": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", @@ -37569,6 +36313,12 @@ "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", "dev": true }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "dev": true + }, "detect-node": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", @@ -37629,43 +36379,6 @@ } } }, - "dev-null": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dev-null/-/dev-null-0.1.1.tgz", - "integrity": "sha1-WiBc48Ky73e2I41roXnrdMag6Bg=", - "dev": true - }, - "devtools": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/devtools/-/devtools-6.12.1.tgz", - "integrity": "sha512-JyG46suEiZmld7/UVeogkCWM0zYGt+2ML/TI+SkEp+bTv9cs46cDb0pKF3glYZJA7wVVL2gC07Ic0iCxyJEnCQ==", - "dev": true, - "requires": { - "@wdio/config": "6.12.1", - "@wdio/logger": "6.10.10", - "@wdio/protocols": "6.12.0", - "@wdio/utils": "6.11.0", - "chrome-launcher": "^0.13.1", - "edge-paths": "^2.1.0", - "puppeteer-core": "^5.1.0", - "ua-parser-js": "^0.7.21", - "uuid": "^8.0.0" - }, - "dependencies": { - "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 - } - } - }, - "devtools-protocol": { - "version": "0.0.818844", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.818844.tgz", - "integrity": "sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg==", - "dev": true - }, "devtron": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/devtron/-/devtron-1.4.0.tgz", @@ -38242,27 +36955,6 @@ "stream-shift": "^1.0.0" } }, - "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" - } - } - } - }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -38446,39 +37138,6 @@ } } }, - "electron-chromedriver": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-13.0.0.tgz", - "integrity": "sha512-fID1ms8wT7qNfoKkXHNpH0ZE8/Nclb5YmkF3O0w57OxsR8S9PxgE9CJAgaSGroxBgZ+ge1i2OU0Aq/WE/e/Neg==", - "dev": true, - "requires": { - "@electron/get": "^1.12.4", - "extract-zip": "^2.0.0" - }, - "dependencies": { - "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" - } - }, - "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" - } - } - } - }, "electron-connect": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/electron-connect/-/electron-connect-0.6.3.tgz", @@ -39969,12 +38628,6 @@ } } }, - "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-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -40025,6 +38678,12 @@ } } }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true + }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -40985,12 +39644,6 @@ "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-proxy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", @@ -41076,6 +39729,12 @@ } } }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", + "dev": true + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -41384,12 +40043,6 @@ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", "dev": true }, - "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", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -41823,32 +40476,12 @@ "micromatch": "^3.1.10" } }, - "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": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, - "https-proxy-agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", - "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", - "dev": true, - "requires": { - "agent-base": "5", - "debug": "4" - } - }, "humanize-plus": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/humanize-plus/-/humanize-plus-1.8.2.tgz", @@ -42962,6 +41595,12 @@ } } }, + "jpeg-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.3.tgz", + "integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==", + "dev": true + }, "jquery": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", @@ -43154,15 +41793,6 @@ "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==" }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - } - }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -43181,33 +41811,6 @@ "immediate": "~3.0.5" } }, - "lighthouse-logger": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.2.0.tgz", - "integrity": "sha512-wzUvdIeJZhRsG6gpZfmSCfysaxNEr43i+QT+Hie94wvHDKFLi4n7C2GqZ4sTC+PH5b5iktmXJvU87rWvhP3lHw==", - "dev": true, - "requires": { - "debug": "^2.6.8", - "marky": "^1.2.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -43291,76 +41894,22 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "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.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "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.escaperegexp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" }, - "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.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" }, - "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.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 - }, "logalot": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz", @@ -43391,12 +41940,6 @@ "integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA==", "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 - }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -43547,12 +42090,6 @@ "unquote": "^1.1.0" } }, - "marky": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.2.tgz", - "integrity": "sha512-k1dB2HNeaNyORco8ulVEhctyEGkKHb2YWAhDsxeFlW2nROIirsctBYzKwwS3Vza+sKTS1zO4Z+n9/+9WbGLIxQ==", - "dev": true - }, "matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", @@ -44244,8 +42781,7 @@ "version": "2.14.1", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "dev": true, - "optional": true + "dev": true }, "nanoid": { "version": "3.1.20", @@ -44272,6 +42808,12 @@ "to-regex": "^3.0.1" } }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, "native-url": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/native-url/-/native-url-0.2.6.tgz", @@ -44329,6 +42871,15 @@ } } }, + "node-abi": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "dev": true, + "requires": { + "semver": "^5.4.1" + } + }, "node-addon-api": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", @@ -44408,6 +42959,12 @@ "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", "devOptional": true }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", + "dev": true + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -45345,6 +43902,98 @@ } } }, + "playwright": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.15.2.tgz", + "integrity": "sha512-+Z+7ckihyxR6rK5q8DWC6eUbKARfXpyxpjNcoJfgwSr64lAOzjhyFQiPC/JkdIqhsLgZjxpWfl1S7fLb+wPkgA==", + "dev": true, + "requires": { + "commander": "^6.1.0", + "debug": "^4.1.1", + "extract-zip": "^2.0.1", + "https-proxy-agent": "^5.0.0", + "jpeg-js": "^0.4.2", + "mime": "^2.4.6", + "pngjs": "^5.0.0", + "progress": "^2.0.3", + "proper-lockfile": "^4.1.1", + "proxy-from-env": "^1.1.0", + "rimraf": "^3.0.2", + "stack-utils": "^2.0.3", + "ws": "^7.4.6", + "yazl": "^2.5.1" + }, + "dependencies": { + "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" + } + }, + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "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" + } + }, + "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" + } + }, + "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" + } + }, + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "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" + } + }, + "ws": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", + "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "dev": true, + "requires": {} + } + } + }, "plist": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.2.tgz", @@ -45366,6 +44015,12 @@ } } }, + "pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "dev": true + }, "pngquant-bin": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/pngquant-bin/-/pngquant-bin-5.0.2.tgz", @@ -45662,6 +44317,29 @@ "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", "dev": true }, + "prebuild-install": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz", + "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==", + "dev": true, + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.7.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + } + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -45690,12 +44368,6 @@ "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", "dev": true }, - "printj": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", - "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==", - "dev": true - }, "prismjs": { "version": "1.23.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz", @@ -45782,6 +44454,17 @@ "warning": "^4.0.0" } }, + "proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, "property-information": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", @@ -45895,74 +44578,6 @@ "escape-goat": "^2.0.0" } }, - "puppeteer-core": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-5.5.0.tgz", - "integrity": "sha512-tlA+1n+ziW/Db03hVV+bAecDKse8ihFRXYiEypBe9IlLRvOCzYFG6qrCMBYK34HO/Q/Ecjc+tvkHRAfLVH+NgQ==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "devtools-protocol": "0.0.818844", - "extract-zip": "^2.0.0", - "https-proxy-agent": "^4.0.0", - "node-fetch": "^2.6.1", - "pkg-dir": "^4.2.0", - "progress": "^2.0.1", - "proxy-from-env": "^1.0.0", - "rimraf": "^3.0.2", - "tar-fs": "^2.0.0", - "unbzip2-stream": "^1.3.3", - "ws": "^7.2.3" - }, - "dependencies": { - "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" - } - }, - "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" - } - }, - "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" - } - }, - "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" - } - }, - "ws": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", - "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", - "dev": true, - "requires": {} - } - } - }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -45997,12 +44612,6 @@ "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", "dev": true }, - "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 - }, "raf-schd": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", @@ -46980,15 +45589,6 @@ "util-deprecate": "~1.0.1" } }, - "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": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", @@ -47263,12 +45863,6 @@ "path-parse": "^1.0.6" } }, - "resolve-alpn": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.1.2.tgz", - "integrity": "sha512-8OyfzhAtA32LVUsJSke3auIyINcwdh5l3cvYKdKO0nvsYSKuiLfTM5i78PJswFPT8y6cPW+L1v6/hE95chcpDA==", - "dev": true - }, "resolve-cwd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", @@ -47317,23 +45911,6 @@ "lowercase-keys": "^1.0.0" } }, - "resq": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/resq/-/resq-1.10.0.tgz", - "integrity": "sha512-hCUd0xMalqtPDz4jXIqs0M5Wnv/LZXN8h7unFOo4/nvExT9dDPbhwd3udRxLlp0HgBnHcV009UlduE9NZi7A6w==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1" - }, - "dependencies": { - "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 - } - } - }, "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", @@ -47352,12 +45929,6 @@ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, - "rgb2hex": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.3.tgz", - "integrity": "sha512-clEe0m1xv+Tva1B/TOepuIcvLAxP0U+sCDfgt1SX1HmI2Ahr5/Cd/nzJM1e78NKVtWdoo0s33YehpFA8UfIShQ==", - "dev": true - }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -47401,6 +45972,17 @@ } } }, + "robotjs": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/robotjs/-/robotjs-0.6.0.tgz", + "integrity": "sha512-6pRWI3d+CBZqCXT/rsJfabbZoELua+jTeXilG27F8Jvix/J2BYZ0O7Tly2WCmXyqw5xYdCvOwvCeLRHEtXkt4w==", + "dev": true, + "requires": { + "nan": "^2.14.0", + "node-abi": "^2.13.0", + "prebuild-install": "^5.3.3" + } + }, "run-parallel": { "version": "1.1.10", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", @@ -47903,6 +46485,40 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true + }, + "simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "dev": true, + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + }, + "dependencies": { + "decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "dev": true, + "requires": { + "mimic-response": "^2.0.0" + } + }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "dev": true + } + } + }, "sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -48217,152 +46833,6 @@ } } }, - "spectron": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/spectron/-/spectron-15.0.0.tgz", - "integrity": "sha512-eErHqymkEVb6H+LPZQoDYvWEv93o3nhxL7HXXdmC61ncV0jBckh8x3Qt6j+As2c1n0C/hKG9A2H1NnwGwD6agg==", - "dev": true, - "requires": { - "@electron/remote": "^1.1.0", - "dev-null": "^0.1.1", - "electron-chromedriver": "^13.0.0", - "got": "^11.8.0", - "split": "^1.0.1", - "webdriverio": "^6.9.1" - }, - "dependencies": { - "@sindresorhus/is": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", - "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", - "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" - } - }, - "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" - } - }, - "decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "requires": { - "mimic-response": "^3.1.0" - } - }, - "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 - }, - "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" - } - }, - "got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", - "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.1", - "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" - } - }, - "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 - }, - "keyv": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", - "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", - "dev": true, - "requires": { - "json-buffer": "3.0.1" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - }, - "mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true - }, - "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 - }, - "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 - }, - "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" - } - } - } - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "requires": { - "through": "2" - } - }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -48452,6 +46922,23 @@ "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", "dev": true }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, "stackframe": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", @@ -49100,7 +47587,8 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "dev": true, + "optional": true }, "through2": { "version": "2.0.5", @@ -49366,7 +47854,6 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.0.1" } @@ -49424,12 +47911,6 @@ "integrity": "sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew==", "dev": true }, - "ua-parser-js": { - "version": "0.7.21", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz", - "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==", - "dev": true - }, "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", @@ -49453,6 +47934,7 @@ "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "dev": true, + "optional": true, "requires": { "buffer": "^5.2.1", "through": "^2.3.8" @@ -49463,6 +47945,7 @@ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, + "optional": true, "requires": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -50120,191 +48603,6 @@ "minimalistic-assert": "^1.0.0" } }, - "webdriver": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-6.12.1.tgz", - "integrity": "sha512-3rZgAj9o2XHp16FDTzvUYaHelPMSPbO1TpLIMUT06DfdZjNYIzZiItpIb/NbQDTPmNhzd9cuGmdI56WFBGY2BA==", - "dev": true, - "requires": { - "@wdio/config": "6.12.1", - "@wdio/logger": "6.10.10", - "@wdio/protocols": "6.12.0", - "@wdio/utils": "6.11.0", - "got": "^11.0.2", - "lodash.merge": "^4.6.1" - }, - "dependencies": { - "@sindresorhus/is": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", - "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", - "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" - } - }, - "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" - } - }, - "decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "requires": { - "mimic-response": "^3.1.0" - } - }, - "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 - }, - "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" - } - }, - "got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", - "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.1", - "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" - } - }, - "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 - }, - "keyv": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", - "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", - "dev": true, - "requires": { - "json-buffer": "3.0.1" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - }, - "mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true - }, - "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 - }, - "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 - }, - "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" - } - } - } - }, - "webdriverio": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-6.12.1.tgz", - "integrity": "sha512-Nx7ge0vTWHVIRUbZCT+IuMwB5Q0Q5nLlYdgnmmJviUKLuc3XtaEBkYPTbhHWHgSBXsPZMIc023vZKNkn+6iyeQ==", - "dev": true, - "requires": { - "@types/puppeteer-core": "^5.4.0", - "@wdio/config": "6.12.1", - "@wdio/logger": "6.10.10", - "@wdio/repl": "6.11.0", - "@wdio/utils": "6.11.0", - "archiver": "^5.0.0", - "atob": "^2.1.2", - "css-shorthand-properties": "^1.1.1", - "css-value": "^0.0.1", - "devtools": "6.12.1", - "fs-extra": "^9.0.1", - "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": "^5.1.0", - "resq": "^1.9.1", - "rgb2hex": "0.2.3", - "serialize-error": "^8.0.0", - "webdriver": "6.12.1" - }, - "dependencies": { - "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" - } - }, - "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 - } - } - }, "webpack": { "version": "4.44.2", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", @@ -51046,6 +49344,12 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "dev": true + }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", @@ -51298,35 +49602,20 @@ "fd-slicer": "~1.1.0" } }, + "yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3" + } + }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true - }, - "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" - } - } - } } } } diff --git a/package.json b/package.json index b92d9a47..8dec84b9 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "build:main": "webpack-cli --bail --config webpack.config.main.js", "build:renderer": "webpack-cli --bail --config webpack.config.renderer.js", "build-prod": "npm-run-all build:*", + "build-robotjs": "npm rebuild --runtime=electron --target=14.1.0 --disturl=https://atom.io/download/atom-shell --abi=83", "start": "electron dist/ --disable-dev-mode", "restart": "npm run build && npm run start", "storybook": "start-storybook -p 9001 -c src/.storybook", @@ -38,7 +39,8 @@ "watch:main": "node scripts/watch_main_and_preload.js", "watch:renderer": "webpack-dev-server --config webpack.config.renderer.js", "test": "npm-run-all lint:js test:unit test:e2e", - "test:e2e": "cross-env NODE_ENV=test npm-run-all build test:e2e:build test:e2e:run", + "test:e2e": "cross-env NODE_ENV=test npm-run-all build build-robotjs test:e2e:build test:e2e:run", + "test:e2e:nobuild": "cross-env NODE_ENV=test npm-run-all test:e2e:build test:e2e:run", "test:e2e:build": "webpack-cli --bail --config webpack.config.test.js", "test:e2e:run": "electron-mocha -r @babel/register --reporter mocha-circleci-reporter dist/tests/e2e_bundle.js", "test:unit": "npm-run-all test:unit:build test:unit:run", @@ -111,9 +113,10 @@ "mocha": "^5.2.0", "mocha-circleci-reporter": "0.0.3", "npm-run-all": "^4.1.5", + "playwright": "^1.15.2", + "robotjs": "^0.6.0", "sass-loader": "^10.2.0", "shebang-loader": "^0.0.1", - "spectron": "^15.0.0", "style-loader": "^2.0.0", "typescript": "^4.3.4", "url-loader": "^1.1.2", diff --git a/src/common/communication.ts b/src/common/communication.ts index 379ac335..764e2b4c 100644 --- a/src/common/communication.ts +++ b/src/common/communication.ts @@ -100,3 +100,6 @@ export const BROWSER_HISTORY_PUSH = 'browser-history-push'; export const APP_LOGGED_IN = 'app-logged-in'; export const GET_AVAILABLE_SPELL_CHECKER_LANGUAGES = 'get-available-spell-checker-languages'; + +export const GET_VIEW_NAME = 'get-view-name'; +export const GET_VIEW_WEBCONTENTS_ID = 'get-view-webcontents-id'; diff --git a/src/main/notifications/index.ts b/src/main/notifications/index.ts index dd4a812b..5a493a2e 100644 --- a/src/main/notifications/index.ts +++ b/src/main/notifications/index.ts @@ -51,6 +51,7 @@ export function displayMention(title: string, body: string, channel: {id: string }); mention.on('click', () => { + log.info('notification click', serverName, mention); if (serverName) { windowManager.switchTab(serverName, TAB_MESSAGING); webcontents.send('notification-clicked', {channel, teamId, url}); diff --git a/src/main/preload/mattermost.js b/src/main/preload/mattermost.js index ec422f56..b58c6b2d 100644 --- a/src/main/preload/mattermost.js +++ b/src/main/preload/mattermost.js @@ -6,7 +6,7 @@ /* eslint-disable no-magic-numbers */ -import {ipcRenderer, webFrame} from 'electron'; +import {contextBridge, ipcRenderer, webFrame} from 'electron'; // I've filed an issue in electron-log https://github.com/megahertz/electron-log/issues/267 // we'll be able to use it again if there is a workaround for the 'os' import @@ -23,6 +23,8 @@ import { CLOSE_TEAMS_DROPDOWN, BROWSER_HISTORY_PUSH, APP_LOGGED_IN, + GET_VIEW_NAME, + GET_VIEW_WEBCONTENTS_ID, } from 'common/communication'; const UNREAD_COUNT_INTERVAL = 1000; @@ -36,6 +38,13 @@ let shouldSendNotifications; console.log('Preload initialized'); +if (process.env.NODE_ENV === 'test') { + contextBridge.exposeInMainWorld('testHelper', { + getViewName: () => ipcRenderer.invoke(GET_VIEW_NAME), + getWebContentsId: () => ipcRenderer.invoke(GET_VIEW_WEBCONTENTS_ID), + }); +} + ipcRenderer.invoke('get-app-version').then(({name, version}) => { appVersion = version; appName = name; diff --git a/src/main/views/MattermostView.ts b/src/main/views/MattermostView.ts index 99121688..ba873df0 100644 --- a/src/main/views/MattermostView.ts +++ b/src/main/views/MattermostView.ts @@ -77,13 +77,11 @@ export class MattermostView extends EventEmitter { this.options = Object.assign({}, options); this.options.webPreferences = { nativeWindowOpen: true, - contextIsolation: process.env.NODE_ENV !== 'test', preload, additionalArguments: [ `version=${app.getVersion()}`, `appName=${app.name}`, ], - nodeIntegration: process.env.NODE_ENV === 'test', ...options.webPreferences, }; this.isVisible = false; @@ -273,12 +271,7 @@ export class MattermostView extends EventEmitter { } getWebContents = () => { - if (this.status === Status.READY) { - return this.view.webContents; - } else if (this.window) { - return this.window.webContents; // if it's not ready you are looking at the renderer process - } - return WindowManager.getMainWindow()?.webContents; + return this.view.webContents; } handleInputEvents = (_: Event, input: Input) => { diff --git a/src/main/views/modalView.ts b/src/main/views/modalView.ts index 5358a20e..ad64ff75 100644 --- a/src/main/views/modalView.ts +++ b/src/main/views/modalView.ts @@ -32,9 +32,7 @@ export class ModalView { log.info(`preloading with ${preload}`); this.view = new BrowserView({webPreferences: { nativeWindowOpen: true, - contextIsolation: process.env.NODE_ENV !== 'test', preload, - nodeIntegration: process.env.NODE_ENV === 'test', // Workaround for this issue: https://github.com/electron/electron/issues/30993 // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/src/main/views/teamDropdownView.ts b/src/main/views/teamDropdownView.ts index 024d50bd..1449e3d1 100644 --- a/src/main/views/teamDropdownView.ts +++ b/src/main/views/teamDropdownView.ts @@ -46,9 +46,7 @@ export default class TeamDropdownView { const preload = getLocalPreload('dropdown.js'); this.view = new BrowserView({webPreferences: { nativeWindowOpen: true, - contextIsolation: process.env.NODE_ENV !== 'test', preload, - nodeIntegration: process.env.NODE_ENV === 'test', // Workaround for this issue: https://github.com/electron/electron/issues/30993 // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/src/main/views/viewManager.ts b/src/main/views/viewManager.ts index ecff858a..a532a520 100644 --- a/src/main/views/viewManager.ts +++ b/src/main/views/viewManager.ts @@ -295,8 +295,6 @@ export class ViewManager { const urlView = new BrowserView({ webPreferences: { nativeWindowOpen: true, - contextIsolation: process.env.NODE_ENV !== 'test', - nodeIntegration: process.env.NODE_ENV === 'test', // Workaround for this issue: https://github.com/electron/electron/issues/30993 // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/src/main/views/webContentEvents.ts b/src/main/views/webContentEvents.ts index a2484fd8..06c7f208 100644 --- a/src/main/views/webContentEvents.ts +++ b/src/main/views/webContentEvents.ts @@ -169,8 +169,6 @@ const generateNewWindowListener = (getServersFunction: () => TeamWithTabs[], spe center: true, webPreferences: { nativeWindowOpen: true, - nodeIntegration: process.env.NODE_ENV === 'test', - contextIsolation: process.env.NODE_ENV !== 'test', spellcheck: (typeof spellcheck === 'undefined' ? true : spellcheck), }, }); diff --git a/src/main/windows/mainWindow.ts b/src/main/windows/mainWindow.ts index 6dc6026d..938a6ba7 100644 --- a/src/main/windows/mainWindow.ts +++ b/src/main/windows/mainWindow.ts @@ -80,8 +80,6 @@ function createMainWindow(config: CombinedConfig, options: {linuxAppIcon: string backgroundColor: '#fff', // prevents blurry text: https://electronjs.org/docs/faq#the-font-looks-blurry-what-is-this-and-what-can-i-do webPreferences: { nativeWindowOpen: true, - nodeIntegration: process.env.NODE_ENV === 'test', - contextIsolation: process.env.NODE_ENV !== 'test', disableBlinkFeatures: 'Auxclick', preload, spellcheck, diff --git a/src/main/windows/windowManager.ts b/src/main/windows/windowManager.ts index 256a14f4..0e1b96ba 100644 --- a/src/main/windows/windowManager.ts +++ b/src/main/windows/windowManager.ts @@ -2,7 +2,7 @@ // See LICENSE.txt for license information. import path from 'path'; -import {app, BrowserWindow, nativeImage, systemPreferences, ipcMain, IpcMainEvent} from 'electron'; +import {app, BrowserWindow, nativeImage, systemPreferences, ipcMain, IpcMainEvent, IpcMainInvokeEvent} from 'electron'; import log from 'electron-log'; import {CombinedConfig} from 'types/config'; @@ -18,6 +18,8 @@ import { UPDATE_SHORTCUT_MENU, BROWSER_HISTORY_PUSH, APP_LOGGED_IN, + GET_VIEW_NAME, + GET_VIEW_WEBCONTENTS_ID, } from 'common/communication'; import urlUtils from 'common/utils/url'; @@ -54,6 +56,8 @@ ipcMain.on(REACT_APP_INITIALIZED, handleReactAppInitialized); ipcMain.on(LOADING_SCREEN_ANIMATION_FINISHED, handleLoadingScreenAnimationFinished); ipcMain.on(BROWSER_HISTORY_PUSH, handleBrowserHistoryPush); ipcMain.on(APP_LOGGED_IN, handleAppLoggedIn); +ipcMain.handle(GET_VIEW_NAME, handleGetViewName); +ipcMain.handle(GET_VIEW_WEBCONTENTS_ID, handleGetWebContentsId); export function setConfig(data: CombinedConfig) { if (data) { @@ -585,3 +589,11 @@ export function getCurrentTeamName() { function handleAppLoggedIn(event: IpcMainEvent, viewName: string) { status.viewManager?.reloadViewIfNeeded(viewName); } + +function handleGetViewName(event: IpcMainInvokeEvent) { + return getViewNameByWebContentsId(event.sender.id); +} +function handleGetWebContentsId(event: IpcMainInvokeEvent) { + return event.sender.id; +} + diff --git a/test/modules/environment.js b/test/modules/environment.js index 6d893397..2a009539 100644 --- a/test/modules/environment.js +++ b/test/modules/environment.js @@ -7,11 +7,13 @@ const fs = require('fs'); const path = require('path'); -const Application = require('spectron').Application; +const {_electron: electron} = require('playwright'); const chai = require('chai'); const {ipcRenderer} = require('electron'); const {SHOW_SETTINGS_WINDOW} = require('../../src/common/communication'); + +const {asyncSleep} = require('./utils'); chai.should(); const sourceRootDir = path.join(__dirname, '../..'); @@ -47,27 +49,61 @@ module.exports = { }); }, + cleanDataDir() { + try { + fs.rmdirSync(userDataDir, {recursive: true}); + } catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.error(err); + } + } + }, + createTestUserDataDir() { if (!fs.existsSync(userDataDir)) { fs.mkdirSync(userDataDir); } }, - getSpectronApp() { + async getApp() { const options = { - path: electronBinaryPath, + executablePath: electronBinaryPath, args: [`${path.join(sourceRootDir, 'dist')}`, `--data-dir=${userDataDir}`, '--disable-dev-mode'], - chromeDriverArgs: [], }; - if (process.env.MM_DEBUG_SETTINGS) { - options.chromeDriverLogPath = './chromedriverlog.txt'; - } - if (process.platform === 'darwin' || process.platform === 'linux') { - // on a mac, debbuging port might conflict with other apps - // this changes the default debugging port so chromedriver can run without issues. - options.chromeDriverArgs.push('remote-debugging-port=9222'); - } - return new Application(options); + + // if (process.env.MM_DEBUG_SETTINGS) { + // options.chromeDriverLogPath = './chromedriverlog.txt'; + // } + // if (process.platform === 'darwin' || process.platform === 'linux') { + // // on a mac, debbuging port might conflict with other apps + // // this changes the default debugging port so chromedriver can run without issues. + // options.chromeDriverArgs.push('remote-debugging-port=9222'); + //} + return electron.launch(options).then(async (app) => { + // Make sure the app has time to fully load + await asyncSleep(1000); + return app; + }); + }, + + async getServerMap(app) { + const map = {}; + await Promise.all(app.windows().map(async (win) => { + return win.evaluate(async () => { + if (!window.testHelper) { + return null; + } + const name = await window.testHelper.getViewName(); + const webContentsId = await window.testHelper.getWebContentsId(); + return {viewName: name, webContentsId}; + }).then((result) => { + if (result) { + map[result.viewName] = {win, webContentsId: result.webContentsId}; + } + }); + })); + return map; }, addClientCommands(client) { diff --git a/test/specs/app_test.js b/test/specs/app_test.js index 3d18a2c7..0d18393f 100644 --- a/test/specs/app_test.js +++ b/test/specs/app_test.js @@ -2,153 +2,50 @@ // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -// TODO: Commenting out until Spectron is upgraded for Electron v14 +'use strict'; -// 'use strict'; +const env = require('../modules/environment'); -// const fs = require('fs'); +describe('application', function desc() { + this.timeout(30000); -// const env = require('../modules/environment'); + beforeEach(async () => { + env.createTestUserDataDir(); + env.cleanTestConfig(); + this.app = await env.getApp(); + }); -// describe('application', function desc() { -// this.timeout(30000); + afterEach(async () => { + if (this.app) { + await this.app.close(); + } + }); -// beforeEach(() => { -// env.createTestUserDataDir(); -// env.cleanTestConfig(); -// this.app = env.getSpectronApp(); -// return this.app.start(); -// }); + it('should show the new server modal when no servers exist', async () => { + const newServerModal = this.app.windows().find((window) => window.url().includes('newServer')); + const modalTitle = await newServerModal.innerText('#newServerModal .modal-title'); + modalTitle.should.equal('Add Server'); + }); -// afterEach(async () => { -// if (this.app && this.app.isRunning()) { -// await this.app.stop(); -// } -// }); + it('should show no servers configured in dropdown when no servers exist', async () => { + const mainWindow = this.app.windows().find((window) => window.url().includes('index')); + const dropdownButtonText = await mainWindow.innerText('.TeamDropdownButton'); + dropdownButtonText.should.equal('No servers configured'); + }); -// // it('should show two windows if there is no config file', async () => { -// // await this.app.client.waitUntilWindowLoaded(); -// // const count = await this.app.client.getWindowCount(); -// // count.should.equal(2); -// // const opened = await this.app.browserWindow.isDevToolsOpened(); -// // opened.should.be.false; + it('should be stopped when the app instance already exists', (done) => { + const secondApp = env.getApp(); -// // const visible = await this.app.browserWindow.isVisible(); -// // visible.should.be.true; -// // }); - -// if (process.platform === 'darwin') { -// it.skip('should show closed window with cmd+tab', async () => { -// // Unable to utilize Command key press due to: https://bugs.chromium.org/p/chromedriver/issues/detail?id=3023#c2 -// await this.app.client.waitUntilWindowLoaded(); -// await this.app.client.keys(['Meta', 'w']); -// let visible = await this.app.browserWindow.isVisible(); -// visible.should.be.false; - -// this.app.client.keys(['Meta', 'Tab']); -// visible = await this.app.browserWindow.isVisible(); -// visible.should.be.true; -// }); -// } - -// it.skip('should restore window bounds', async () => { -// // bounds seems to be incorrectly calculated in some environments -// // - Windows 10: OK -// // - CircleCI: NG -// const expectedBounds = {x: 100, y: 200, width: 300, height: 400}; -// fs.writeFileSync(env.boundsInfoPath, JSON.stringify(expectedBounds)); -// await this.app.restart(); -// const bounds = await this.app.browserWindow.getBounds(); -// bounds.should.deep.equal(expectedBounds); -// }); - -// it('should NOT restore window bounds if the origin is located on outside of viewarea', async () => { -// // bounds seems to be incorrectly calculated in some environments (e.g. CircleCI) -// // - Windows 10: OK -// // - CircleCI: NG -// fs.writeFileSync(env.boundsInfoPath, JSON.stringify({x: -100000, y: 200, width: 300, height: 400})); -// await this.app.restart(); -// let bounds = await this.app.browserWindow.getBounds(); -// bounds.x.should.satisfy((x) => (x > -10000)); - -// fs.writeFileSync(env.boundsInfoPath, JSON.stringify({x: 100, y: 200000, width: 300, height: 400})); -// await this.app.restart(); -// bounds = await this.app.browserWindow.getBounds(); -// bounds.y.should.satisfy((y) => (y < 10000)); -// }); - -// // it('should show settings.html when there is no config file', async () => { -// // await this.app.client.waitUntilWindowLoaded(); -// // await this.app.client.pause(1000); -// // const url = await this.app.client.getUrl(); -// // url.should.match(/\/settings.html$/); - -// // const existing = await this.app.client.isExisting('#newServerModal'); -// // existing.should.equal(true); -// // }); - -// // it('should show index.html when there is config file', async () => { -// // const config = { -// // version: 2, -// // teams: [{ -// // name: 'example', -// // url: env.mattermostURL, -// // order: 0, -// // }, { -// // name: 'github', -// // url: 'https://github.com/', -// // order: 1, -// // }], -// // showTrayIcon: false, -// // trayIconTheme: 'light', -// // minimizeToTray: false, -// // notifications: { -// // flashWindow: 0, -// // bounceIcon: false, -// // bounceIconType: 'informational', -// // }, -// // showUnreadBadge: true, -// // useSpellChecker: true, -// // enableHardwareAcceleration: true, -// // autostart: true, -// // darkMode: false, -// // }; -// // fs.writeFileSync(env.configFilePath, JSON.stringify(config)); -// // await this.app.restart(); - -// // const url = await this.app.client.getUrl(); -// // url.should.match(/\/index.html$/); -// // }); - -// // it('should upgrade v0 config file', async () => { -// // const Config = require('../../src/common/config').default; -// // const newConfig = new Config(env.configFilePath); -// // const oldConfig = { -// // url: env.mattermostURL, -// // }; -// // fs.writeFileSync(env.configFilePath, JSON.stringify(oldConfig)); -// // await this.app.restart(); - -// // const url = await this.app.client.getUrl(); -// // url.should.match(/\/index.html$/); - -// // const str = fs.readFileSync(env.configFilePath, 'utf8'); -// // const upgradedConfig = JSON.parse(str); -// // upgradedConfig.version.should.equal(newConfig.defaultData.version); -// // }); - -// // it.skip('should be stopped when the app instance already exists', (done) => { -// // const secondApp = env.getSpectronApp(); - -// // // In the correct case, 'start().then' is not called. -// // // So need to use setTimeout in order to finish this test. -// // const timer = setTimeout(() => { -// // done(); -// // }, 3000); -// // secondApp.start().then(() => { -// // clearTimeout(timer); -// // return secondApp.stop(); -// // }).then(() => { -// // done(new Error('Second app instance exists')); -// // }); -// }); + // In the correct case, 'start().then' is not called. + // So need to use setTimeout in order to finish this test. + const timer = setTimeout(() => { + done(); + }, 3000); + secondApp.then(() => { + clearTimeout(timer); + return secondApp.close(); + }).then(() => { + done(new Error('Second app instance exists')); + }); + }); +}); diff --git a/test/specs/browser/index_test.js b/test/specs/browser/index_test.js index df290991..5e17006a 100644 --- a/test/specs/browser/index_test.js +++ b/test/specs/browser/index_test.js @@ -5,8 +5,10 @@ const fs = require('fs'); -const http = require('http'); -const path = require('path'); +const robot = require('robotjs'); + +// const http = require('http'); +// const path = require('path'); const env = require('../../modules/environment'); const {asyncSleep} = require('../../modules/utils'); @@ -15,15 +17,51 @@ describe('renderer/index.html', function desc() { this.timeout(30000); const config = { - version: 2, + version: 3, teams: [{ name: 'example', url: env.mattermostURL, order: 0, + tabs: [ + { + name: 'TAB_MESSAGING', + order: 0, + isOpen: true, + }, + { + name: 'TAB_FOCALBOARD', + order: 1, + isOpen: true, + }, + { + name: 'TAB_PLAYBOOKS', + order: 2, + isOpen: true, + }, + ], + lastActiveTab: 0, }, { name: 'github', url: 'https://github.com/', order: 1, + tabs: [ + { + name: 'TAB_MESSAGING', + order: 0, + isOpen: true, + }, + { + name: 'TAB_FOCALBOARD', + order: 1, + isOpen: true, + }, + { + name: 'TAB_PLAYBOOKS', + order: 2, + isOpen: true, + }, + ], + lastActiveTab: 0, }], showTrayIcon: false, trayIconTheme: 'light', @@ -38,178 +76,123 @@ describe('renderer/index.html', function desc() { enableHardwareAcceleration: true, autostart: true, darkMode: false, + lastActiveTeam: 0, + spellCheckerLocales: [], }; - const serverPort = 8181; - - before(() => { - function serverCallback(req, res) { - res.writeHead(200, { - 'Content-Type': 'text/html', - }); - res.end(fs.readFileSync(path.resolve(env.sourceRootDir, 'test/modules/test.html'), 'utf-8')); - } - this.server = http.createServer(serverCallback).listen(serverPort, '127.0.0.1'); - }); - beforeEach(async () => { + env.createTestUserDataDir(); + env.cleanTestConfig(); fs.writeFileSync(env.configFilePath, JSON.stringify(config)); await asyncSleep(1000); - this.app = env.getSpectronApp(); - await this.app.start(); + this.app = await env.getApp(); }); afterEach(async () => { - if (this.app && this.app.isRunning()) { - await this.app.stop(); + if (this.app) { + await this.app.close(); } }); - after((done) => { - this.server.close(done); + it('should set src of browser view from config file', async () => { + const firstServer = this.app.windows().find((window) => window.url() === config.teams[0].url); + const secondServer = this.app.windows().find((window) => window.url() === config.teams[1].url); + + firstServer.should.not.be.null; + secondServer.should.not.be.null; }); - // it('should set src of webview from config file', async () => { - // const src0 = await this.app.client.getAttribute('#mattermostView0', 'src'); - // src0.should.equal(config.teams[0].url); + it('should set name of menu item from config file', async () => { + const mainWindow = this.app.windows().find((window) => window.url().includes('index')); + const dropdownView = this.app.windows().find((window) => window.url().includes('dropdown')); + await mainWindow.click('.TeamDropdownButton'); + const firstMenuItem = await dropdownView.innerText('.TeamDropdown button.TeamDropdown__button:nth-child(1) span'); + const secondMenuItem = await dropdownView.innerText('.TeamDropdown button.TeamDropdown__button:nth-child(2) span'); - // const src1 = await this.app.client.getAttribute('#mattermostView1', 'src'); - // src1.should.equal(config.teams[1].url); + firstMenuItem.should.equal(config.teams[0].name); + secondMenuItem.should.equal(config.teams[1].name); + }); - // const existing = await this.app.client.isExisting('#mattermostView2'); - // existing.should.be.false; - // }); + it('should only show dropdown when button is clicked', async () => { + const mainWindow = await this.app.firstWindow(); + const browserWindow = await this.app.browserWindow(mainWindow); + const mainView = this.app.windows().find((window) => window.url().includes('index')); - // it('should set name of tab from config file', async () => { - // const tabName0 = await this.app.client.getText('#teamTabItem0'); - // tabName0.should.equal(config.teams[0].name); + let dropdownHeight = await browserWindow.evaluate((window) => window.getBrowserViews().find((view) => view.webContents.getURL().includes('dropdown')).getBounds().height); + dropdownHeight.should.equal(0); - // const tabName1 = await this.app.client.getText('#teamTabItem1'); - // tabName1.should.equal(config.teams[1].name); - // }); + await mainView.click('.TeamDropdownButton'); + dropdownHeight = await browserWindow.evaluate((window) => window.getBrowserViews().find((view) => view.webContents.getURL().includes('dropdown')).getBounds().height); + dropdownHeight.should.be.greaterThan(0); - // it('should show only the selected team', () => { - // return this.app.client. - // waitForVisible('#mattermostView0', 2000). - // waitForVisible('#mattermostView1', 2000, true). - // click('#teamTabItem1'). - // waitForVisible('#mattermostView1', 2000). - // waitForVisible('#mattermostView0', 2000, true); - // }); + await mainView.click('.TabBar'); + dropdownHeight = await browserWindow.evaluate((window) => window.getBrowserViews().find((view) => view.webContents.getURL().includes('dropdown')).getBounds().height); + dropdownHeight.should.equal(0); + }); - // validation now prevents incorrect url's from being used - // it.skip('should show error when using incorrect URL', async () => { - // this.timeout(30000); - // fs.writeFileSync(env.configFilePath, JSON.stringify({ - // version: 2, - // teams: [{ - // name: 'error_1', - // url: 'http://false', - // order: 0, - // }], - // })); - // await this.app.restart(); - // return this.app.client. - // waitForVisible('#mattermostView0-fail', 20000); - // }); + it('should show only the selected team', async () => { + const mainWindow = await this.app.firstWindow(); + const browserWindow = await this.app.browserWindow(mainWindow); - // it('shouldn\'t set window title by using webview\'s one', async () => { - // fs.writeFileSync(env.configFilePath, JSON.stringify({ - // version: 2, - // teams: [{ - // name: 'title_test', - // url: `http://localhost:${serverPort}`, - // order: 0, - // }], - // })); - // await this.app.restart(); - // await this.app.client.pause(2000); - // const windowTitle = await this.app.browserWindow.getTitle(); - // windowTitle.should.equal('Mattermost Desktop App'); - // }); + let firstViewIsAttached = await browserWindow.evaluate((window, url) => Boolean(window.getBrowserViews().find((view) => view.webContents.getURL() === url)), env.mattermostURL); + firstViewIsAttached.should.be.true; + let secondViewIsAttached = await browserWindow.evaluate((window) => Boolean(window.getBrowserViews().find((view) => view.webContents.getURL() === 'https://github.com/'))); + secondViewIsAttached.should.be.false; - // Skip because it's very unstable in CI - // it.skip('should update window title when the activated tab\'s title is updated', async () => { - // fs.writeFileSync(env.configFilePath, JSON.stringify({ - // version: 2, - // teams: [{ - // name: 'title_test_0', - // url: `http://localhost:${serverPort}`, - // order: 0, - // }, { - // name: 'title_test_1', - // url: `http://localhost:${serverPort}`, - // order: 1, - // }], - // })); - // await this.app.restart(); - // await this.app.client.pause(500); + const mainView = this.app.windows().find((window) => window.url().includes('index')); + const dropdownView = this.app.windows().find((window) => window.url().includes('dropdown')); + await mainView.click('.TeamDropdownButton'); + await dropdownView.click('.TeamDropdown button.TeamDropdown__button:nth-child(2)'); - // // Note: Indices of webview are correct. - // // Somehow they are swapped. - // await this.app.client. - // windowByIndex(2). - // execute(() => { - // document.title = 'Title 0'; - // }); - // await this.app.client.windowByIndex(0).pause(500); - // let windowTitle = await this.app.browserWindow.getTitle(); - // windowTitle.should.equal('Title 0'); + firstViewIsAttached = await browserWindow.evaluate((window, url) => Boolean(window.getBrowserViews().find((view) => view.webContents.getURL() === url)), env.mattermostURL); + firstViewIsAttached.should.be.false; + secondViewIsAttached = await browserWindow.evaluate((window) => Boolean(window.getBrowserViews().find((view) => view.webContents.getURL() === 'https://github.com/'))); + secondViewIsAttached.should.be.true; + }); - // await this.app.client. - // windowByIndex(1). - // execute(() => { - // document.title = 'Title 1'; - // }); - // await this.app.client.windowByIndex(0).pause(500); - // windowTitle = await this.app.browserWindow.getTitle(); - // windowTitle.should.equal('Title 0'); - // }); + it('should open the new server prompt after clicking the add button', async () => { + const mainWindow = this.app.windows().find((window) => window.url().includes('index')); + const dropdownView = this.app.windows().find((window) => window.url().includes('dropdown')); + await mainWindow.click('.TeamDropdownButton'); + await dropdownView.click('.TeamDropdown__button.addServer'); - // Skip because it's very unstable in CI - // it.skip('should update window title when a tab is selected', async () => { - // fs.writeFileSync(env.configFilePath, JSON.stringify({ - // version: 2, - // teams: [{ - // name: 'title_test_0', - // url: `http://localhost:${serverPort}`, - // order: 0, - // }, { - // name: 'title_test_1', - // url: `http://localhost:${serverPort}`, - // order: 1, - // }], - // })); - // await this.app.restart(); + const newServerModal = await this.app.waitForEvent('window', { + predicate: (window) => window.url().includes('newServer'), + }); + const modalTitle = await newServerModal.innerText('#newServerModal .modal-title'); + modalTitle.should.equal('Add Server'); + }); - // // Note: Indices of webview are correct. - // // Somehow they are swapped. - // await this.app.client.pause(500); + it('should switch to servers when keyboard shortcuts are pressed', async () => { + const mainWindow = this.app.windows().find((window) => window.url().includes('index')); - // await this.app.client. - // windowByIndex(2). - // execute(() => { - // document.title = 'Title 0'; - // }); - // await this.app.client. - // windowByIndex(1). - // execute(() => { - // document.title = 'Title 1'; - // }); - // await this.app.client.windowByIndex(0).pause(500); + let dropdownButtonText = await mainWindow.innerText('.TeamDropdownButton'); + dropdownButtonText.should.equal('example'); - // let windowTitle = await this.app.browserWindow.getTitle(); - // windowTitle.should.equal('Title 0'); + robot.keyTap('2', ['control', 'shift']); + dropdownButtonText = await mainWindow.innerText('.TeamDropdownButton'); + dropdownButtonText.should.equal('github'); - // await this.app.client.click('#teamTabItem1').pause(500); - // windowTitle = await this.app.browserWindow.getTitle(); - // windowTitle.should.equal('Title 1'); - // }); + robot.keyTap('1', ['control', 'shift']); + dropdownButtonText = await mainWindow.innerText('.TeamDropdownButton'); + dropdownButtonText.should.equal('example'); + }); - // it('should open the new server prompt after clicking the add button', async () => { - // // See settings_test for specs that cover the actual prompt - // await this.app.client.click('#addServerButton').pause(500); - // const isModalExisting = await this.app.client.isExisting('#newServerModal'); - // isModalExisting.should.be.true; - // }); + if (process.platform !== 'darwin') { + it('should open the 3 dot menu with Alt', async () => { + const mainWindow = this.app.windows().find((window) => window.url().includes('index')); + mainWindow.should.not.be.null; + + // Settings window should open if Alt works + robot.keyTap('alt'); + robot.keyTap('enter'); + robot.keyTap('f'); + robot.keyTap('s'); + robot.keyTap('enter'); + const settingsWindow = await this.app.waitForEvent('window', { + predicate: (window) => window.url().includes('settings'), + }); + settingsWindow.should.not.be.null; + }); + } }); diff --git a/test/specs/browser/modal_test.js b/test/specs/browser/modal_test.js new file mode 100644 index 00000000..b6aebb8f --- /dev/null +++ b/test/specs/browser/modal_test.js @@ -0,0 +1,266 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +'use strict'; + +const fs = require('fs'); + +const env = require('../../modules/environment'); +const {asyncSleep} = require('../../modules/utils'); + +describe('modals', function desc() { + this.timeout(30000); + + const config = { + version: 3, + teams: [{ + name: 'example', + url: env.mattermostURL, + order: 0, + tabs: [ + { + name: 'TAB_MESSAGING', + order: 0, + isOpen: true, + }, + { + name: 'TAB_FOCALBOARD', + order: 1, + isOpen: true, + }, + { + name: 'TAB_PLAYBOOKS', + order: 2, + isOpen: true, + }, + ], + lastActiveTab: 0, + }, { + name: 'github', + url: 'https://github.com/', + order: 1, + tabs: [ + { + name: 'TAB_MESSAGING', + order: 0, + isOpen: true, + }, + { + name: 'TAB_FOCALBOARD', + order: 1, + isOpen: true, + }, + { + name: 'TAB_PLAYBOOKS', + order: 2, + isOpen: true, + }, + ], + lastActiveTab: 0, + }], + showTrayIcon: false, + trayIconTheme: 'light', + minimizeToTray: false, + notifications: { + flashWindow: 0, + bounceIcon: false, + bounceIconType: 'informational', + }, + showUnreadBadge: true, + useSpellChecker: true, + enableHardwareAcceleration: true, + autostart: true, + darkMode: false, + lastActiveTeam: 0, + spellCheckerLocales: [], + }; + + beforeEach(async () => { + env.createTestUserDataDir(); + env.cleanTestConfig(); + fs.writeFileSync(env.configFilePath, JSON.stringify(config)); + await asyncSleep(1000); + this.app = await env.getApp(); + }); + + afterEach(async () => { + if (this.app) { + await this.app.close(); + } + }); + + describe('RemoveServerModal', () => { + let removeServerView; + + beforeEach(async () => { + const mainView = this.app.windows().find((window) => window.url().includes('index')); + const dropdownView = this.app.windows().find((window) => window.url().includes('dropdown')); + await mainView.click('.TeamDropdownButton'); + await dropdownView.hover('.TeamDropdown .TeamDropdown__button:nth-child(1)'); + await dropdownView.click('.TeamDropdown .TeamDropdown__button:nth-child(1) button.TeamDropdown__button-remove'); + + removeServerView = await this.app.waitForEvent('window', { + predicate: (window) => window.url().includes('removeServer'), + }); + }); + + it('should remove existing team on click Remove', async () => { + await removeServerView.click('button:has-text("Remove")'); + await asyncSleep(1000); + + const expectedConfig = JSON.parse(JSON.stringify(config.teams.slice(1))); + expectedConfig.forEach((value) => { + value.order--; + }); + + const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8')); + savedConfig.teams.should.deep.equal(expectedConfig); + }); + + it('should NOT remove existing team on click Cancel', async () => { + await removeServerView.click('button:has-text("Cancel")'); + await asyncSleep(1000); + + const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8')); + savedConfig.teams.should.deep.equal(config.teams); + }); + + it('should disappear on click Close', async () => { + await removeServerView.click('button.close'); + await asyncSleep(1000); + const existing = Boolean(await this.app.windows().find((window) => window.url().includes('removeServer'))); + existing.should.be.false; + }); + + it('should disappear on click background', async () => { + await removeServerView.click('.modal', {position: {x: 20, y: 20}}); + await asyncSleep(1000); + const existing = Boolean(await this.app.windows().find((window) => window.url().includes('removeServer'))); + existing.should.be.false; + }); + }); + + describe('NewTeamModal', () => { + let newServerView; + + beforeEach(async () => { + const mainView = this.app.windows().find((window) => window.url().includes('index')); + const dropdownView = this.app.windows().find((window) => window.url().includes('dropdown')); + await mainView.click('.TeamDropdownButton'); + await dropdownView.click('.TeamDropdown .TeamDropdown__button.addServer'); + newServerView = await this.app.waitForEvent('window', { + predicate: (window) => window.url().includes('newServer'), + }); + + // wait for autofocus to finish + await asyncSleep(500); + }); + + it('should open the new server modal', async () => { + const existing = Boolean(await this.app.windows().find((window) => window.url().includes('newServer'))); + existing.should.be.true; + }); + + it('should close the window after clicking cancel', async () => { + await newServerView.click('#cancelNewServerModal'); + await asyncSleep(1000); + const existing = Boolean(await this.app.windows().find((window) => window.url().includes('newServer'))); + existing.should.be.false; + }); + + it('should not be valid if no team name has been set', async () => { + await newServerView.click('#saveNewServerModal'); + const existing = await newServerView.isVisible('#teamNameInput.is-invalid'); + existing.should.be.true; + }); + + it('should not be valid if no server address has been set', async () => { + await newServerView.click('#saveNewServerModal'); + const existing = await newServerView.isVisible('#teamUrlInput.is-invalid'); + existing.should.be.true; + }); + + describe('Valid server name', async () => { + beforeEach(async () => { + await newServerView.type('#teamNameInput', 'TestTeam'); + await newServerView.click('#saveNewServerModal'); + }); + + it('should not be marked invalid', async () => { + const existing = await newServerView.isVisible('#teamNameInput.is-invalid'); + existing.should.be.false; + }); + + it('should not be possible to click save', async () => { + const disabled = await newServerView.getAttribute('#saveNewServerModal', 'disabled'); + (disabled === '').should.be.true; + }); + }); + + describe('Valid server url', () => { + beforeEach(async () => { + await newServerView.type('#teamUrlInput', 'http://example.org'); + await newServerView.click('#saveNewServerModal'); + }); + + it('should be valid', async () => { + const existing = await newServerView.isVisible('#teamUrlInput.is-invalid'); + existing.should.be.false; + }); + + it('should not be possible to click save', async () => { + const disabled = await newServerView.getAttribute('#saveNewServerModal', 'disabled'); + (disabled === '').should.be.true; + }); + }); + + it('should not be valid if an invalid server address has been set', async () => { + await newServerView.type('#teamUrlInput', 'superInvalid url'); + await newServerView.click('#saveNewServerModal'); + const existing = await newServerView.isVisible('#teamUrlInput.is-invalid'); + existing.should.be.true; + }); + + describe('Valid Team Settings', () => { + beforeEach(async () => { + await newServerView.type('#teamUrlInput', 'http://example.org'); + await newServerView.type('#teamNameInput', 'TestTeam'); + }); + + it('should be possible to click add', async () => { + const disabled = await newServerView.getAttribute('#saveNewServerModal', 'disabled'); + (disabled === null).should.be.true; + }); + + it('should add the team to the config file', async () => { + await newServerView.click('#saveNewServerModal'); + await asyncSleep(1000); + const existing = Boolean(await this.app.windows().find((window) => window.url().includes('newServer'))); + existing.should.be.false; + + const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8')); + savedConfig.teams.should.deep.contain({ + name: 'TestTeam', + url: 'http://example.org', + order: 2, + tabs: [ + { + name: 'TAB_MESSAGING', + order: 0, + isOpen: true, + }, + { + name: 'TAB_FOCALBOARD', + order: 1, + }, + { + name: 'TAB_PLAYBOOKS', + order: 2, + }, + ], + lastActiveTab: 0, + }); + }); + }); + }); +}); diff --git a/test/specs/browser/settings_test.js b/test/specs/browser/settings_test.js index 6ed7c78e..92f70085 100644 --- a/test/specs/browser/settings_test.js +++ b/test/specs/browser/settings_test.js @@ -4,529 +4,265 @@ // TODO: fix test with new settings window -// 'use strict'; - -// const fs = require('fs'); - -// const env = require('../../modules/environment'); -// const {asyncSleep} = require('../../modules/utils'); - -// describe('renderer/settings.html', function desc() { -// this.timeout(30000); - -// const config = { -// version: 2, -// teams: [{ -// name: 'example', -// url: env.mattermostURL, -// order: 0, -// }, { -// name: 'github', -// url: 'https://github.com/', -// order: 1, -// }], -// showTrayIcon: false, -// trayIconTheme: 'light', -// minimizeToTray: false, -// notifications: { -// flashWindow: 0, -// bounceIcon: false, -// bounceIconType: 'informational', -// }, -// showUnreadBadge: true, -// useSpellChecker: true, -// enableHardwareAcceleration: true, -// autostart: true, -// darkMode: false, -// }; - -// beforeEach(async () => { -// fs.writeFileSync(env.configFilePath, JSON.stringify(config)); -// await asyncSleep(1000); -// this.app = env.getSpectronApp(); -// await this.app.start(); -// }); - -// afterEach(async () => { -// if (this.app && this.app.isRunning()) { -// await this.app.stop(); -// } -// }); - -// describe('Close button', async () => { -// // it.skip('should show index.html when it\'s clicked', async () => { -// // env.addClientCommands(this.app.client); -// // await this.app.client. -// // loadSettingsPage(). -// // click('#btnClose'). -// // pause(1000); -// // const url = await this.app.client.getUrl(); -// // url.should.match(/\/index.html(\?.+)?$/); -// // }); - -// it('should be disabled when the number of servers is zero', async () => { -// await this.app.stop(); -// env.cleanTestConfig(); -// await this.app.start(); - -// await this.app.client.waitUntilWindowLoaded(). -// waitForVisible('#newServerModal', 10000). -// click('#cancelNewServerModal'); -// let isCloseButtonEnabled = await this.app.client.isEnabled('#btnClose'); -// isCloseButtonEnabled.should.equal(false); - -// await this.app.client. -// waitForVisible('#newServerModal', true). -// pause(250). -// click('#addNewServer'). -// waitForVisible('#newServerModal'). -// setValue('#teamNameInput', 'TestTeam'). -// pause(100). -// setValue('#teamUrlInput', 'http://example.org'). -// click('#saveNewServerModal'). -// waitForVisible('#newServerModal', true). -// waitForVisible('#serversSaveIndicator'). -// waitForVisible('#serversSaveIndicator', 10000, true); // at least 2500 ms to disappear -// isCloseButtonEnabled = await this.app.client.isEnabled('#btnClose'); -// isCloseButtonEnabled.should.equal(true); -// }); -// }); - -// it('should show NewServerModal after all servers are removed', async () => { -// const modalTitleSelector = '.modal-title=Remove Server'; -// env.addClientCommands(this.app.client); -// await this.app.client. -// loadSettingsPage(). -// click('=Remove'). -// waitForVisible(modalTitleSelector). -// element('.modal-dialog').click('.btn=Remove'). -// pause(500). -// click('=Remove'). -// waitForVisible(modalTitleSelector). -// element('.modal-dialog').click('.btn=Remove'). -// pause(500); -// const isModalExisting = await this.app.client.isExisting('#newServerModal'); -// isModalExisting.should.be.true; -// }); - -// // describe('Server list', () => { -// // it.skip('should open the corresponding tab when a server list item is clicked', async () => { -// // env.addClientCommands(this.app.client); -// // await this.app.client. -// // loadSettingsPage(). -// // click('h4=example'). -// // pause(1000). -// // waitUntilWindowLoaded(); -// // let indexURL = await this.app.client.getUrl(); -// // indexURL.should.match(/\/index.html(\?.+)?$/); - -// // let isView0Visible = await this.app.client.isVisible('#mattermostView0'); -// // isView0Visible.should.be.true; - -// // let isView1Visible = await this.app.client.isVisible('#mattermostView1'); -// // isView1Visible.should.be.false; - -// // await this.app.client. -// // loadSettingsPage(). -// // click('h4=github'). -// // pause(1000). -// // waitUntilWindowLoaded(); -// // indexURL = await this.app.client.getUrl(); -// // indexURL.should.match(/\/index.html(\?.+)?$/); - -// // isView0Visible = await this.app.client.isVisible('#mattermostView0'); -// // isView0Visible.should.be.false; - -// // isView1Visible = await this.app.client.isVisible('#mattermostView1'); -// // isView1Visible.should.be.true; -// // }); -// // }); - -// describe('Options', () => { -// // describe.skip('Hide Menu Bar', () => { -// // it('should appear on win32 or linux', async () => { -// // const expected = (process.platform === 'win32' || process.platform === 'linux'); -// // env.addClientCommands(this.app.client); -// // await this.app.client.loadSettingsPage(); -// // const existing = await this.app.client.isExisting('#inputHideMenuBar'); -// // existing.should.equal(expected); -// // }); - -// // [true, false].forEach((v) => { -// // env.shouldTest(it, env.isOneOf(['win32', 'linux']))(`should be saved and loaded: ${v}`, async () => { -// // env.addClientCommands(this.app.client); -// // await this.app.client. -// // loadSettingsPage(). -// // scroll('#inputHideMenuBar'); -// // const isSelected = await this.app.client.isSelected('#inputHideMenuBar'); -// // if (isSelected !== v) { -// // await this.app.client.click('#inputHideMenuBar'); -// // } - -// // await this.app.client. -// // pause(600). -// // click('#btnClose'). -// // pause(1000); - -// // const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8')); -// // savedConfig.hideMenuBar.should.equal(v); - -// // let autoHide = await this.app.browserWindow.isMenuBarAutoHide(); -// // autoHide.should.equal(v); - -// // // confirm actual behavior -// // await this.app.restart(); -// // env.addClientCommands(this.app.client); - -// // autoHide = await this.app.browserWindow.isMenuBarAutoHide(); -// // autoHide.should.equal(v); - -// // await this.app.loadSettingsPage(); -// // autoHide = await this.app.client.isSelected('#inputHideMenuBar'); -// // autoHide.should.equal(v); -// // }); -// // }); -// // }); - -// describe('Start app on login', () => { -// it('should appear on win32 or linux', async () => { -// const expected = (process.platform === 'win32' || process.platform === 'linux'); -// env.addClientCommands(this.app.client); -// await this.app.client.loadSettingsPage(); -// const existing = await this.app.client.isExisting('#inputAutoStart'); -// existing.should.equal(expected); -// }); -// }); - -// describe('Show icon in menu bar / notification area', () => { -// it('should appear on darwin or linux', async () => { -// const expected = (process.platform === 'darwin' || process.platform === 'linux'); -// env.addClientCommands(this.app.client); -// await this.app.client.loadSettingsPage(); -// const existing = await this.app.client.isExisting('#inputShowTrayIcon'); -// existing.should.equal(expected); -// }); - -// describe('Save tray icon setting on mac', () => { -// env.shouldTest(it, env.isOneOf(['darwin', 'linux']))('should be saved when it\'s selected', async () => { -// env.addClientCommands(this.app.client); -// await this.app.browserWindow.setSize(1024, 768); // Resize the window to click the element -// await this.app.client. -// loadSettingsPage(). -// click('#inputShowTrayIcon'). -// waitForAppOptionsAutoSaved(); - -// let config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8')); -// config0.showTrayIcon.should.true; - -// await this.app.client. -// click('#inputShowTrayIcon'). -// waitForAppOptionsAutoSaved(); - -// config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8')); -// config0.showTrayIcon.should.false; -// }); -// }); - -// describe('Save tray icon theme on linux', () => { -// env.shouldTest(it, process.platform === 'linux')('should be saved when it\'s selected', async () => { -// env.addClientCommands(this.app.client); -// await this.app.browserWindow.setSize(1024, 768); // Resize the window to click the element -// await this.app.client. -// loadSettingsPage(). -// click('#inputShowTrayIcon'). -// click('input[value="dark"]'). -// pause(700); // wait auto-save - -// const config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8')); -// config0.trayIconTheme.should.equal('dark'); - -// await this.app.client. -// click('input[value="light"]'). -// pause(700); // wait auto-save - -// const config1 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8')); -// config1.trayIconTheme.should.equal('light'); -// }); -// }); -// }); - -// describe('Leave app running in notification area when application window is closed', () => { -// it('should appear on linux', async () => { -// const expected = (process.platform === 'linux'); -// env.addClientCommands(this.app.client); -// await this.app.client.loadSettingsPage(); -// const existing = await this.app.client.isExisting('#inputMinimizeToTray'); -// existing.should.equal(expected); -// }); -// }); - -// // describe.skip('Toggle window visibility when clicking on the tray icon', () => { -// // it('should appear on win32', async () => { -// // const expected = (process.platform === 'win32'); -// // env.addClientCommands(this.app.client); -// // await this.app.client.loadSettingsPage(); -// // const existing = await this.app.client.isExisting('#inputToggleWindowOnTrayIconClick'); -// // existing.should.equal(expected); -// // }); -// // }); - -// describe('Flash app window and taskbar icon when a new message is received', () => { -// it('should appear on win32 and linux', async () => { -// const expected = (process.platform === 'win32' || process.platform === 'linux'); -// env.addClientCommands(this.app.client); -// await this.app.client.loadSettingsPage(); -// const existing = await this.app.client.isExisting('#inputflashWindow'); -// existing.should.equal(expected); -// }); -// }); - -// describe('Show red badge on taskbar icon to indicate unread messages', () => { -// it('should appear on darwin or win32', async () => { -// const expected = (process.platform === 'darwin' || process.platform === 'win32'); -// env.addClientCommands(this.app.client); -// await this.app.client.loadSettingsPage(); -// const existing = await this.app.client.isExisting('#inputShowUnreadBadge'); -// existing.should.equal(expected); -// }); -// }); - -// describe('Check spelling', () => { -// it('should appear and be selectable', async () => { -// env.addClientCommands(this.app.client); -// await this.app.client.loadSettingsPage(); -// const existing = await this.app.client.isExisting('#inputSpellChecker'); -// existing.should.equal(true); - -// const selected = await this.app.client.isSelected('#inputSpellChecker'); -// selected.should.equal(true); - -// const windowBounds = await this.app.browserWindow.getBounds(); -// const inputLocation = await this.app.client.getLocation('#inputSpellChecker'); -// const offset = (inputLocation.y - windowBounds.height) + 100; - -// await this.app.client. -// scroll(0, offset). -// click('#inputSpellChecker'). -// pause(5000); -// const config1 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8')); -// config1.useSpellChecker.should.equal(false); -// }); -// }); - -// describe('Enable GPU hardware acceleration', () => { -// it('should save selected option', async () => { -// const ID_INPUT_ENABLE_HARDWARE_ACCELERATION = '#inputEnableHardwareAcceleration'; -// env.addClientCommands(this.app.client); -// await this.app.client. -// loadSettingsPage(). -// waitForExist(ID_INPUT_ENABLE_HARDWARE_ACCELERATION, 5000). -// scroll(ID_INPUT_ENABLE_HARDWARE_ACCELERATION); -// const selected = await this.app.client.isSelected(ID_INPUT_ENABLE_HARDWARE_ACCELERATION); -// selected.should.equal(true); // default is true - -// await this.app.client.click(ID_INPUT_ENABLE_HARDWARE_ACCELERATION). -// waitForVisible('#appOptionsSaveIndicator', 5000). -// waitForVisible('#appOptionsSaveIndicator', 5000, true); // at least 2500 ms to disappear -// const config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8')); -// config0.enableHardwareAcceleration.should.equal(false); - -// await this.app.client.click(ID_INPUT_ENABLE_HARDWARE_ACCELERATION). -// waitForVisible('#appOptionsSaveIndicator', 5000). -// waitForVisible('#appOptionsSaveIndicator', 5000, true); // at least 2500 ms to disappear -// const config1 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8')); -// config1.enableHardwareAcceleration.should.equal(true); -// }); -// }); -// }); - -// describe('RemoveServerModal', () => { -// const modalTitleSelector = '.modal-title=Remove Server'; - -// beforeEach(async () => { -// env.addClientCommands(this.app.client); -// await this.app.client.loadSettingsPage(); -// const existing = await this.app.client.isExisting(modalTitleSelector); -// existing.should.be.false; - -// const visible = await this.app.client.isVisible(modalTitleSelector); -// visible.should.be.false; - -// await this.app.client. -// click('=Remove'). -// waitForVisible(modalTitleSelector); -// }); - -// it('should remove existing team on click Remove', async () => { -// await this.app.client. -// element('.modal-dialog').click('.btn=Remove'). -// waitForExist(modalTitleSelector, 5000, true); - -// await this.app.client.waitForVisible('#serversSaveIndicator', 10000, true); - -// const expectedConfig = JSON.parse(JSON.stringify(config.teams.slice(1))); -// expectedConfig.forEach((value) => { -// value.order--; -// }); - -// const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8')); -// savedConfig.teams.should.deep.equal(expectedConfig); -// }); - -// it('should NOT remove existing team on click Cancel', async () => { -// await this.app.client. -// element('.modal-dialog').click('.btn=Cancel'). -// waitForExist(modalTitleSelector, 5000, true); - -// await this.app.client.waitForVisible('#serversSaveIndicator', 10000, true); - -// const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8')); -// savedConfig.teams.should.deep.equal(config.teams); -// }); - -// it('should disappear on click Close', async () => { -// await this.app.client. -// element('.modal-dialog').click('button.close'). -// waitForVisible(modalTitleSelector, 10000, true); -// const existing = await this.app.client.isExisting(modalTitleSelector); -// existing.should.be.false; -// }); - -// it('should disappear on click background', async () => { -// await this.app.browserWindow.setSize(1024, 768); // Resize the window to click the center of -// await this.app.client. -// click('body'). -// waitForVisible(modalTitleSelector, 10000, true); -// const existing = await this.app.client.isExisting(modalTitleSelector); -// existing.should.be.false; -// }); -// }); - -// describe('NewTeamModal', () => { -// beforeEach(() => { -// env.addClientCommands(this.app.client); -// return this.app.client. -// loadSettingsPage(). -// click('#addNewServer'). -// pause(1000); -// }); - -// it('should open the new server modal', () => { -// return this.app.client.isExisting('#newServerModal').then((existing) => { -// existing.should.be.true; -// }); -// }); - -// it('should close the window after clicking cancel', () => { -// return this.app.client. -// click('#cancelNewServerModal'). -// waitForExist('#newServerModal', 10000, true). -// isExisting('#newServerModal').then((existing) => { -// existing.should.be.false; -// }); -// }); - -// it('should not be valid if no team name has been set', () => { -// return this.app.client. -// click('#saveNewServerModal'). -// waitForExist('.has-error #teamNameInput', 10000). -// isExisting('.has-error #teamNameInput').then((existing) => { -// existing.should.be.true; -// }); -// }); - -// it('should not be valid if no server address has been set', () => { -// return this.app.client. -// click('#saveNewServerModal'). -// waitForExist('.has-error #teamUrlInput', 10000). -// isExisting('.has-error #teamUrlInput').then((existing) => { -// existing.should.be.true; -// }); -// }); - -// describe('Valid server name', () => { -// beforeEach(() => { -// return this.app.client. -// setValue('#teamNameInput', 'TestTeam'). -// click('#saveNewServerModal'); -// }); - -// it('should not be marked invalid', () => { -// return this.app.client. -// isExisting('.has-error #teamNameInput').then((existing) => { -// existing.should.be.false; -// }); -// }); - -// it('should not be possible to click save', () => { -// return this.app.client. -// getAttribute('#saveNewServerModal', 'disabled').then((disabled) => { -// disabled.should.equal('true'); -// }); -// }); -// }); - -// describe('Valid server url', () => { -// beforeEach(() => { -// return this.app.client. -// setValue('#teamUrlInput', 'http://example.org'). -// click('#saveNewServerModal'); -// }); - -// it('should be valid', () => { -// return this.app.client. -// isExisting('.has-error #teamUrlInput').then((existing) => { -// existing.should.be.false; -// }); -// }); - -// it('should not be possible to click save', () => { -// return this.app.client. -// getAttribute('#saveNewServerModal', 'disabled').then((disabled) => { -// disabled.should.equal('true'); -// }); -// }); -// }); - -// it('should not be valid if an invalid server address has been set', () => { -// return this.app.client. -// setValue('#teamUrlInput', 'superInvalid url'). -// click('#saveNewServerModal'). -// pause(500). -// isExisting('.has-error #teamUrlInput').then((existing) => { -// existing.should.be.true; -// }); -// }); - -// describe('Valid Team Settings', () => { -// beforeEach(() => { -// return this.app.client. -// setValue('#teamUrlInput', 'http://example.org'). -// setValue('#teamNameInput', 'TestTeam'); -// }); - -// it('should be possible to click add', () => { -// return this.app.client. -// getAttribute('#saveNewServerModal', 'disabled').then((disabled) => { -// (disabled === null).should.be.true; -// }); -// }); - -// it('should add the team to the config file', async () => { -// await this.app.client. -// click('#saveNewServerModal'). -// waitForVisible('#newServerModal', 10000, true). -// waitForVisible('#serversSaveIndicator', 10000). -// waitForVisible('#serversSaveIndicator', 10000, true). // at least 2500 ms to disappear -// waitUntilWindowLoaded(); - -// const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8')); -// savedConfig.teams.should.deep.contain({ -// name: 'TestTeam', -// url: 'http://example.org', -// order: 2, -// }); -// }); -// }); -// }); -// }); +'use strict'; + +const fs = require('fs'); + +const {SHOW_SETTINGS_WINDOW} = require('../../../src/common/communication'); + +const env = require('../../modules/environment'); +const {asyncSleep} = require('../../modules/utils'); + +describe('renderer/settings.html', function desc() { + this.timeout(30000); + + const config = { + version: 3, + teams: [{ + name: 'example', + url: env.mattermostURL, + order: 0, + tabs: [ + { + name: 'TAB_MESSAGING', + order: 0, + isOpen: true, + }, + { + name: 'TAB_FOCALBOARD', + order: 1, + isOpen: true, + }, + { + name: 'TAB_PLAYBOOKS', + order: 2, + isOpen: true, + }, + ], + lastActiveTab: 0, + }, { + name: 'github', + url: 'https://github.com/', + order: 1, + tabs: [ + { + name: 'TAB_MESSAGING', + order: 0, + isOpen: true, + }, + { + name: 'TAB_FOCALBOARD', + order: 1, + isOpen: true, + }, + { + name: 'TAB_PLAYBOOKS', + order: 2, + isOpen: true, + }, + ], + lastActiveTab: 0, + }], + showTrayIcon: false, + trayIconTheme: 'light', + minimizeToTray: false, + notifications: { + flashWindow: 0, + bounceIcon: false, + bounceIconType: 'informational', + }, + showUnreadBadge: true, + useSpellChecker: true, + enableHardwareAcceleration: true, + autostart: true, + darkMode: false, + lastActiveTeam: 0, + spellCheckerLocales: [], + }; + + beforeEach(async () => { + env.createTestUserDataDir(); + env.cleanTestConfig(); + fs.writeFileSync(env.configFilePath, JSON.stringify(config)); + await asyncSleep(1000); + this.app = await env.getApp(); + }); + + afterEach(async () => { + if (this.app) { + await this.app.close(); + } + }); + + describe('Options', () => { + describe('Start app on login', () => { + it('should appear on win32 or linux', async () => { + const expected = (process.platform === 'win32' || process.platform === 'linux'); + this.app.evaluate(({ipcMain}, showWindow) => { + ipcMain.emit(showWindow); + }, SHOW_SETTINGS_WINDOW); + const settingsWindow = await this.app.waitForEvent('window', { + predicate: (window) => window.url().includes('settings'), + }); + await settingsWindow.waitForSelector('.settingsPage.container'); + const existing = await settingsWindow.isVisible('#inputAutoStart'); + existing.should.equal(expected); + }); + }); + + describe('Show icon in menu bar / notification area', () => { + it('should appear on darwin or linux', async () => { + const expected = (process.platform === 'darwin' || process.platform === 'linux'); + this.app.evaluate(({ipcMain}, showWindow) => { + ipcMain.emit(showWindow); + }, SHOW_SETTINGS_WINDOW); + const settingsWindow = await this.app.waitForEvent('window', { + predicate: (window) => window.url().includes('settings'), + }); + await settingsWindow.waitForSelector('.settingsPage.container'); + const existing = await settingsWindow.isVisible('#inputShowTrayIcon'); + existing.should.equal(expected); + }); + + describe('Save tray icon setting on mac', () => { + env.shouldTest(it, env.isOneOf(['darwin', 'linux']))('should be saved when it\'s selected', async () => { + this.app.evaluate(({ipcMain}, showWindow) => { + ipcMain.emit(showWindow); + }, SHOW_SETTINGS_WINDOW); + const settingsWindow = await this.app.waitForEvent('window', { + predicate: (window) => window.url().includes('settings'), + }); + await settingsWindow.waitForSelector('.settingsPage.container'); + await settingsWindow.click('#inputShowTrayIcon'); + await settingsWindow.waitForSelector('.IndicatorContainer :text("Saved")'); + + let config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8')); + config0.showTrayIcon.should.true; + + await settingsWindow.click('#inputShowTrayIcon'); + await settingsWindow.waitForSelector('.IndicatorContainer :text("Saved")'); + + config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8')); + config0.showTrayIcon.should.false; + }); + }); + + describe('Save tray icon theme on linux', () => { + env.shouldTest(it, process.platform === 'linux')('should be saved when it\'s selected', async () => { + this.app.evaluate(({ipcMain}, showWindow) => { + ipcMain.emit(showWindow); + }, SHOW_SETTINGS_WINDOW); + const settingsWindow = await this.app.waitForEvent('window', { + predicate: (window) => window.url().includes('settings'), + }); + await settingsWindow.waitForSelector('.settingsPage.container'); + await settingsWindow.click('#inputShowTrayIcon'); + await settingsWindow.click('input[value="dark"]'); + await settingsWindow.waitForSelector('.IndicatorContainer :text("Saved")'); + + const config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8')); + config0.trayIconTheme.should.equal('dark'); + + await settingsWindow.click('input[value="light"]'); + await settingsWindow.waitForSelector('.IndicatorContainer :text("Saved")'); + + const config1 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8')); + config1.trayIconTheme.should.equal('light'); + }); + }); + }); + + describe('Leave app running in notification area when application window is closed', () => { + it('should appear on linux', async () => { + const expected = (process.platform === 'linux'); + this.app.evaluate(({ipcMain}, showWindow) => { + ipcMain.emit(showWindow); + }, SHOW_SETTINGS_WINDOW); + const settingsWindow = await this.app.waitForEvent('window', { + predicate: (window) => window.url().includes('settings'), + }); + await settingsWindow.waitForSelector('.settingsPage.container'); + const existing = await settingsWindow.isVisible('#inputMinimizeToTray'); + existing.should.equal(expected); + }); + }); + + describe('Flash app window and taskbar icon when a new message is received', () => { + it('should appear on win32 and linux', async () => { + const expected = (process.platform === 'win32' || process.platform === 'linux'); + this.app.evaluate(({ipcMain}, showWindow) => { + ipcMain.emit(showWindow); + }, SHOW_SETTINGS_WINDOW); + const settingsWindow = await this.app.waitForEvent('window', { + predicate: (window) => window.url().includes('settings'), + }); + await settingsWindow.waitForSelector('.settingsPage.container'); + const existing = await settingsWindow.isVisible('#inputflashWindow'); + existing.should.equal(expected); + }); + }); + + describe('Show red badge on taskbar icon to indicate unread messages', () => { + it('should appear on darwin or win32', async () => { + const expected = (process.platform === 'darwin' || process.platform === 'win32'); + this.app.evaluate(({ipcMain}, showWindow) => { + ipcMain.emit(showWindow); + }, SHOW_SETTINGS_WINDOW); + const settingsWindow = await this.app.waitForEvent('window', { + predicate: (window) => window.url().includes('settings'), + }); + await settingsWindow.waitForSelector('.settingsPage.container'); + const existing = await settingsWindow.isVisible('#inputShowUnreadBadge'); + existing.should.equal(expected); + }); + }); + + describe('Check spelling', () => { + it('should appear and be selectable', async () => { + this.app.evaluate(({ipcMain}, showWindow) => { + ipcMain.emit(showWindow); + }, SHOW_SETTINGS_WINDOW); + const settingsWindow = await this.app.waitForEvent('window', { + predicate: (window) => window.url().includes('settings'), + }); + await settingsWindow.waitForSelector('.settingsPage.container'); + const existing = await settingsWindow.isVisible('#inputSpellChecker'); + existing.should.equal(true); + + const selected = await settingsWindow.isChecked('#inputSpellChecker'); + selected.should.equal(true); + + await settingsWindow.click('#inputSpellChecker'); + await settingsWindow.waitForSelector('.IndicatorContainer :text("Saved")'); + + const config1 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8')); + config1.useSpellChecker.should.equal(false); + }); + }); + + describe('Enable GPU hardware acceleration', () => { + it('should save selected option', async () => { + const ID_INPUT_ENABLE_HARDWARE_ACCELERATION = '#inputEnableHardwareAcceleration'; + this.app.evaluate(({ipcMain}, showWindow) => { + ipcMain.emit(showWindow); + }, SHOW_SETTINGS_WINDOW); + const settingsWindow = await this.app.waitForEvent('window', { + predicate: (window) => window.url().includes('settings'), + }); + await settingsWindow.waitForSelector('.settingsPage.container'); + const selected = await settingsWindow.isChecked(ID_INPUT_ENABLE_HARDWARE_ACCELERATION); + selected.should.equal(true); // default is true + + await settingsWindow.click(ID_INPUT_ENABLE_HARDWARE_ACCELERATION); + await settingsWindow.waitForSelector('.IndicatorContainer :text("Saved")'); + const config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8')); + config0.enableHardwareAcceleration.should.equal(false); + + await settingsWindow.click(ID_INPUT_ENABLE_HARDWARE_ACCELERATION); + await settingsWindow.waitForSelector('.IndicatorContainer :text("Saved")'); + const config1 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8')); + config1.enableHardwareAcceleration.should.equal(true); + }); + }); + }); +}); diff --git a/test/specs/config_test.js b/test/specs/config_test.js new file mode 100644 index 00000000..046bb4fe --- /dev/null +++ b/test/specs/config_test.js @@ -0,0 +1,116 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +'use strict'; + +const fs = require('fs'); + +const env = require('../modules/environment'); + +describe('config', function desc() { + this.timeout(30000); + + beforeEach(async () => { + env.createTestUserDataDir(); + env.cleanTestConfig(); + }); + + afterEach(async () => { + if (this.app) { + try { + await this.app.close(); + // eslint-disable-next-line no-empty + } catch (err) {} + } + }); + + it('should show servers in dropdown when there is config file', async () => { + const config = { + version: 3, + teams: [{ + name: 'example', + url: env.mattermostURL, + order: 0, + tabs: [ + { + name: 'TAB_MESSAGING', + order: 0, + isOpen: true, + }, + { + name: 'TAB_FOCALBOARD', + order: 1, + isOpen: true, + }, + { + name: 'TAB_PLAYBOOKS', + order: 2, + isOpen: true, + }, + ], + lastActiveTab: 0, + }, { + name: 'github', + url: 'https://github.com/', + order: 1, + tabs: [ + { + name: 'TAB_MESSAGING', + order: 0, + isOpen: true, + }, + { + name: 'TAB_FOCALBOARD', + order: 1, + isOpen: true, + }, + { + name: 'TAB_PLAYBOOKS', + order: 2, + isOpen: true, + }, + ], + lastActiveTab: 0, + }], + showTrayIcon: false, + trayIconTheme: 'light', + minimizeToTray: false, + notifications: { + flashWindow: 0, + bounceIcon: false, + bounceIconType: 'informational', + }, + showUnreadBadge: true, + useSpellChecker: true, + enableHardwareAcceleration: true, + autostart: true, + darkMode: false, + lastActiveTeam: 0, + spellCheckerLocales: [], + }; + fs.writeFileSync(env.configFilePath, JSON.stringify(config)); + this.app = await env.getApp(); + const mainWindow = this.app.windows().find((window) => window.url().includes('index')); + const dropdownButtonText = await mainWindow.innerText('.TeamDropdownButton'); + dropdownButtonText.should.equal('example'); + await this.app.close(); + }); + + it('should upgrade v0 config file', async () => { + const Config = require('../../src/common/config').default; + const newConfig = new Config(env.configFilePath); + const oldConfig = { + url: env.mattermostURL, + }; + fs.writeFileSync(env.configFilePath, JSON.stringify(oldConfig)); + this.app = await env.getApp(); + const mainWindow = this.app.windows().find((window) => window.url().includes('index')); + const dropdownButtonText = await mainWindow.innerText('.TeamDropdownButton:has-text("Primary team")'); + dropdownButtonText.should.equal('Primary team'); + + const str = fs.readFileSync(env.configFilePath, 'utf8'); + const upgradedConfig = JSON.parse(str); + upgradedConfig.version.should.equal(newConfig.defaultData.version); + await this.app.close(); + }); +}); diff --git a/test/specs/index.js b/test/specs/index.js index 280f5889..96cf443a 100644 --- a/test/specs/index.js +++ b/test/specs/index.js @@ -2,9 +2,13 @@ // See LICENSE.txt for license information. import './app_test.js'; -import './security_test.js'; -import './spellchecker_test.js'; +import './config_test.js'; +import './mattermost_test.js'; +import './window_test.js'; + import './browser/index_test.js'; +import './browser/modal_test.js'; import './browser/settings_test.js'; + import './main/user_activity_monitor_test.js'; import './utils/util_test.js'; diff --git a/test/specs/mattermost_test.js b/test/specs/mattermost_test.js new file mode 100644 index 00000000..4f060d5a --- /dev/null +++ b/test/specs/mattermost_test.js @@ -0,0 +1,106 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. +'use strict'; + +const fs = require('fs'); + +const env = require('../modules/environment'); +const {asyncSleep} = require('../modules/utils'); + +describe('mattermost', function desc() { + this.timeout(30000); + + const config = { + version: 3, + teams: [{ + name: 'example', + url: env.mattermostURL, + order: 0, + tabs: [ + { + name: 'TAB_MESSAGING', + order: 0, + isOpen: true, + }, + { + name: 'TAB_FOCALBOARD', + order: 1, + isOpen: false, + }, + { + name: 'TAB_PLAYBOOKS', + order: 2, + isOpen: false, + }, + ], + lastActiveTab: 0, + }, { + name: 'github', + url: 'https://github.com/', + order: 1, + tabs: [ + { + name: 'TAB_MESSAGING', + order: 0, + isOpen: true, + }, + { + name: 'TAB_FOCALBOARD', + order: 1, + isOpen: false, + }, + { + name: 'TAB_PLAYBOOKS', + order: 2, + isOpen: false, + }, + ], + lastActiveTab: 0, + }], + showTrayIcon: false, + trayIconTheme: 'light', + minimizeToTray: false, + notifications: { + flashWindow: 0, + bounceIcon: false, + bounceIconType: 'informational', + }, + showUnreadBadge: true, + useSpellChecker: true, + enableHardwareAcceleration: true, + autostart: true, + darkMode: false, + lastActiveTeam: 0, + spellCheckerLocales: [], + }; + + beforeEach(async () => { + env.cleanDataDir(); + env.createTestUserDataDir(); + env.cleanTestConfig(); + fs.writeFileSync(env.configFilePath, JSON.stringify(config)); + await asyncSleep(1000); + this.app = await env.getApp(); + this.serverMap = await env.getServerMap(this.app); + }); + + afterEach(async () => { + if (this.app) { + await this.app.close(); + } + }); + + // TODO: enable when we have a server to test against + it.skip('Control+F should focus the search bar in Mattermost', async () => { + const loadingScreen = this.app.windows().find((window) => window.url().includes('loadingScreen')); + await loadingScreen.waitForSelector('.LoadingScreen', {state: 'hidden'}); + const firstServer = this.serverMap[`${config.teams[0].name}___TAB_MESSAGING`].win; + await env.loginToMattermost(firstServer); + await firstServer.waitForSelector('#searchBox'); + await firstServer.press('body', process.platform === 'darwin' ? 'Meta+F' : 'Control+F'); + const isFocused = await firstServer.$eval('#searchBox', (el) => el === document.activeElement); + isFocused.should.be.true; + const text = await firstServer.inputValue('#searchBox'); + text.should.include('in:'); + }); +}); diff --git a/test/specs/menu_test.js b/test/specs/menu_test.js new file mode 100644 index 00000000..ac7e4b1a --- /dev/null +++ b/test/specs/menu_test.js @@ -0,0 +1,143 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. +'use strict'; + +const fs = require('fs'); + +// const http = require('http'); +// const path = require('path'); + +const robot = require('robotjs'); + +const env = require('../modules/environment'); +const {asyncSleep} = require('../modules/utils'); + +describe('mattermost', function desc() { + this.timeout(30000); + + const config = { + version: 3, + teams: [{ + name: 'example', + url: env.mattermostURL, + order: 0, + tabs: [ + { + name: 'TAB_MESSAGING', + order: 0, + isOpen: true, + }, + { + name: 'TAB_FOCALBOARD', + order: 1, + isOpen: false, + }, + { + name: 'TAB_PLAYBOOKS', + order: 2, + isOpen: false, + }, + ], + lastActiveTab: 0, + }, { + name: 'github', + url: 'https://github.com/', + order: 1, + tabs: [ + { + name: 'TAB_MESSAGING', + order: 0, + isOpen: true, + }, + { + name: 'TAB_FOCALBOARD', + order: 1, + isOpen: false, + }, + { + name: 'TAB_PLAYBOOKS', + order: 2, + isOpen: false, + }, + ], + lastActiveTab: 0, + }], + showTrayIcon: false, + trayIconTheme: 'light', + minimizeToTray: false, + notifications: { + flashWindow: 0, + bounceIcon: false, + bounceIconType: 'informational', + }, + showUnreadBadge: true, + useSpellChecker: true, + enableHardwareAcceleration: true, + autostart: true, + darkMode: false, + lastActiveTeam: 0, + spellCheckerLocales: [], + }; + + beforeEach(async () => { + env.cleanDataDir(); + env.createTestUserDataDir(); + env.cleanTestConfig(); + fs.writeFileSync(env.configFilePath, JSON.stringify(config)); + await asyncSleep(1000); + this.app = await env.getApp(); + this.serverMap = await env.getServerMap(this.app); + }); + + afterEach(async () => { + if (this.app) { + await this.app.close(); + } + }); + + it('should reload page when pressing Ctrl+R', async () => { + const mainWindow = await this.app.firstWindow(); + const browserWindow = await this.app.browserWindow(mainWindow); + const webContentsId = this.serverMap[`${config.teams[0].name}___TAB_MESSAGING`].webContentsId; + + const loadingScreen = this.app.windows().find((window) => window.url().includes('loadingScreen')); + await loadingScreen.waitForSelector('.LoadingScreen', {state: 'hidden'}); + const check = browserWindow.evaluate(async (window, id) => { + const promise = new Promise((resolve) => { + const browserView = window.getBrowserViews().find((view) => view.webContents.id === id); + browserView.webContents.on('did-finish-load', () => { + resolve(); + }); + }); + await promise; + return true; + }, webContentsId); + await asyncSleep(500); + robot.keyTap('r', ['control']); + const result = await check; + result.should.be.true; + }); + + it('should reload page when pressing Ctrl+Shift+R', async () => { + const mainWindow = await this.app.firstWindow(); + const browserWindow = await this.app.browserWindow(mainWindow); + const webContentsId = this.serverMap[`${config.teams[0].name}___TAB_MESSAGING`].webContentsId; + + const loadingScreen = this.app.windows().find((window) => window.url().includes('loadingScreen')); + await loadingScreen.waitForSelector('.LoadingScreen', {state: 'hidden'}); + const check = browserWindow.evaluate(async (window, id) => { + const promise = new Promise((resolve) => { + const browserView = window.getBrowserViews().find((view) => view.webContents.id === id); + browserView.webContents.on('did-finish-load', () => { + resolve(); + }); + }); + await promise; + return true; + }, webContentsId); + await asyncSleep(500); + robot.keyTap('r', ['control', 'shift']); + const result = await check; + result.should.be.true; + }); +}); diff --git a/test/specs/security_test.js b/test/specs/security_test.js deleted file mode 100644 index fcb1d456..00000000 --- a/test/specs/security_test.js +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2015-2016 Yuya Ochiai -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. -'use strict'; - -// const fs = require('fs'); - -// const path = require('path'); -// const http = require('http'); - -// const env = require('../modules/environment'); - -// describe.skip('security', function desc() { -// this.timeout(30000); - -// const serverPort = 8181; -// const testURL = `http://localhost:${serverPort}`; - -// const config = { -// version: 2, -// teams: [{ -// name: 'example_1', -// url: testURL, -// order: 0, -// }, { -// name: 'example_2', -// url: testURL, -// order: 1, -// }], -// }; - -// before(() => { -// this.server = http.createServer((req, res) => { -// res.writeHead(200, { -// 'Content-Type': 'text/html', -// }); -// res.end(fs.readFileSync(path.resolve(env.sourceRootDir, 'test/modules/test.html'), 'utf-8')); -// }).listen(serverPort, '127.0.0.1'); -// }); - -// beforeEach(() => { -// fs.writeFileSync(env.configFilePath, JSON.stringify(config)); -// this.app = env.getSpectronApp(); -// return this.app.start(); -// }); - -// afterEach(() => { -// if (this.app && this.app.isRunning()) { -// return this.app.stop(); -// } -// return true; -// }); - -// after((done) => { -// this.server.close(done); -// }); - -// it('should NOT be able to call Node.js API in webview', () => { -// env.addClientCommands(this.app.client); - -// // webview is handled as a window by chromedriver. -// return this.app.client. -// windowByIndex(1).isNodeEnabled().then((enabled) => { -// enabled.should.be.false; -// }). -// windowByIndex(2).isNodeEnabled().then((enabled) => { -// enabled.should.be.false; -// }). -// windowByIndex(0). -// getAttribute('webview', 'nodeintegration').then((nodeintegration) => { -// // nodeintegration is an array of string -// nodeintegration.forEach((n) => { -// n.should.equal('false'); -// }); -// }); -// }); - -// it('should NOT be able to call Node.js API in a new window', () => { -// env.addClientCommands(this.app.client); -// const client = this.app.client; -// return this.app.client. -// windowByIndex(1). // in the first webview -// execute(() => { -// open_window(); -// }). -// waitUntil(() => { -// return client.windowHandles().then((handles) => { -// return handles.value.length === 4; -// }); -// }, 5000, 'expected a new window'). -// windowByIndex(3).isNodeEnabled().then((enabled) => { -// enabled.should.be.false; -// }); -// }); - -// it('should NOT be able to call eval() in any window', () => { -// env.addClientCommands(this.app.client); -// const tryEval = (index) => { -// return this.app.client. -// windowByIndex(index). -// execute(() => { -// return eval('1 + 1'); -// }).then((result) => { -// throw new Error(`Promise was unexpectedly fulfilled (result: ${result})`); -// }, (error) => { -// (error !== null).should.be.true; -// }); -// }; -// const tryEvalInSettingsPage = () => { -// return this.app.client. -// windowByIndex(0). -// loadSettingsPage(). -// execute(() => { -// return eval('1 + 1'); -// }).then((result) => { -// throw new Error(`Promise was unexpectedly fulfilled (result: ${result})`); -// }, (error) => { -// (error !== null).should.be.true; -// }); -// }; -// return Promise.all([ -// tryEval(0), -// tryEvalInSettingsPage(), -// ]); -// }); -// }); diff --git a/test/specs/spellchecker_test.js b/test/specs/spellchecker_test.js deleted file mode 100644 index 189e4f32..00000000 --- a/test/specs/spellchecker_test.js +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2015-2016 Yuya Ochiai -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. -//import path from 'path'; - -// TODO: reenable with the new spellchecker - -// describe('main/Spellchecker.js', function() { -// describe('getSpellCheckerLocale()', () => { -// it('should return recognized locale', () => { -// // SpellChecker.getSpellCheckerLocale('en').should.equal('en-US'); -// // SpellChecker.getSpellCheckerLocale('en-US').should.equal('en-US'); - -// // SpellChecker.getSpellCheckerLocale('fr').should.equal('fr-FR'); -// // SpellChecker.getSpellCheckerLocale('fr-FR').should.equal('fr-FR'); - -// // SpellChecker.getSpellCheckerLocale('de').should.equal('de-DE'); -// // SpellChecker.getSpellCheckerLocale('de-DE').should.equal('de-DE'); - -// // SpellChecker.getSpellCheckerLocale('es').should.equal('es-ES'); -// // SpellChecker.getSpellCheckerLocale('es-ES').should.equal('es-ES'); - -// // SpellChecker.getSpellCheckerLocale('nl').should.equal('nl-NL'); -// // SpellChecker.getSpellCheckerLocale('nl-NL').should.equal('nl-NL'); - -// // SpellChecker.getSpellCheckerLocale('pl').should.equal('pl-PL'); -// // SpellChecker.getSpellCheckerLocale('pl-PL').should.equal('pl-PL'); -// // SpellChecker.getSpellCheckerLocale('pt').should.equal('pt-BR'); -// // SpellChecker.getSpellCheckerLocale('pt-BR').should.equal('pt-BR'); - -// // SpellChecker.getSpellCheckerLocale('ja').should.equal('en-US'); -// // SpellChecker.getSpellCheckerLocale('ja-JP').should.equal('en-US'); - -// // SpellChecker.getSpellCheckerLocale('it').should.equal('it-IT'); -// // SpellChecker.getSpellCheckerLocale('it-IT').should.equal('it-IT'); -// }); -// }); - -// describe('en-US', function() { -// const spellchecker = null; - -// // before(function(done) { -// // // spellchecker = new SpellChecker( -// // // 'en-US', -// // // path.resolve(__dirname, '../../src/node_modules/simple-spellchecker/dict'), -// // // done -// // // ); -// // }); - -// it('should spellcheck', function() { -// // https://github.com/jfmdev/simple-spellchecker/issues/3 -// spellchecker.spellCheck('spell').should.equal(true); -// spellchecker.spellCheck('spel').should.equal(false); -// spellchecker.spellCheck('December').should.equal(true); -// spellchecker.spellCheck('december').should.equal(true); -// spellchecker.spellCheck('English').should.equal(true); -// spellchecker.spellCheck('Japan').should.equal(true); -// }); - -// it('should allow contractions', function() { -// spellchecker.spellCheck("shouldn't").should.equal(true); -// spellchecker.spellCheck('shouldn').should.equal(true); -// }); - -// it('should allow numerals', function() { -// spellchecker.spellCheck('1').should.equal(true); -// spellchecker.spellCheck('-100').should.equal(true); -// spellchecker.spellCheck('3.14').should.equal(true); -// }); - -// it('should allow "Mattermost"', function() { -// spellchecker.spellCheck('Mattermost').should.equal(true); -// spellchecker.spellCheck('mattermost').should.equal(true); -// }); - -// it('should give at most the requested number of suggestions', function() { -// // helllo known to give at least 4 suggestions -// spellchecker.getSuggestions('helllo', 4).length.should.be.equal(4); -// spellchecker.getSuggestions('helllo', 1).length.should.be.equal(1); -// }); - -// it('should give suggestions which preserve case of first letter', function() { -// let suggestions = spellchecker.getSuggestions('carr', 4); -// suggestions.length.should.not.be.equal(0); -// let i; -// for (i = 0; i < suggestions.length; i++) { -// suggestions[i].charAt(0).should.be.equal('c'); -// } - -// suggestions = spellchecker.getSuggestions('Carr', 4); -// suggestions.length.should.not.be.equal(0); -// for (i = 0; i < suggestions.length; i++) { -// suggestions[i].charAt(0).should.be.equal('C'); -// } -// }); -// }); - -// describe('en-GB', function() { -// const spellchecker = null; - -// // before(function(done) { -// // spellchecker = new SpellChecker( -// // 'en-GB', -// // path.resolve(__dirname, '../../src/node_modules/simple-spellchecker/dict'), -// // done -// // ); -// // }); - -// it('should allow contractions', function() { -// spellchecker.spellCheck("shouldn't").should.equal(true); -// spellchecker.spellCheck('shouldn').should.equal(true); -// }); -// }); - -// describe('de-DE', function() { -// const spellchecker = null; - -// // before(function(done) { -// // spellchecker = new SpellChecker( -// // 'de-DE', -// // path.resolve(__dirname, '../../src/node_modules/simple-spellchecker/dict'), -// // done -// // ); -// // }); - -// it('should spellcheck', function() { -// spellchecker.spellCheck('Guten').should.equal(true); -// spellchecker.spellCheck('tag').should.equal(true); -// }); - -// it('should allow numerals', function() { -// spellchecker.spellCheck('1').should.equal(true); -// spellchecker.spellCheck('-100').should.equal(true); -// spellchecker.spellCheck('3.14').should.equal(true); -// }); - -// it('should give suggestions which preserve case of first letter', function() { -// let suggestions = spellchecker.getSuggestions('gutenn', 4); -// suggestions.length.should.not.be.equal(0); -// let i; -// for (i = 0; i < suggestions.length; i++) { -// suggestions[i].charAt(0).should.be.equal('g'); -// } - -// suggestions = spellchecker.getSuggestions('Gutenn', 4); -// suggestions.length.should.not.be.equal(0); -// for (i = 0; i < suggestions.length; i++) { -// suggestions[i].charAt(0).should.be.equal('G'); -// } -// }); -// }); -// }); diff --git a/test/specs/window_test.js b/test/specs/window_test.js new file mode 100644 index 00000000..0375a50b --- /dev/null +++ b/test/specs/window_test.js @@ -0,0 +1,67 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +'use strict'; + +const fs = require('fs'); + +const env = require('../modules/environment'); + +describe('window', function desc() { + this.timeout(30000); + + beforeEach(async () => { + env.createTestUserDataDir(); + env.cleanTestConfig(); + }); + + afterEach(async () => { + if (this.app) { + try { + await this.app.close(); + // eslint-disable-next-line no-empty + } catch (err) {} + } + }); + + it.skip('should restore window bounds', async () => { + // TODO: Still fails in CircleCI + // bounds seems to be incorrectly calculated in some environments + // - Windows 10: OK + // - CircleCI: NG + const expectedBounds = {x: 100, y: 200, width: 800, height: 400}; + fs.writeFileSync(env.boundsInfoPath, JSON.stringify(expectedBounds)); + this.app = await env.getApp(); + const mainWindow = await this.app.firstWindow(); + const browserWindow = await this.app.browserWindow(mainWindow); + const bounds = await browserWindow.evaluate((window) => window.getContentBounds()); + bounds.should.deep.equal(expectedBounds); + await this.app.close(); + }); + + it('should NOT restore window bounds if x is located on outside of viewarea', async () => { + // bounds seems to be incorrectly calculated in some environments (e.g. CircleCI) + // - Windows 10: OK + // - CircleCI: NG + fs.writeFileSync(env.boundsInfoPath, JSON.stringify({x: -100000, y: 200, width: 800, height: 400})); + this.app = await env.getApp(); + const mainWindow = await this.app.firstWindow(); + const browserWindow = await this.app.browserWindow(mainWindow); + const bounds = await browserWindow.evaluate((window) => window.getContentBounds()); + bounds.x.should.satisfy((x) => (x > -100000)); + await this.app.close(); + }); + + it('should NOT restore window bounds if y is located on outside of viewarea', async () => { + // bounds seems to be incorrectly calculated in some environments (e.g. CircleCI) + // - Windows 10: OK + // - CircleCI: NG + fs.writeFileSync(env.boundsInfoPath, JSON.stringify({x: 100, y: 200000, width: 800, height: 400})); + this.app = await env.getApp(); + const mainWindow = await this.app.firstWindow(); + const browserWindow = await this.app.browserWindow(mainWindow); + const bounds = await browserWindow.evaluate((window) => window.getContentBounds()); + bounds.y.should.satisfy((y) => (y < 200000)); + await this.app.close(); + }); +}); diff --git a/webpack.config.test.js b/webpack.config.test.js index 12afe928..4c27843a 100644 --- a/webpack.config.test.js +++ b/webpack.config.test.js @@ -38,7 +38,8 @@ module.exports = merge(base, { net: 'require("net")', repl: 'require("repl")', tls: 'require("tls")', - spectron: 'require("spectron")', + playwright: 'require("playwright")', + robotjs: 'require("robotjs")', }, node: { __filename: false,