From b4193b8c68575f8d8d55cb4dcb15ff344d6e1a05 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Tue, 30 Mar 2021 10:30:38 -0700 Subject: [PATCH 01/15] feat: add jest-playwright and packages --- test/jest.e2e.config.ts | 1 + test/package.json | 6 + test/yarn.lock | 588 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 581 insertions(+), 14 deletions(-) diff --git a/test/jest.e2e.config.ts b/test/jest.e2e.config.ts index 9c678acb..e2a7a144 100644 --- a/test/jest.e2e.config.ts +++ b/test/jest.e2e.config.ts @@ -2,6 +2,7 @@ import type { Config } from "@jest/types" const config: Config.InitialOptions = { + preset: "jest-playwright-preset", transform: { "^.+\\.ts$": "/node_modules/ts-jest", }, diff --git a/test/package.json b/test/package.json index dfd9f9f1..73da131a 100644 --- a/test/package.json +++ b/test/package.json @@ -12,5 +12,11 @@ "playwright": "^1.8.0", "supertest": "^6.1.1", "ts-jest": "^26.4.4" + }, + "dependencies": { + "jest-playwright-preset": "^1.5.1", + "playwright-chromium": "^1.10.0", + "playwright-firefox": "^1.10.0", + "playwright-webkit": "^1.10.0" } } diff --git a/test/yarn.lock b/test/yarn.lock index 4f6ae7ab..e1ce0de6 100644 --- a/test/yarn.lock +++ b/test/yarn.lock @@ -278,6 +278,18 @@ exec-sh "^0.3.2" minimist "^1.2.0" +"@hapi/hoek@^9.0.0": + version "9.1.1" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.1.1.tgz#9daf5745156fd84b8e9889a2dc721f0c58e894aa" + integrity sha512-CAEbWH7OIur6jEOzaai83jq3FmKmv4PmX1JYfs9IrYcGEVI/lyL1EXJGCj7eFVJ0bg5QR8LMxBlEtA+xKiLpFw== + +"@hapi/topo@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.0.0.tgz#c19af8577fa393a06e9c77b60995af959be721e7" + integrity sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw== + dependencies: + "@hapi/hoek" "^9.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -465,6 +477,23 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@sideway/address@^4.1.0": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.1.tgz#9e321e74310963fdf8eebfbee09c7bd69972de4d" + integrity sha512-+I5aaQr3m0OAmMr7RQ3fR9zx55sejEYR2BFJaxL+zT3VM2611X0SHvPWIbAUBZVTn/YzYKbV8gJ2oT/QELknfQ== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" + integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + "@sinonjs/commons@^1.7.0": version "1.8.2" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.2.tgz#858f5c4b48d80778fde4b9d541f27edc0d56488b" @@ -613,6 +642,11 @@ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.0.tgz#fef1904e4668b6e5ecee60c52cc6a078ffa6697d" integrity sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A== +"@types/wait-on@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@types/wait-on/-/wait-on-5.2.0.tgz#f9096b7bd0c9c03052d6d402ae5cd51714480b2d" + integrity sha512-3+jsMyPm8aot1mqDUDLOl+dejPvpysUUoUXD6CCRY20MNNhcjEfvdcBnGdnk7DEYs9Hr16ubGJA/9/QW0Df/9g== + "@types/yargs-parser@*": version "20.2.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9" @@ -662,6 +696,14 @@ agent-base@6: dependencies: debug "4" +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + ajv@^6.12.3: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -714,6 +756,18 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" +append-transform@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" + integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== + dependencies: + default-require-extensions "^3.0.0" + +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -778,6 +832,13 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== +axios@^0.21.1: + version "0.21.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" + integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== + dependencies: + follow-redirects "^1.10.0" + babel-jest@^26.6.3: version "26.6.3" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" @@ -939,6 +1000,16 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +caching-transform@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" + integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== + dependencies: + hasha "^5.0.0" + make-dir "^3.0.0" + package-hash "^4.0.0" + write-file-atomic "^3.0.0" + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -966,7 +1037,7 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chalk@^2.0.0: +chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -975,7 +1046,7 @@ chalk@^2.0.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== @@ -1008,6 +1079,11 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + cliui@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" @@ -1066,11 +1142,26 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +commander@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + +commander@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== + commander@^6.1.0: version "6.2.1" resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + component-emitter@^1.2.1, component-emitter@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -1140,6 +1231,14 @@ cssstyle@^2.2.0: dependencies: cssom "~0.3.6" +cwd@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/cwd/-/cwd-0.10.0.tgz#172400694057c22a13b0cf16162c7e4b7a7fe567" + integrity sha1-FyQAaUBXwioTsM8WFix+S3p/5Wc= + dependencies: + find-pkg "^0.1.2" + fs-exists-sync "^0.1.0" + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -1185,6 +1284,11 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= + deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -1195,6 +1299,13 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== +default-require-extensions@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.0.tgz#e03f93aac9b2b6443fc52e5e4a37b3ad9ad8df96" + integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg== + dependencies: + strip-bom "^4.0.0" + define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" @@ -1271,6 +1382,11 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +es6-error@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -1359,6 +1475,18 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" +expand-tilde@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-1.2.2.tgz#0b81eba897e5a3d31d1c3d102f8f01441e559449" + integrity sha1-C4HrqJflo9MdHD0QL48BRB5VlEk= + dependencies: + os-homedir "^1.0.1" + +expect-playwright@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/expect-playwright/-/expect-playwright-0.3.3.tgz#575438cb221fb46ade1404b10e8e643974b731e7" + integrity sha512-uoeyx2D5LawJdziMdweOp6cnZzFOOPT9VvPG6gOh6YC7N9pU0k2KpVlRiz/Vc/fFBiGUNNeJq2Aq+9GJ65Nfrw== + expect@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" @@ -1477,6 +1605,39 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +find-cache-dir@^3.2.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + +find-file-up@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/find-file-up/-/find-file-up-0.1.3.tgz#cf68091bcf9f300a40da411b37da5cce5a2fbea0" + integrity sha1-z2gJG8+fMApA2kEbN9pczlovvqA= + dependencies: + fs-exists-sync "^0.1.0" + resolve-dir "^0.1.0" + +find-pkg@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/find-pkg/-/find-pkg-0.1.2.tgz#1bdc22c06e36365532e2a248046854b9788da557" + integrity sha1-G9wiwG42NlUy4qJIBGhUuXiNpVc= + dependencies: + find-file-up "^0.1.2" + +find-process@^1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/find-process/-/find-process-1.4.4.tgz#52820561162fda0d1feef9aed5d56b3787f0fd6e" + integrity sha512-rRSuT1LE4b+BFK588D2V8/VG9liW0Ark1XJgroxZXI0LtwmQJOb490DvDYvbm+Hek9ETFzTutGfJ90gumITPhQ== + dependencies: + chalk "^4.0.0" + commander "^5.1.0" + debug "^4.1.1" + find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -1485,11 +1646,24 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +follow-redirects@^1.10.0: + version "1.13.3" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267" + integrity sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA== + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= +foreground-child@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" + integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^3.0.2" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -1525,6 +1699,16 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" +fromentries@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.3.2.tgz#e4bca6808816bf8f93b52750f1127f5a6fd86e3a" + integrity sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg== + +fs-exists-sync@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" + integrity sha1-mC1ok6+RjnLQjeyehnP/K1qNat0= + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1581,7 +1765,7 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -1593,11 +1777,34 @@ glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" +global-modules@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-0.2.3.tgz#ea5a3bed42c6d6ce995a4f8a1269b5dae223828d" + integrity sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0= + dependencies: + global-prefix "^0.1.4" + is-windows "^0.2.0" + +global-prefix@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-0.1.5.tgz#8d3bc6b8da3ca8112a160d8d496ff0462bfef78f" + integrity sha1-jTvGuNo8qBEqFg2NSW/wRiv+948= + dependencies: + homedir-polyfill "^1.0.0" + ini "^1.3.4" + is-windows "^0.2.0" + which "^1.2.12" + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +graceful-fs@^4.1.15: + version "4.2.6" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" + integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== + graceful-fs@^4.2.4: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" @@ -1669,6 +1876,21 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hasha@^5.0.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz#a48477989b3b327aea3c04f53096d816d97522a1" + integrity sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ== + dependencies: + is-stream "^2.0.0" + type-fest "^0.8.0" + +homedir-polyfill@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== + dependencies: + parse-passwd "^1.0.0" + hosted-git-info@^2.1.4: version "2.8.8" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" @@ -1728,6 +1950,11 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -1741,6 +1968,11 @@ inherits@2, inherits@^2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ini@^1.3.4: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" @@ -1882,6 +2114,11 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= +is-windows@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" + integrity sha1-3hqm1j6indJIc3tp8f+LgALSEIw= + is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -1921,11 +2158,18 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -istanbul-lib-coverage@^3.0.0: +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1: version "3.0.0" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== +istanbul-lib-hook@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" + integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== + dependencies: + append-transform "^2.0.0" + istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" @@ -1936,6 +2180,19 @@ istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: istanbul-lib-coverage "^3.0.0" semver "^6.3.0" +istanbul-lib-processinfo@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz#e1426514662244b2f25df728e8fd1ba35fe53b9c" + integrity sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw== + dependencies: + archy "^1.0.0" + cross-spawn "^7.0.0" + istanbul-lib-coverage "^3.0.0-alpha.1" + make-dir "^3.0.0" + p-map "^3.0.0" + rimraf "^3.0.0" + uuid "^3.3.3" + istanbul-lib-report@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" @@ -1971,6 +2228,33 @@ jest-changed-files@^26.6.2: execa "^4.0.0" throat "^5.0.0" +jest-circus@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-26.6.3.tgz#3cc7ef2a6a3787e5d7bfbe2c72d83262154053e7" + integrity sha512-ACrpWZGcQMpbv13XbzRzpytEJlilP/Su0JtNCi5r/xLpOUhnaIJr8leYYpLEMgPFURZISEHrnnpmB54Q/UziPw== + dependencies: + "@babel/traverse" "^7.1.0" + "@jest/environment" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/babel__traverse" "^7.0.4" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^0.7.0" + expect "^26.6.2" + is-generator-fn "^2.0.0" + jest-each "^26.6.2" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-runner "^26.6.3" + jest-runtime "^26.6.3" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + pretty-format "^26.6.2" + stack-utils "^2.0.2" + throat "^5.0.0" + jest-cli@^26.6.3: version "26.6.3" resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.6.3.tgz#43117cfef24bc4cd691a174a8796a532e135e92a" @@ -2158,11 +2442,42 @@ jest-mock@^26.6.2: "@jest/types" "^26.6.2" "@types/node" "*" +jest-playwright-preset@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/jest-playwright-preset/-/jest-playwright-preset-1.5.1.tgz#d74a338ea99b8dd6cafce59471a27803c5b331d7" + integrity sha512-zsFAe61V72vSLkd1fCcf7YbHmbdAB82SLBdUuCUF43aODIojshQEDF88KdWL9P+4JQ+DvEABT+6sFX4sY0rR2w== + dependencies: + expect-playwright "^0.3.3" + jest-circus "^26.6.3" + jest-environment-node "^26.6.2" + jest-process-manager "^0.2.9" + jest-runner "^26.6.3" + nyc "^15.1.0" + playwright-core ">=1.2.0" + rimraf "^3.0.2" + uuid "^8.3.2" + jest-pnp-resolver@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== +jest-process-manager@^0.2.9: + version "0.2.9" + resolved "https://registry.yarnpkg.com/jest-process-manager/-/jest-process-manager-0.2.9.tgz#4bfa99dda115a2bae1cd0e645f78e3d84e780575" + integrity sha512-IKVdOSz1NLwKg9HTeyEDn63waMvKK6wcS+tCarGquNIktlXt4zAW2cfJ9vAA/xBcidWYKOPXHvy1l1N8qfw3Ww== + dependencies: + "@types/wait-on" "^5.2.0" + chalk "^4.1.0" + cwd "^0.10.0" + exit "^0.1.2" + find-process "^1.4.4" + prompts "^2.4.0" + signal-exit "^3.0.3" + spawnd "^4.4.0" + tree-kill "^1.2.2" + wait-on "^5.2.1" + jest-regex-util@^26.0.0: version "26.0.0" resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" @@ -2335,6 +2650,17 @@ jest@^26.6.3: import-local "^3.0.2" jest-cli "^26.6.3" +joi@^17.3.0: + version "17.4.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.4.0.tgz#b5c2277c8519e016316e49ababd41a1908d9ef20" + integrity sha512-F4WiW2xaV6wc1jxete70Rw4V/VuMd6IN+a5ilZsxG4uYtUXWu2kq9W5P2dz30e7Gmw8RCbY/u/uk+dMPma9tAg== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.0" + "@sideway/formula" "^3.0.0" + "@sideway/pinpoint" "^2.0.0" + jpeg-js@^0.4.2: version "0.4.3" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.3.tgz#6158e09f1983ad773813704be80680550eff977b" @@ -2486,6 +2812,11 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +lodash.flattendeep@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" + integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= + lodash.memoize@4.x: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -2501,6 +2832,11 @@ lodash@^4.17.19: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -2508,7 +2844,7 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -make-dir@^3.0.0: +make-dir@^3.0.0, make-dir@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== @@ -2687,6 +3023,13 @@ node-notifier@^8.0.0: uuid "^8.3.0" which "^2.0.2" +node-preload@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" + integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== + dependencies: + process-on-spawn "^1.0.0" + normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -2728,6 +3071,39 @@ nwsapi@^2.2.0: resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== +nyc@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.1.0.tgz#1335dae12ddc87b6e249d5a1994ca4bdaea75f02" + integrity sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A== + dependencies: + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + caching-transform "^4.0.0" + convert-source-map "^1.7.0" + decamelize "^1.2.0" + find-cache-dir "^3.2.0" + find-up "^4.1.0" + foreground-child "^2.0.0" + get-package-type "^0.1.0" + glob "^7.1.6" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-hook "^3.0.0" + istanbul-lib-instrument "^4.0.0" + istanbul-lib-processinfo "^2.0.2" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + make-dir "^3.0.0" + node-preload "^0.2.1" + p-map "^3.0.0" + process-on-spawn "^1.0.0" + resolve-from "^5.0.0" + rimraf "^3.0.0" + signal-exit "^3.0.2" + spawn-wrap "^2.0.0" + test-exclude "^6.0.0" + yargs "^15.0.2" + oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" @@ -2782,6 +3158,11 @@ optionator@^0.8.1: type-check "~0.3.2" word-wrap "~1.2.3" +os-homedir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + p-each-series@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a" @@ -2806,11 +3187,28 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +package-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" + integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== + dependencies: + graceful-fs "^4.1.15" + hasha "^5.0.0" + lodash.flattendeep "^4.4.0" + release-zalgo "^1.0.0" + parse-json@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" @@ -2821,6 +3219,11 @@ parse-json@^5.0.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= + parse5@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" @@ -2878,13 +3281,89 @@ pirates@^4.0.1: dependencies: node-modules-regexp "^1.0.0" -pkg-dir@^4.2.0: +pkg-dir@^4.1.0, pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" +playwright-chromium@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/playwright-chromium/-/playwright-chromium-1.10.0.tgz#df0e65e42cdda66b599df38d062d9cd8c2dea09c" + integrity sha512-ry/60/YKGJfrnaS7j5C3+xmA2DAMv6pBE351FoTHe4Llq0WU92IL0rBYK3TkK3PzSHYtp1KdCRsRjDnJhImA3g== + 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.3.1" + +playwright-core@>=1.2.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.10.0.tgz#0ed3590ddf97ec4a5fd4baef40346e2d8e2f19ba" + integrity sha512-SDA5KPwnJJSfnNX/b7h8y0ChwBmcbbcCofYXkZGMVuzXZsmHPGLOBRhgkwN2nzJ10Ezf4cd1OcVOeOLKPxjeRg== + 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.3.1" + +playwright-firefox@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/playwright-firefox/-/playwright-firefox-1.10.0.tgz#842f6f93ebdced83eecbd23d6820cad930686728" + integrity sha512-TR7Vyw9PgS4KtbSOIUGqNa20gJxjpRHK6IQv4oDhgehpW/YnCjqxe5ylI9eLrzzYPUPsoyD7bZRxSZDtrcCTLA== + 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.3.1" + +playwright-webkit@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/playwright-webkit/-/playwright-webkit-1.10.0.tgz#0d32f73c5ab3296fb9114b053b0cd1d35597b2c4" + integrity sha512-Dql/wJQ+aFgL3/HHMv9UfVAd3+pzQluLdDHnG7eX8PWLK80ly4idyQO0HYRjwwvoZuyx1G1rA+kuh7jtn7OfHg== + 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.3.1" + playwright@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.8.0.tgz#8eca2250967ee892b9fdfec44e2358455ab0f8e3" @@ -2928,12 +3407,19 @@ pretty-format@^26.0.0, pretty-format@^26.6.2: ansi-styles "^4.0.0" react-is "^17.0.1" +process-on-spawn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.0.0.tgz#95b05a23073d30a17acfdc92a440efd2baefdc93" + integrity sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg== + dependencies: + fromentries "^1.2.0" + progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -prompts@^2.0.1: +prompts@^2.0.1, prompts@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.0.tgz#4aa5de0723a231d1ee9121c40fdf663df73f61d7" integrity sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ== @@ -3024,6 +3510,13 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +release-zalgo@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" + integrity sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA= + dependencies: + es6-error "^4.0.1" + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -3098,6 +3591,14 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" +resolve-dir@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-0.1.1.tgz#b219259a5602fac5c5c496ad894a6e8cc430261e" + integrity sha1-shklmlYC+sXFxJatiUpujMQwJh4= + dependencies: + expand-tilde "^1.2.2" + global-modules "^0.2.3" + resolve-from@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" @@ -3138,6 +3639,13 @@ rsvp@^4.8.4: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== +rxjs@^6.6.3: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" @@ -3243,7 +3751,7 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -signal-exit@^3.0.0, signal-exit@^3.0.2: +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== @@ -3327,6 +3835,28 @@ source-map@^0.7.3: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== +spawn-wrap@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" + integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== + dependencies: + foreground-child "^2.0.0" + is-windows "^1.0.2" + make-dir "^3.0.0" + rimraf "^3.0.0" + signal-exit "^3.0.2" + which "^2.0.1" + +spawnd@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/spawnd/-/spawnd-4.4.0.tgz#bb52c5b34a22e3225ae1d3acb873b2cd58af0886" + integrity sha512-jLPOfB6QOEgMOQY15Z6+lwZEhH3F5ncXxIaZ7WHPIapwNNLyjrs61okj3VJ3K6tmP5TZ6cO0VAu9rEY4MD4YQg== + dependencies: + exit "^0.1.2" + signal-exit "^3.0.2" + tree-kill "^1.2.2" + wait-port "^0.2.7" + spdx-correct@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" @@ -3380,7 +3910,7 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" -stack-utils@^2.0.2: +stack-utils@^2.0.2, stack-utils@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277" integrity sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw== @@ -3586,6 +4116,11 @@ tr46@^2.0.2: dependencies: punycode "^2.1.1" +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + ts-jest@^26.4.4: version "26.4.4" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.4.4.tgz#61f13fb21ab400853c532270e52cc0ed7e502c49" @@ -3603,6 +4138,11 @@ ts-jest@^26.4.4: semver "7.x" yargs-parser "20.x" +tslib@^1.9.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -3637,7 +4177,7 @@ type-fest@^0.6.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== -type-fest@^0.8.1: +type-fest@^0.8.0, type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== @@ -3689,12 +4229,12 @@ util-deprecate@^1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -uuid@^3.3.2: +uuid@^3.3.2, uuid@^3.3.3: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@^8.3.0: +uuid@^8.3.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -3739,6 +4279,26 @@ w3c-xmlserializer@^2.0.0: dependencies: xml-name-validator "^3.0.0" +wait-on@^5.2.1: + version "5.3.0" + resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-5.3.0.tgz#584e17d4b3fe7b46ac2b9f8e5e102c005c2776c7" + integrity sha512-DwrHrnTK+/0QFaB9a8Ol5Lna3k7WvUR4jzSKmz0YaPBpuN2sACyiPVKVfj6ejnjcajAcvn3wlbTyMIn9AZouOg== + dependencies: + axios "^0.21.1" + joi "^17.3.0" + lodash "^4.17.21" + minimist "^1.2.5" + rxjs "^6.6.3" + +wait-port@^0.2.7: + version "0.2.9" + resolved "https://registry.yarnpkg.com/wait-port/-/wait-port-0.2.9.tgz#3905cf271b5dbe37a85c03b85b418b81cb24ee55" + integrity sha512-hQ/cVKsNqGZ/UbZB/oakOGFqic00YAMM5/PEj3Bt4vKarv2jWIWzDbqlwT94qMs/exAQAsvMOq99sZblV92zxQ== + dependencies: + chalk "^2.4.2" + commander "^3.0.2" + debug "^4.1.1" + walker@^1.0.7, walker@~1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" @@ -3782,7 +4342,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@^1.2.9: +which@^1.2.12, which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -3863,7 +4423,7 @@ yargs-parser@^18.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs@^15.4.1: +yargs@^15.0.2, yargs@^15.4.1: version "15.4.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== From 3db19843e29c574f781abe1b61db43b6035deec5 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Tue, 30 Mar 2021 10:35:18 -0700 Subject: [PATCH 02/15] chore: add eslint plugin for jest-playwright --- .eslintrc.yaml | 11 ++++++++++- package.json | 1 + test/jest.e2e.config.ts | 8 +++++++- yarn.lock | 5 +++++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 63515520..b889a5e7 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -16,6 +16,9 @@ extends: - plugin:import/typescript - plugin:prettier/recommended - prettier # Removes eslint rules that conflict with prettier. + # Recommended by jest-playwright + # https://github.com/playwright-community/jest-playwright#globals + - plugin:jest-playwright/recommended rules: # Sometimes you need to add args to implement a function signature even @@ -32,7 +35,13 @@ rules: "@typescript-eslint/no-extra-semi": off eqeqeq: error import/order: - [error, { alphabetize: { order: "asc" }, groups: [["builtin", "external", "internal"], "parent", "sibling"] }] + [ + error, + { + alphabetize: { order: "asc" }, + groups: [["builtin", "external", "internal"], "parent", "sibling"], + }, + ] no-async-promise-executor: off # This isn't a real module, just types, which apparently doesn't resolve. import/no-unresolved: [error, { ignore: ["express-serve-static-core"] }] diff --git a/package.json b/package.json index 059c5337..0d94c3aa 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "eslint-config-prettier": "^8.1.0", "eslint-import-resolver-alias": "^1.1.2", "eslint-plugin-import": "^2.18.2", + "eslint-plugin-jest-playwright": "^0.2.1", "eslint-plugin-prettier": "^3.1.0", "istanbul-badges-readme": "^1.2.0", "leaked-handles": "^5.2.0", diff --git a/test/jest.e2e.config.ts b/test/jest.e2e.config.ts index e2a7a144..6f0fa73a 100644 --- a/test/jest.e2e.config.ts +++ b/test/jest.e2e.config.ts @@ -7,7 +7,13 @@ const config: Config.InitialOptions = { "^.+\\.ts$": "/node_modules/ts-jest", }, globalSetup: "/utils/globalSetup.ts", - testEnvironment: "node", + testEnvironmentOptions: { + "jest-playwright": { + // TODO enable on webkit as well + // waiting on https://github.com/playwright-community/jest-playwright/issues/659 + browsers: ["chromium", "firefox"], + }, + }, testPathIgnorePatterns: ["/node_modules/", "/lib/", "/out/", "test/unit"], testTimeout: 30000, modulePathIgnorePatterns: [ diff --git a/yarn.lock b/yarn.lock index c96f175c..0bb8e9de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3164,6 +3164,11 @@ eslint-plugin-import@^2.18.2: resolve "^1.17.0" tsconfig-paths "^3.9.0" +eslint-plugin-jest-playwright@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest-playwright/-/eslint-plugin-jest-playwright-0.2.1.tgz#8778fee9d5915132a03d94370d3eea0a7ddd08f3" + integrity sha512-BicKUJUpVPsLbHN8c5hYaZn6pv8PCMjBGHXUfvlY1p75fh4APVfX2gTK14HuiR8/Bv3fKBQu5MTaqCro4E3OHg== + eslint-plugin-prettier@^3.1.0: version "3.3.1" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz#7079cfa2497078905011e6f82e8dd8453d1371b7" From 6b3db06c7aa029d0c1155e24c2e43a0bc34c8074 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Tue, 30 Mar 2021 11:35:36 -0700 Subject: [PATCH 03/15] feat: add new e2e test to test browser --- test/e2e/browser.test.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 test/e2e/browser.test.ts diff --git a/test/e2e/browser.test.ts b/test/e2e/browser.test.ts new file mode 100644 index 00000000..0801c9e9 --- /dev/null +++ b/test/e2e/browser.test.ts @@ -0,0 +1,16 @@ +/// + +beforeAll(async () => { + await page.goto("https://whatismybrowser.com/") +}) + +test("should display correct browser", async () => { + const browser = await page.$eval(".string-major", (el) => el.innerHTML) + + const displayNames = { + chromium: "Chrome", + firefox: "Firefox", + webkit: "Safari", + } + expect(browser).toContain(displayNames[browserName]) +}) From bd55cb94becc5953f16945fffa9057e993d5ee59 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Tue, 30 Mar 2021 12:24:51 -0700 Subject: [PATCH 04/15] refactor: move test dir to jest e2e config --- test/e2e/browser.test.ts | 32 +++++++++++++++++++++----------- test/e2e/logout.test.ts | 6 ++---- test/e2e/openHelpAbout.test.ts | 3 +-- test/jest.e2e.config.ts | 8 ++++++++ test/utils/constants.ts | 1 - 5 files changed, 32 insertions(+), 18 deletions(-) diff --git a/test/e2e/browser.test.ts b/test/e2e/browser.test.ts index 0801c9e9..27e2f165 100644 --- a/test/e2e/browser.test.ts +++ b/test/e2e/browser.test.ts @@ -1,16 +1,26 @@ /// -beforeAll(async () => { - await page.goto("https://whatismybrowser.com/") -}) +// This test is for nothing more than to make sure +// tests are running in multiple browsers +describe("Browser gutcheck", () => { + beforeEach(async () => { + await jestPlaywright.resetBrowser() + }) -test("should display correct browser", async () => { - const browser = await page.$eval(".string-major", (el) => el.innerHTML) + test("should display correct browser", async () => { + const displayNames = { + chromium: "Chrome", + firefox: "Firefox", + webkit: "Safari", + } + const userAgent = await page.evaluate("navigator.userAgent") - const displayNames = { - chromium: "Chrome", - firefox: "Firefox", - webkit: "Safari", - } - expect(browser).toContain(displayNames[browserName]) + if (browserName === "firefox") { + expect(userAgent).toContain(displayNames[browserName]) + } + + if (browserName === "chromium") { + expect(userAgent).toContain(displayNames[browserName]) + } + }) }) diff --git a/test/e2e/logout.test.ts b/test/e2e/logout.test.ts index 74df799a..da26ece3 100644 --- a/test/e2e/logout.test.ts +++ b/test/e2e/logout.test.ts @@ -1,5 +1,5 @@ import { chromium, Page, Browser, BrowserContext } from "playwright" -import { CODE_SERVER_ADDRESS, PASSWORD, E2E_VIDEO_DIR } from "../utils/constants" +import { CODE_SERVER_ADDRESS, PASSWORD } from "../utils/constants" describe("logout", () => { let browser: Browser @@ -8,9 +8,7 @@ describe("logout", () => { beforeAll(async () => { browser = await chromium.launch() - context = await browser.newContext({ - recordVideo: { dir: E2E_VIDEO_DIR }, - }) + context = await browser.newContext() }) afterAll(async () => { diff --git a/test/e2e/openHelpAbout.test.ts b/test/e2e/openHelpAbout.test.ts index 2a6ac57b..31bad066 100644 --- a/test/e2e/openHelpAbout.test.ts +++ b/test/e2e/openHelpAbout.test.ts @@ -1,6 +1,6 @@ import { chromium, Page, Browser, BrowserContext, Cookie } from "playwright" import { hash } from "../../src/node/util" -import { CODE_SERVER_ADDRESS, PASSWORD, STORAGE, E2E_VIDEO_DIR } from "../utils/constants" +import { CODE_SERVER_ADDRESS, PASSWORD, STORAGE } from "../utils/constants" import { createCookieIfDoesntExist } from "../utils/helpers" describe("Open Help > About", () => { @@ -45,7 +45,6 @@ describe("Open Help > About", () => { context = await browser.newContext({ storageState: { cookies: maybeUpdatedCookies }, - recordVideo: { dir: E2E_VIDEO_DIR }, }) }) diff --git a/test/jest.e2e.config.ts b/test/jest.e2e.config.ts index 6f0fa73a..dd7af6f6 100644 --- a/test/jest.e2e.config.ts +++ b/test/jest.e2e.config.ts @@ -12,6 +12,14 @@ const config: Config.InitialOptions = { // TODO enable on webkit as well // waiting on https://github.com/playwright-community/jest-playwright/issues/659 browsers: ["chromium", "firefox"], + // If there's a page error, we don't exit + // i.e. something logged in the console + exitOnPageError: false, + contextOptions: { + recordVideo: { + dir: "./test/e2e/videos", + }, + }, }, }, testPathIgnorePatterns: ["/node_modules/", "/lib/", "/out/", "test/unit"], diff --git a/test/utils/constants.ts b/test/utils/constants.ts index 9a750892..ac2250e1 100644 --- a/test/utils/constants.ts +++ b/test/utils/constants.ts @@ -1,4 +1,3 @@ export const CODE_SERVER_ADDRESS = process.env.CODE_SERVER_ADDRESS || "http://localhost:8080" export const PASSWORD = process.env.PASSWORD || "e45432jklfdsab" export const STORAGE = process.env.STORAGE || "" -export const E2E_VIDEO_DIR = "./test/e2e/videos" From 1782f2a2390afa09e73a3e8b363c486a0489d2f4 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Tue, 30 Mar 2021 16:07:51 -0700 Subject: [PATCH 05/15] refactor: rename e2e test to loginPage --- test/e2e/browser.test.ts | 8 ++++++-- test/e2e/e2e.test.ts | 24 ------------------------ test/e2e/loginPage.test.ts | 15 +++++++++++++++ test/jest.e2e.config.ts | 8 +++++--- 4 files changed, 26 insertions(+), 29 deletions(-) delete mode 100644 test/e2e/e2e.test.ts create mode 100644 test/e2e/loginPage.test.ts diff --git a/test/e2e/browser.test.ts b/test/e2e/browser.test.ts index 27e2f165..978c403d 100644 --- a/test/e2e/browser.test.ts +++ b/test/e2e/browser.test.ts @@ -7,7 +7,7 @@ describe("Browser gutcheck", () => { await jestPlaywright.resetBrowser() }) - test("should display correct browser", async () => { + test("should display correct browser based on userAgent", async () => { const displayNames = { chromium: "Chrome", firefox: "Firefox", @@ -15,11 +15,15 @@ describe("Browser gutcheck", () => { } const userAgent = await page.evaluate("navigator.userAgent") + if (browserName === "chromium") { + expect(userAgent).toContain(displayNames[browserName]) + } + if (browserName === "firefox") { expect(userAgent).toContain(displayNames[browserName]) } - if (browserName === "chromium") { + if (browserName === "webkit") { expect(userAgent).toContain(displayNames[browserName]) } }) diff --git a/test/e2e/e2e.test.ts b/test/e2e/e2e.test.ts deleted file mode 100644 index 4e60c6eb..00000000 --- a/test/e2e/e2e.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { chromium, Page, Browser } from "playwright" -import { CODE_SERVER_ADDRESS } from "../utils/constants" - -let browser: Browser -let page: Page - -beforeAll(async () => { - browser = await chromium.launch() -}) -afterAll(async () => { - await browser.close() -}) -beforeEach(async () => { - page = await browser.newPage() -}) -afterEach(async () => { - await page.close() -}) - -it("should see the login page", async () => { - await page.goto(CODE_SERVER_ADDRESS) - // It should send us to the login page - expect(await page.title()).toBe("code-server login") -}) diff --git a/test/e2e/loginPage.test.ts b/test/e2e/loginPage.test.ts new file mode 100644 index 00000000..ef85f8fc --- /dev/null +++ b/test/e2e/loginPage.test.ts @@ -0,0 +1,15 @@ +/// + +import { CODE_SERVER_ADDRESS } from "../utils/constants" + +describe("login page", () => { + beforeEach(async () => { + await jestPlaywright.resetContext() + await page.goto(CODE_SERVER_ADDRESS) + }) + + it("should see the login page", async () => { + // It should send us to the login page + expect(await page.title()).toBe("code-server login") + }) +}) diff --git a/test/jest.e2e.config.ts b/test/jest.e2e.config.ts index dd7af6f6..66653441 100644 --- a/test/jest.e2e.config.ts +++ b/test/jest.e2e.config.ts @@ -9,9 +9,11 @@ const config: Config.InitialOptions = { globalSetup: "/utils/globalSetup.ts", testEnvironmentOptions: { "jest-playwright": { - // TODO enable on webkit as well - // waiting on https://github.com/playwright-community/jest-playwright/issues/659 - browsers: ["chromium", "firefox"], + // TODO(@jsjoeio) enable on webkit and firefox + // waiting on next playwright release + // - https://github.com/microsoft/playwright/issues/6009#event-4536210890 + // - https://github.com/microsoft/playwright/issues/6020 + browsers: ["chromium"], // If there's a page error, we don't exit // i.e. something logged in the console exitOnPageError: false, From 4b703cbd4d339d21f893bf8e1cd1f521c996bc15 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Thu, 1 Apr 2021 10:57:44 -0700 Subject: [PATCH 06/15] refactor: e2e tests based on jest-playwright --- test/e2e/login.test.ts | 28 ++++++---------------------- test/e2e/logout.test.ts | 25 ++++--------------------- test/e2e/openHelpAbout.test.ts | 27 ++++----------------------- test/utils/globalSetup.ts | 4 ++++ 4 files changed, 18 insertions(+), 66 deletions(-) diff --git a/test/e2e/login.test.ts b/test/e2e/login.test.ts index ca098904..1caf40b0 100644 --- a/test/e2e/login.test.ts +++ b/test/e2e/login.test.ts @@ -1,36 +1,20 @@ -import { chromium, Page, Browser, BrowserContext } from "playwright" +/// import { CODE_SERVER_ADDRESS, PASSWORD } from "../utils/constants" describe("login", () => { - let browser: Browser - let page: Page - let context: BrowserContext - - beforeAll(async () => { - browser = await chromium.launch() - context = await browser.newContext() - }) - - afterAll(async () => { - await browser.close() - }) - beforeEach(async () => { - page = await context.newPage() - }) - - afterEach(async () => { - await page.close() - // Remove password from local storage - await context.clearCookies() + await jestPlaywright.resetContext() + await page.goto(CODE_SERVER_ADDRESS) }) it("should be able to login", async () => { - await page.goto(CODE_SERVER_ADDRESS) // Type in password await page.fill(".password", PASSWORD) // Click the submit button and login await page.click(".submit") + // For some reason, it wasn't waiting for the click and navigation before checking + // so adding a timeout ensures that we allow the editor time to load + await page.waitForTimeout(1000) // See the editor const codeServerEditor = await page.isVisible(".monaco-workbench") expect(codeServerEditor).toBeTruthy() diff --git a/test/e2e/logout.test.ts b/test/e2e/logout.test.ts index da26ece3..c717a5f7 100644 --- a/test/e2e/logout.test.ts +++ b/test/e2e/logout.test.ts @@ -1,28 +1,9 @@ -import { chromium, Page, Browser, BrowserContext } from "playwright" +/// import { CODE_SERVER_ADDRESS, PASSWORD } from "../utils/constants" describe("logout", () => { - let browser: Browser - let page: Page - let context: BrowserContext - - beforeAll(async () => { - browser = await chromium.launch() - context = await browser.newContext() - }) - - afterAll(async () => { - await browser.close() - }) - beforeEach(async () => { - page = await context.newPage() - }) - - afterEach(async () => { - await page.close() - // Remove password from local storage - await context.clearCookies() + await jestPlaywright.resetContext() }) it("should be able login and logout", async () => { @@ -31,6 +12,8 @@ describe("logout", () => { await page.fill(".password", PASSWORD) // Click the submit button and login await page.click(".submit") + // Allow time to navigate + await page.waitForTimeout(1000) // See the editor const codeServerEditor = await page.isVisible(".monaco-workbench") expect(codeServerEditor).toBeTruthy() diff --git a/test/e2e/openHelpAbout.test.ts b/test/e2e/openHelpAbout.test.ts index 31bad066..c8830bfe 100644 --- a/test/e2e/openHelpAbout.test.ts +++ b/test/e2e/openHelpAbout.test.ts @@ -1,15 +1,11 @@ -import { chromium, Page, Browser, BrowserContext, Cookie } from "playwright" +/// +import { Cookie } from "playwright" import { hash } from "../../src/node/util" import { CODE_SERVER_ADDRESS, PASSWORD, STORAGE } from "../utils/constants" import { createCookieIfDoesntExist } from "../utils/helpers" describe("Open Help > About", () => { - let browser: Browser - let page: Page - let context: BrowserContext - - beforeAll(async () => { - browser = await chromium.launch() + beforeEach(async () => { // Create a new context with the saved storage state const storageState = JSON.parse(STORAGE) || {} @@ -42,22 +38,7 @@ describe("Open Help > About", () => { // See discussion: https://github.com/cdr/code-server/pull/2648#discussion_r575434946 const maybeUpdatedCookies = createCookieIfDoesntExist(cookies, cookieToStore) - - context = await browser.newContext({ - storageState: { cookies: maybeUpdatedCookies }, - }) - }) - - afterAll(async () => { - // Remove password from local storage - await context.clearCookies() - - await context.close() - await browser.close() - }) - - beforeEach(async () => { - page = await context.newPage() + await jestPlaywright.resetBrowser({ storageState: { cookies: maybeUpdatedCookies } }) }) it("should see a 'Help' then 'About' button in the Application Menu that opens a dialog", async () => { diff --git a/test/utils/globalSetup.ts b/test/utils/globalSetup.ts index 36b242d7..498d21a3 100644 --- a/test/utils/globalSetup.ts +++ b/test/utils/globalSetup.ts @@ -21,6 +21,10 @@ module.exports = async () => { await page.fill(".password", PASSWORD) // Click the submit button and login await page.click(".submit") + // After logging in, we store a cookie in localStorage + // we need to wait a bit to make sure that happens + // before we grab the storage and save it + await page.waitForTimeout(1000) // Save storage state and store as an env variable // More info: https://playwright.dev/docs/auth?_highlight=authe#reuse-authentication-state From 51010e73cb0c39efe06a4e44afd0a41c9e92526d Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Thu, 1 Apr 2021 11:48:23 -0700 Subject: [PATCH 07/15] feat: add test for globalSetup --- test/e2e/globalSetup.test.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 test/e2e/globalSetup.test.ts diff --git a/test/e2e/globalSetup.test.ts b/test/e2e/globalSetup.test.ts new file mode 100644 index 00000000..cfbe512b --- /dev/null +++ b/test/e2e/globalSetup.test.ts @@ -0,0 +1,22 @@ +/// +import { CODE_SERVER_ADDRESS, STORAGE } from "../utils/constants" + +// This test is to make sure the globalSetup works as expected +// meaning globalSetup ran and stored the storageState in STORAGE +describe("globalSetup", () => { + beforeEach(async () => { + // Create a new context with the saved storage state + const storageState = JSON.parse(STORAGE) || {} + console.log("what is storage ", storageState) + await jestPlaywright.resetContext({ storageState }) + await page.goto(CODE_SERVER_ADDRESS) + // code-server takes a second to load + await page.waitForTimeout(1000) + }) + + it("should keep us logged in if we don't reset the browser", async () => { + // See the editor + const codeServerEditor = await page.isVisible(".monaco-workbench") + expect(codeServerEditor).toBeTruthy() + }) +}) From c666b476688e8e50a282ccb19c8ea1e6bc4e1a64 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Thu, 1 Apr 2021 14:52:46 -0700 Subject: [PATCH 08/15] refactor: globalSetup and create cookie manually --- .eslintrc.yaml | 8 +------ test/e2e/globalSetup.test.ts | 6 ++--- test/e2e/login.test.ts | 8 +++---- test/e2e/loginPage.test.ts | 2 +- test/e2e/logout.test.ts | 11 ++++----- test/e2e/openHelpAbout.test.ts | 43 ++++------------------------------ test/utils/globalSetup.ts | 32 +++++++++++++------------ 7 files changed, 33 insertions(+), 77 deletions(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index b889a5e7..f520fd9f 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -35,13 +35,7 @@ rules: "@typescript-eslint/no-extra-semi": off eqeqeq: error import/order: - [ - error, - { - alphabetize: { order: "asc" }, - groups: [["builtin", "external", "internal"], "parent", "sibling"], - }, - ] + [error, { alphabetize: { order: "asc" }, groups: [["builtin", "external", "internal"], "parent", "sibling"] }] no-async-promise-executor: off # This isn't a real module, just types, which apparently doesn't resolve. import/no-unresolved: [error, { ignore: ["express-serve-static-core"] }] diff --git a/test/e2e/globalSetup.test.ts b/test/e2e/globalSetup.test.ts index cfbe512b..ee4b6443 100644 --- a/test/e2e/globalSetup.test.ts +++ b/test/e2e/globalSetup.test.ts @@ -6,12 +6,10 @@ import { CODE_SERVER_ADDRESS, STORAGE } from "../utils/constants" describe("globalSetup", () => { beforeEach(async () => { // Create a new context with the saved storage state + // so we don't have to logged in const storageState = JSON.parse(STORAGE) || {} - console.log("what is storage ", storageState) await jestPlaywright.resetContext({ storageState }) - await page.goto(CODE_SERVER_ADDRESS) - // code-server takes a second to load - await page.waitForTimeout(1000) + await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) it("should keep us logged in if we don't reset the browser", async () => { diff --git a/test/e2e/login.test.ts b/test/e2e/login.test.ts index 1caf40b0..29a23235 100644 --- a/test/e2e/login.test.ts +++ b/test/e2e/login.test.ts @@ -3,8 +3,8 @@ import { CODE_SERVER_ADDRESS, PASSWORD } from "../utils/constants" describe("login", () => { beforeEach(async () => { - await jestPlaywright.resetContext() - await page.goto(CODE_SERVER_ADDRESS) + await jestPlaywright.resetBrowser() + await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) it("should be able to login", async () => { @@ -12,9 +12,7 @@ describe("login", () => { await page.fill(".password", PASSWORD) // Click the submit button and login await page.click(".submit") - // For some reason, it wasn't waiting for the click and navigation before checking - // so adding a timeout ensures that we allow the editor time to load - await page.waitForTimeout(1000) + await page.waitForLoadState("networkidle") // See the editor const codeServerEditor = await page.isVisible(".monaco-workbench") expect(codeServerEditor).toBeTruthy() diff --git a/test/e2e/loginPage.test.ts b/test/e2e/loginPage.test.ts index ef85f8fc..eee4ae3a 100644 --- a/test/e2e/loginPage.test.ts +++ b/test/e2e/loginPage.test.ts @@ -5,7 +5,7 @@ import { CODE_SERVER_ADDRESS } from "../utils/constants" describe("login page", () => { beforeEach(async () => { await jestPlaywright.resetContext() - await page.goto(CODE_SERVER_ADDRESS) + await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) it("should see the login page", async () => { diff --git a/test/e2e/logout.test.ts b/test/e2e/logout.test.ts index c717a5f7..da364fe7 100644 --- a/test/e2e/logout.test.ts +++ b/test/e2e/logout.test.ts @@ -3,17 +3,16 @@ import { CODE_SERVER_ADDRESS, PASSWORD } from "../utils/constants" describe("logout", () => { beforeEach(async () => { - await jestPlaywright.resetContext() + await jestPlaywright.resetBrowser() + await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) it("should be able login and logout", async () => { - await page.goto(CODE_SERVER_ADDRESS) // Type in password await page.fill(".password", PASSWORD) // Click the submit button and login await page.click(".submit") - // Allow time to navigate - await page.waitForTimeout(1000) + await page.waitForLoadState("networkidle") // See the editor const codeServerEditor = await page.isVisible(".monaco-workbench") expect(codeServerEditor).toBeTruthy() @@ -28,8 +27,8 @@ describe("logout", () => { await page.hover(logoutButton) await page.click(logoutButton) - // it takes a couple seconds to navigate - await page.waitForTimeout(2000) + // it takes a couple seconds for url to change + await page.waitForLoadState("networkidle") const currentUrl = page.url() expect(currentUrl).toBe(`${CODE_SERVER_ADDRESS}/login`) }) diff --git a/test/e2e/openHelpAbout.test.ts b/test/e2e/openHelpAbout.test.ts index c8830bfe..fd63766d 100644 --- a/test/e2e/openHelpAbout.test.ts +++ b/test/e2e/openHelpAbout.test.ts @@ -1,51 +1,16 @@ /// -import { Cookie } from "playwright" -import { hash } from "../../src/node/util" -import { CODE_SERVER_ADDRESS, PASSWORD, STORAGE } from "../utils/constants" -import { createCookieIfDoesntExist } from "../utils/helpers" +import { CODE_SERVER_ADDRESS, STORAGE } from "../utils/constants" describe("Open Help > About", () => { beforeEach(async () => { // Create a new context with the saved storage state + // so we don't have to logged in const storageState = JSON.parse(STORAGE) || {} - - const cookieToStore = { - sameSite: "Lax" as const, - name: "key", - value: hash(PASSWORD), - domain: "localhost", - path: "/", - expires: -1, - httpOnly: false, - secure: false, - } - - // For some odd reason, the login method used in globalSetup.ts doesn't always work - // I don't know if it's on playwright clearing our cookies by accident - // or if it's our cookies disappearing. - // This means we need an additional check to make sure we're logged in. - // We do this by manually adding the cookie to the browser environment - // if it's not there at the time the test starts - const cookies: Cookie[] = storageState.cookies || [] - // If the cookie exists in cookies then - // this will return the cookies with no changes - // otherwise if it doesn't exist, it will create it - // hence the name maybeUpdatedCookies - // - // TODO(@jsjoeio) - // The playwright storage thing sometimes works and sometimes doesn't. We should investigate this further - // at some point. - // See discussion: https://github.com/cdr/code-server/pull/2648#discussion_r575434946 - - const maybeUpdatedCookies = createCookieIfDoesntExist(cookies, cookieToStore) - await jestPlaywright.resetBrowser({ storageState: { cookies: maybeUpdatedCookies } }) + await jestPlaywright.resetContext({ storageState }) + await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) it("should see a 'Help' then 'About' button in the Application Menu that opens a dialog", async () => { - // waitUntil: "domcontentloaded" - // In case the page takes a long time to load - await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "domcontentloaded" }) - // Make sure the editor actually loaded expect(await page.isVisible("div.monaco-workbench")) diff --git a/test/utils/globalSetup.ts b/test/utils/globalSetup.ts index 498d21a3..44adfaa8 100644 --- a/test/utils/globalSetup.ts +++ b/test/utils/globalSetup.ts @@ -2,37 +2,39 @@ // so that it authenticates us into code-server // ensuring that we're logged in before we run any tests import { chromium } from "playwright" -import { CODE_SERVER_ADDRESS, PASSWORD } from "./constants" +import { PASSWORD } from "./constants" +import { hash } from "../../src/node/util" import * as wtfnode from "./wtfnode" +const cookieToStore = { + sameSite: "Lax" as const, + name: "key", + value: hash(PASSWORD), + domain: "localhost", + path: "/", + expires: -1, + httpOnly: false, + secure: false, +} + module.exports = async () => { console.log("\n🚨 Running Global Setup for Jest End-to-End Tests") console.log(" Please hang tight...") const browser = await chromium.launch() - const context = await browser.newContext() - const page = await context.newPage() + const page = await browser.newPage() + const storage = await page.context().storageState() if (process.env.WTF_NODE) { wtfnode.setup() } - await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "domcontentloaded" }) - // Type in password - await page.fill(".password", PASSWORD) - // Click the submit button and login - await page.click(".submit") - // After logging in, we store a cookie in localStorage - // we need to wait a bit to make sure that happens - // before we grab the storage and save it - await page.waitForTimeout(1000) + storage.cookies = [cookieToStore] // Save storage state and store as an env variable // More info: https://playwright.dev/docs/auth?_highlight=authe#reuse-authentication-state - const storage = await context.storageState() process.env.STORAGE = JSON.stringify(storage) - await page.close() await browser.close() - await context.close() + console.log("✅ Global Setup for Jest End-to-End Tests is now complete.") } From fd69f2db88b778eee39528c9fe3a3086ac456b1f Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Fri, 2 Apr 2021 12:32:24 -0700 Subject: [PATCH 09/15] refactor: logout test --- test/e2e/globalSetup.test.ts | 2 +- test/e2e/logout.test.ts | 12 ++++++-- test/unit/util.test.ts | 59 +----------------------------------- test/utils/helpers.ts | 36 ---------------------- 4 files changed, 11 insertions(+), 98 deletions(-) diff --git a/test/e2e/globalSetup.test.ts b/test/e2e/globalSetup.test.ts index ee4b6443..6d4982b6 100644 --- a/test/e2e/globalSetup.test.ts +++ b/test/e2e/globalSetup.test.ts @@ -12,7 +12,7 @@ describe("globalSetup", () => { await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) - it("should keep us logged in if we don't reset the browser", async () => { + it("should keep us logged in using the storageState", async () => { // See the editor const codeServerEditor = await page.isVisible(".monaco-workbench") expect(codeServerEditor).toBeTruthy() diff --git a/test/e2e/logout.test.ts b/test/e2e/logout.test.ts index da364fe7..6ffce5ca 100644 --- a/test/e2e/logout.test.ts +++ b/test/e2e/logout.test.ts @@ -25,10 +25,16 @@ describe("logout", () => { expect(await page.isVisible(logoutButton)) await page.hover(logoutButton) + // TODO(@jsjoeio) + // Look into how we're attaching the handlers for the logout feature + // We need to see how it's done upstream and add logging to the + // handlers themselves. + // They may be attached too slowly, hence why we need this timeout + await page.waitForTimeout(2000) - await page.click(logoutButton) - // it takes a couple seconds for url to change - await page.waitForLoadState("networkidle") + // Recommended by Playwright for async navigation + // https://github.com/microsoft/playwright/issues/1987#issuecomment-620182151 + await Promise.all([page.waitForNavigation(), page.click(logoutButton)]) const currentUrl = page.url() expect(currentUrl).toBe(`${CODE_SERVER_ADDRESS}/login`) }) diff --git a/test/unit/util.test.ts b/test/unit/util.test.ts index 31eace76..02f3fdc5 100644 --- a/test/unit/util.test.ts +++ b/test/unit/util.test.ts @@ -11,10 +11,7 @@ import { trimSlashes, normalize, } from "../../src/common/util" -import { Cookie as CookieEnum } from "../../src/node/routes/login" -import { hash } from "../../src/node/util" -import { PASSWORD } from "../utils/constants" -import { checkForCookie, createCookieIfDoesntExist, loggerModule, Cookie } from "../utils/helpers" +import { loggerModule } from "../utils/helpers" const dom = new JSDOM() global.document = dom.window.document @@ -252,58 +249,4 @@ describe("util", () => { expect(loggerModule.logger.error).toHaveBeenCalledWith("api: oh no") }) }) - - describe("checkForCookie", () => { - it("should check if the cookie exists and has a value", () => { - const fakeCookies: Cookie[] = [ - { - name: CookieEnum.Key, - value: hash(PASSWORD), - domain: "localhost", - secure: false, - sameSite: "Lax", - httpOnly: false, - expires: 18000, - path: "/", - }, - ] - expect(checkForCookie(fakeCookies, CookieEnum.Key)).toBe(true) - }) - it("should return false if there are no cookies", () => { - const fakeCookies: Cookie[] = [] - expect(checkForCookie(fakeCookies, "key")).toBe(false) - }) - }) - - describe("createCookieIfDoesntExist", () => { - it("should create a cookie if it doesn't exist", () => { - const cookies: Cookie[] = [] - const cookieToStore = { - name: CookieEnum.Key, - value: hash(PASSWORD), - domain: "localhost", - secure: false, - sameSite: "Lax" as const, - httpOnly: false, - expires: 18000, - path: "/", - } - expect(createCookieIfDoesntExist(cookies, cookieToStore)).toStrictEqual([cookieToStore]) - }) - it("should return the same cookies if the cookie already exists", () => { - const PASSWORD = "123supersecure" - const cookieToStore = { - name: CookieEnum.Key, - value: hash(PASSWORD), - domain: "localhost", - secure: false, - sameSite: "Lax" as const, - httpOnly: false, - expires: 18000, - path: "/", - } - const cookies: Cookie[] = [cookieToStore] - expect(createCookieIfDoesntExist(cookies, cookieToStore)).toStrictEqual(cookies) - }) - }) }) diff --git a/test/utils/helpers.ts b/test/utils/helpers.ts index 2aeb82df..b4580401 100644 --- a/test/utils/helpers.ts +++ b/test/utils/helpers.ts @@ -1,39 +1,3 @@ -// Borrowed from playwright -export interface Cookie { - name: string - value: string - domain: string - path: string - /** - * Unix time in seconds. - */ - expires: number - httpOnly: boolean - secure: boolean - sameSite: "Strict" | "Lax" | "None" -} - -/** - * Checks if a cookie exists in array of cookies - */ -export function checkForCookie(cookies: Array, key: string): boolean { - // Check for a cookie where the name is equal to key - return Boolean(cookies.find((cookie) => cookie.name === key)) -} - -/** - * Creates a login cookie if one doesn't already exist - */ -export function createCookieIfDoesntExist(cookies: Array, cookieToStore: Cookie): Array { - const cookieName = cookieToStore.name - const doesCookieExist = checkForCookie(cookies, cookieName) - if (!doesCookieExist) { - const updatedCookies = [...cookies, cookieToStore] - return updatedCookies - } - return cookies -} - export const loggerModule = { field: jest.fn(), level: 2, From 32d0fb0a5e4a07e0c7afc4eff8683de5740cb88e Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Fri, 2 Apr 2021 14:50:31 -0700 Subject: [PATCH 10/15] refactor: add --runInBand to e2e test script --- ci/dev/test-e2e.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/dev/test-e2e.sh b/ci/dev/test-e2e.sh index 739f75c5..62a6fcf4 100755 --- a/ci/dev/test-e2e.sh +++ b/ci/dev/test-e2e.sh @@ -15,7 +15,7 @@ main() { echo -e "\n" exit 1 fi - CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@" --config ./test/jest.e2e.config.ts + CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@" --config ./test/jest.e2e.config.ts --runInBand } main "$@" From b1ea47c5066e5e0656e2e578050b8239e4b4c578 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Fri, 2 Apr 2021 14:52:01 -0700 Subject: [PATCH 11/15] chore: remove --home from test-e2e script --- ci/steps/test-e2e.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/steps/test-e2e.sh b/ci/steps/test-e2e.sh index c43fbd07..13376dc9 100755 --- a/ci/steps/test-e2e.sh +++ b/ci/steps/test-e2e.sh @@ -4,7 +4,7 @@ set -euo pipefail main() { cd "$(dirname "$0")/../.." - "./release-packages/code-server*-linux-amd64/bin/code-server" --home "$CODE_SERVER_ADDRESS"/healthz & + "./release-packages/code-server*-linux-amd64/bin/code-server" & yarn --frozen-lockfile yarn test:e2e } From 03f730989d6527f8b502c7470421ed4a900795b6 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Fri, 2 Apr 2021 16:02:49 -0700 Subject: [PATCH 12/15] feat: add --log trace for running cs in ci --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index af915298..834910dd 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -63,7 +63,7 @@ jobs: - uses: microsoft/playwright-github-action@v1 - name: Install dependencies and run end-to-end tests run: | - ./release-packages/code-server*-linux-amd64/bin/code-server & + ./release-packages/code-server*-linux-amd64/bin/code-server --log trace & yarn --frozen-lockfile yarn test:e2e - name: Upload test artifacts From f241e38907c9c9f27f45036fd6ce6c09aced9987 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Fri, 2 Apr 2021 16:30:57 -0700 Subject: [PATCH 13/15] chore: fix typo in extensionDownloader --- .../vs/platform/extensionManagement/node/extensionDownloader.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/vscode/src/vs/platform/extensionManagement/node/extensionDownloader.ts b/lib/vscode/src/vs/platform/extensionManagement/node/extensionDownloader.ts index 3df9b337..3ccd5eef 100644 --- a/lib/vscode/src/vs/platform/extensionManagement/node/extensionDownloader.ts +++ b/lib/vscode/src/vs/platform/extensionManagement/node/extensionDownloader.ts @@ -76,7 +76,7 @@ export class ExtensionsDownloader extends Disposable { private async cleanUp(): Promise { try { if (!(await this.fileService.exists(this.extensionsDownloadDir))) { - this.logService.trace('Extension VSIX downlads cache dir does not exist'); + this.logService.trace('Extension VSIX downloads cache dir does not exist'); return; } const folderStat = await this.fileService.resolve(this.extensionsDownloadDir, { resolveMetadata: true }); From dd80eed5b04ac96175321a8e030520939802d2f5 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Fri, 2 Apr 2021 16:49:01 -0700 Subject: [PATCH 14/15] feat: add logger to tests --- test/e2e/browser.test.ts | 7 ++++++- test/e2e/globalSetup.test.ts | 8 +++++++- test/e2e/login.test.ts | 7 ++++++- test/e2e/loginPage.test.ts | 7 ++++++- test/e2e/logout.test.ts | 7 ++++++- test/e2e/openHelpAbout.test.ts | 8 +++++++- 6 files changed, 38 insertions(+), 6 deletions(-) diff --git a/test/e2e/browser.test.ts b/test/e2e/browser.test.ts index 978c403d..642ff7a5 100644 --- a/test/e2e/browser.test.ts +++ b/test/e2e/browser.test.ts @@ -4,7 +4,12 @@ // tests are running in multiple browsers describe("Browser gutcheck", () => { beforeEach(async () => { - await jestPlaywright.resetBrowser() + await jestPlaywright.resetBrowser({ + logger: { + isEnabled: (name) => name === "browser", + log: (name, severity, message, args) => console.log(`${name} ${message}`), + }, + }) }) test("should display correct browser based on userAgent", async () => { diff --git a/test/e2e/globalSetup.test.ts b/test/e2e/globalSetup.test.ts index 6d4982b6..18be48b7 100644 --- a/test/e2e/globalSetup.test.ts +++ b/test/e2e/globalSetup.test.ts @@ -8,7 +8,13 @@ describe("globalSetup", () => { // Create a new context with the saved storage state // so we don't have to logged in const storageState = JSON.parse(STORAGE) || {} - await jestPlaywright.resetContext({ storageState }) + await jestPlaywright.resetContext({ + storageState, + logger: { + isEnabled: (name, severity) => name === "browser", + log: (name, severity, message, args) => console.log(`${name} ${message}`), + }, + }) await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) diff --git a/test/e2e/login.test.ts b/test/e2e/login.test.ts index 29a23235..bf274932 100644 --- a/test/e2e/login.test.ts +++ b/test/e2e/login.test.ts @@ -3,7 +3,12 @@ import { CODE_SERVER_ADDRESS, PASSWORD } from "../utils/constants" describe("login", () => { beforeEach(async () => { - await jestPlaywright.resetBrowser() + await jestPlaywright.resetBrowser({ + logger: { + isEnabled: (name, severity) => name === "browser", + log: (name, severity, message, args) => console.log(`${name} ${message}`), + }, + }) await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) diff --git a/test/e2e/loginPage.test.ts b/test/e2e/loginPage.test.ts index eee4ae3a..9016ded4 100644 --- a/test/e2e/loginPage.test.ts +++ b/test/e2e/loginPage.test.ts @@ -4,7 +4,12 @@ import { CODE_SERVER_ADDRESS } from "../utils/constants" describe("login page", () => { beforeEach(async () => { - await jestPlaywright.resetContext() + await jestPlaywright.resetContext({ + logger: { + isEnabled: (name, severity) => name === "browser", + log: (name, severity, message, args) => console.log(`${name} ${message}`), + }, + }) await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) diff --git a/test/e2e/logout.test.ts b/test/e2e/logout.test.ts index 6ffce5ca..b88c0963 100644 --- a/test/e2e/logout.test.ts +++ b/test/e2e/logout.test.ts @@ -3,7 +3,12 @@ import { CODE_SERVER_ADDRESS, PASSWORD } from "../utils/constants" describe("logout", () => { beforeEach(async () => { - await jestPlaywright.resetBrowser() + await jestPlaywright.resetBrowser({ + logger: { + isEnabled: (name, severity) => name === "browser", + log: (name, severity, message, args) => console.log(`${name} ${message}`), + }, + }) await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) diff --git a/test/e2e/openHelpAbout.test.ts b/test/e2e/openHelpAbout.test.ts index fd63766d..38ac4e21 100644 --- a/test/e2e/openHelpAbout.test.ts +++ b/test/e2e/openHelpAbout.test.ts @@ -6,7 +6,13 @@ describe("Open Help > About", () => { // Create a new context with the saved storage state // so we don't have to logged in const storageState = JSON.parse(STORAGE) || {} - await jestPlaywright.resetContext({ storageState }) + await jestPlaywright.resetContext({ + storageState, + logger: { + isEnabled: (name, severity) => name === "browser", + log: (name, severity, message, args) => console.log(`${name} ${message}`), + }, + }) await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) From ad0f12e664a318391573215cf9921790da1a2167 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Mon, 5 Apr 2021 15:18:13 -0700 Subject: [PATCH 15/15] refactor: check for editor consistently in tests --- .eslintrc.yaml | 4 +++- test/e2e/globalSetup.test.ts | 9 ++------- test/e2e/login.test.ts | 12 +++--------- test/e2e/logout.test.ts | 12 +++--------- test/e2e/openHelpAbout.test.ts | 4 ---- test/package.json | 10 ++++------ test/utils/globalSetup.ts | 2 +- 7 files changed, 16 insertions(+), 37 deletions(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index f520fd9f..9b4f5744 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -15,10 +15,12 @@ extends: - plugin:import/recommended - plugin:import/typescript - plugin:prettier/recommended - - prettier # Removes eslint rules that conflict with prettier. # Recommended by jest-playwright # https://github.com/playwright-community/jest-playwright#globals - plugin:jest-playwright/recommended + # Prettier should always be last + # Removes eslint rules that conflict with prettier. + - prettier rules: # Sometimes you need to add args to implement a function signature even diff --git a/test/e2e/globalSetup.test.ts b/test/e2e/globalSetup.test.ts index 18be48b7..3608fff4 100644 --- a/test/e2e/globalSetup.test.ts +++ b/test/e2e/globalSetup.test.ts @@ -10,17 +10,12 @@ describe("globalSetup", () => { const storageState = JSON.parse(STORAGE) || {} await jestPlaywright.resetContext({ storageState, - logger: { - isEnabled: (name, severity) => name === "browser", - log: (name, severity, message, args) => console.log(`${name} ${message}`), - }, }) await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) it("should keep us logged in using the storageState", async () => { - // See the editor - const codeServerEditor = await page.isVisible(".monaco-workbench") - expect(codeServerEditor).toBeTruthy() + // Make sure the editor actually loaded + expect(await page.isVisible("div.monaco-workbench")) }) }) diff --git a/test/e2e/login.test.ts b/test/e2e/login.test.ts index bf274932..41983855 100644 --- a/test/e2e/login.test.ts +++ b/test/e2e/login.test.ts @@ -3,12 +3,7 @@ import { CODE_SERVER_ADDRESS, PASSWORD } from "../utils/constants" describe("login", () => { beforeEach(async () => { - await jestPlaywright.resetBrowser({ - logger: { - isEnabled: (name, severity) => name === "browser", - log: (name, severity, message, args) => console.log(`${name} ${message}`), - }, - }) + await jestPlaywright.resetBrowser() await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) @@ -18,8 +13,7 @@ describe("login", () => { // Click the submit button and login await page.click(".submit") await page.waitForLoadState("networkidle") - // See the editor - const codeServerEditor = await page.isVisible(".monaco-workbench") - expect(codeServerEditor).toBeTruthy() + // Make sure the editor actually loaded + expect(await page.isVisible("div.monaco-workbench")) }) }) diff --git a/test/e2e/logout.test.ts b/test/e2e/logout.test.ts index b88c0963..bb5c2003 100644 --- a/test/e2e/logout.test.ts +++ b/test/e2e/logout.test.ts @@ -3,12 +3,7 @@ import { CODE_SERVER_ADDRESS, PASSWORD } from "../utils/constants" describe("logout", () => { beforeEach(async () => { - await jestPlaywright.resetBrowser({ - logger: { - isEnabled: (name, severity) => name === "browser", - log: (name, severity, message, args) => console.log(`${name} ${message}`), - }, - }) + await jestPlaywright.resetBrowser() await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) @@ -18,9 +13,8 @@ describe("logout", () => { // Click the submit button and login await page.click(".submit") await page.waitForLoadState("networkidle") - // See the editor - const codeServerEditor = await page.isVisible(".monaco-workbench") - expect(codeServerEditor).toBeTruthy() + // Make sure the editor actually loaded + expect(await page.isVisible("div.monaco-workbench")) // Click the Application menu await page.click("[aria-label='Application Menu']") diff --git a/test/e2e/openHelpAbout.test.ts b/test/e2e/openHelpAbout.test.ts index 38ac4e21..18fe407b 100644 --- a/test/e2e/openHelpAbout.test.ts +++ b/test/e2e/openHelpAbout.test.ts @@ -8,10 +8,6 @@ describe("Open Help > About", () => { const storageState = JSON.parse(STORAGE) || {} await jestPlaywright.resetContext({ storageState, - logger: { - isEnabled: (name, severity) => name === "browser", - log: (name, severity, message, args) => console.log(`${name} ${message}`), - }, }) await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) diff --git a/test/package.json b/test/package.json index 73da131a..a24fae4b 100644 --- a/test/package.json +++ b/test/package.json @@ -7,16 +7,14 @@ "@types/node-fetch": "^2.5.8", "@types/supertest": "^2.0.10", "jest": "^26.6.3", + "jest-playwright-preset": "^1.5.1", "jsdom": "^16.4.0", "node-fetch": "^2.6.1", "playwright": "^1.8.0", - "supertest": "^6.1.1", - "ts-jest": "^26.4.4" - }, - "dependencies": { - "jest-playwright-preset": "^1.5.1", "playwright-chromium": "^1.10.0", "playwright-firefox": "^1.10.0", - "playwright-webkit": "^1.10.0" + "playwright-webkit": "^1.10.0", + "supertest": "^6.1.1", + "ts-jest": "^26.4.4" } } diff --git a/test/utils/globalSetup.ts b/test/utils/globalSetup.ts index 44adfaa8..836cc600 100644 --- a/test/utils/globalSetup.ts +++ b/test/utils/globalSetup.ts @@ -2,8 +2,8 @@ // so that it authenticates us into code-server // ensuring that we're logged in before we run any tests import { chromium } from "playwright" -import { PASSWORD } from "./constants" import { hash } from "../../src/node/util" +import { PASSWORD } from "./constants" import * as wtfnode from "./wtfnode" const cookieToStore = {