From 4fcd3ae25f5c82c0f1663b65f76e219520ca4b58 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Fri, 18 Mar 2022 17:46:07 -0400 Subject: [PATCH] automatically start server for jest (#26206) * reinstate * start server manually * routing tests too * skip more * sleep more and fail if not 200 * use e2etest for content/ too * automatically start server for jest * does this work? * feedbacked * rename things * getting it to work * add dev dependency * install the right version * don't need to start that * fix package lock * update readme about it * feedbacked --- .github/workflows/browser-test.yml | 3 + .github/workflows/test.yml | 10 - Dockerfile | 1 + jest.config.js | 2 + package-lock.json | 409 +++++++++++++++-------------- package.json | 7 +- script/kill-server-for-jest.mjs | 24 ++ script/server-for-jest.mjs | 35 +++ script/start-server-for-jest.mjs | 42 +++ server.mjs | 54 +--- start-server.mjs | 54 ++++ tests/README.md | 25 ++ tests/browser/browser.js | 52 ++-- 13 files changed, 430 insertions(+), 288 deletions(-) create mode 100755 script/kill-server-for-jest.mjs create mode 100644 script/server-for-jest.mjs create mode 100755 script/start-server-for-jest.mjs create mode 100644 start-server.mjs diff --git a/.github/workflows/browser-test.yml b/.github/workflows/browser-test.yml index b5fb973f6c..14b0e3de1b 100644 --- a/.github/workflows/browser-test.yml +++ b/.github/workflows/browser-test.yml @@ -59,5 +59,8 @@ jobs: path: .next/cache key: ${{ runner.os }}-nextjs-${{ hashFiles('package*.json') }} + - name: Run build script + run: npm run build + - name: Run browser-test run: npm run browser-test diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 61e3e3c673..de1034d14f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -140,16 +140,6 @@ jobs: NODE_ENV: test run: ./script/warm-before-tests.mjs - - name: Start production-like server in the background - if: ${{ matrix.test-group == 'rendering' || matrix.test-group == 'routing' || matrix.test-group == 'content' }} - env: - NODE_ENV: test - PORT: 4000 - run: | - node server.mjs & - sleep 3 - curl --retry-connrefused --retry 5 -I --fail http://localhost:4000/healthz - - name: Run tests env: DIFF_FILE: get_diff_files.txt diff --git a/Dockerfile b/Dockerfile index 082e40cf85..2fef6655a0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -89,6 +89,7 @@ COPY --chown=node:node feature-flags.json ./ COPY --chown=node:node data ./data COPY --chown=node:node next.config.js ./ COPY --chown=node:node server.mjs ./server.mjs +COPY --chown=node:node start-server.mjs ./start-server.mjs EXPOSE $PORT diff --git a/jest.config.js b/jest.config.js index 6b0e3458c1..7e320cd0dc 100644 --- a/jest.config.js +++ b/jest.config.js @@ -41,4 +41,6 @@ module.exports = { ], testMatch: ['**/tests/**/*.js'], testLocationInResults: isActions, + globalSetup: './script/start-server-for-jest.mjs', + globalTeardown: './script/kill-server-for-jest.mjs', } diff --git a/package-lock.json b/package-lock.json index db07591998..4f2a50a441 100644 --- a/package-lock.json +++ b/package-lock.json @@ -140,9 +140,11 @@ "japanese-characters": "^1.1.0", "javascript-stringify": "^2.1.0", "jest": "^27.4.7", + "jest-environment-puppeteer": "5.0.4", "jest-fail-on-console": "^2.2.3", "jest-github-actions-reporter": "^1.0.3", "jest-slow-test-reporter": "^1.0.0", + "kill-port": "1.6.1", "linkinator": "^3.0.3", "lint-staged": "^12.3.3", "make-promises-safe": "^5.1.0", @@ -3665,9 +3667,9 @@ } }, "node_modules/@sideway/address": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.2.tgz", - "integrity": "sha512-idTz8ibqWFrPU8kMirL0CoPH/A29XOzzAzpyN3zQ4kAWnzmNfFmRaoMNN6VI8ske5M73HZyhIaW4OuSFIdM4oA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz", + "integrity": "sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ==", "devOptional": true, "dependencies": { "@hapi/hoek": "^9.0.0" @@ -4847,7 +4849,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "optional": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -6891,7 +6893,7 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", "integrity": "sha1-TnPdCen7lxzDhnDF3O2cGJZIHMY=", - "optional": true, + "devOptional": true, "dependencies": { "for-own": "^0.1.3", "is-plain-object": "^2.0.1", @@ -6907,13 +6909,13 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "optional": true + "devOptional": true }, "node_modules/clone-deep/node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "optional": true, + "devOptional": true, "dependencies": { "isobject": "^3.0.1" }, @@ -6925,7 +6927,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "optional": true, + "devOptional": true, "dependencies": { "is-buffer": "^1.1.5" }, @@ -7532,7 +7534,7 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/cwd/-/cwd-0.10.0.tgz", "integrity": "sha1-FyQAaUBXwioTsM8WFix+S3p/5Wc=", - "optional": true, + "devOptional": true, "dependencies": { "find-pkg": "^0.1.2", "fs-exists-sync": "^0.1.0" @@ -9227,7 +9229,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", - "optional": true, + "devOptional": true, "dependencies": { "os-homedir": "^1.0.1" }, @@ -9597,7 +9599,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-0.1.3.tgz", "integrity": "sha1-z2gJG8+fMApA2kEbN9pczlovvqA=", - "optional": true, + "devOptional": true, "dependencies": { "fs-exists-sync": "^0.1.0", "resolve-dir": "^0.1.0" @@ -9610,7 +9612,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/find-pkg/-/find-pkg-0.1.2.tgz", "integrity": "sha1-G9wiwG42NlUy4qJIBGhUuXiNpVc=", - "optional": true, + "devOptional": true, "dependencies": { "find-file-up": "^0.1.2" }, @@ -9622,7 +9624,7 @@ "version": "1.4.7", "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.7.tgz", "integrity": "sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==", - "optional": true, + "devOptional": true, "dependencies": { "chalk": "^4.0.0", "commander": "^5.1.0", @@ -9636,7 +9638,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "optional": true, + "devOptional": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -9652,7 +9654,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "optional": true, + "devOptional": true, "engines": { "node": ">= 6" } @@ -9725,7 +9727,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "optional": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -9734,7 +9736,7 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "optional": true, + "devOptional": true, "dependencies": { "for-in": "^1.0.1" }, @@ -9845,7 +9847,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", - "optional": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -10029,6 +10031,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-them-args": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/get-them-args/-/get-them-args-1.3.2.tgz", + "integrity": "sha1-dKILqKSr7OWuGZrQPyvMaP38m6U=", + "dev": true + }, "node_modules/gifwrap": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.9.2.tgz", @@ -10236,7 +10244,7 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", - "optional": true, + "devOptional": true, "dependencies": { "global-prefix": "^0.1.4", "is-windows": "^0.2.0" @@ -10249,7 +10257,7 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", - "optional": true, + "devOptional": true, "dependencies": { "homedir-polyfill": "^1.0.0", "ini": "^1.3.4", @@ -10264,7 +10272,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "optional": true, + "devOptional": true, "dependencies": { "isexe": "^2.0.0" }, @@ -10822,7 +10830,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "optional": true, + "devOptional": true, "dependencies": { "parse-passwd": "^1.0.0" }, @@ -11718,7 +11726,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", - "optional": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -11766,7 +11774,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "optional": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -12081,7 +12089,7 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/jest-dev-server/-/jest-dev-server-5.0.3.tgz", "integrity": "sha512-aJR3a5KdY18Lsz+VbREKwx2HM3iukiui+J9rlv9o6iYTwZCSsJazSTStcD9K1q0AIF3oA+FqLOKDyo/sc7+fJw==", - "optional": true, + "devOptional": true, "dependencies": { "chalk": "^4.1.1", "cwd": "^0.10.0", @@ -12096,7 +12104,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "optional": true, + "devOptional": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -12222,7 +12230,7 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/jest-environment-puppeteer/-/jest-environment-puppeteer-5.0.4.tgz", "integrity": "sha512-wd4EDOD4QRi11QZ1IV8WsL1wlnnMUtcqtU0BNm+REzRtg78K2XHn3jS6YxGeXIOnsgrJeHxsD7DlRZ/GkFteLg==", - "optional": true, + "devOptional": true, "dependencies": { "chalk": "^4.1.1", "cwd": "^0.10.0", @@ -12235,7 +12243,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "optional": true, + "devOptional": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -12891,14 +12899,14 @@ } }, "node_modules/joi": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.2.tgz", - "integrity": "sha512-Lm56PP+n0+Z2A2rfRvsfWVDXGEWjXxatPopkQ8qQ5mxCEhwHG+Ettgg5o98FFaxilOxozoa14cFhrE/hOzh/Nw==", + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz", + "integrity": "sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==", "devOptional": true, "dependencies": { "@hapi/hoek": "^9.0.0", "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.0", + "@sideway/address": "^4.1.3", "@sideway/formula": "^3.0.0", "@sideway/pinpoint": "^2.0.0" } @@ -13138,6 +13146,19 @@ "json-buffer": "3.0.1" } }, + "node_modules/kill-port": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/kill-port/-/kill-port-1.6.1.tgz", + "integrity": "sha512-un0Y55cOM7JKGaLnGja28T38tDDop0AQ8N0KlAdyh+B1nmMoX8AnNmqPNZbS3mUMgiST51DCVqmbFT1gNJpVNw==", + "dev": true, + "dependencies": { + "get-them-args": "1.3.2", + "shell-exec": "1.0.2" + }, + "bin": { + "kill-port": "cli.js" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -13194,7 +13215,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "optional": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -13452,15 +13473,6 @@ "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", "dev": true }, - "node_modules/listr2/node_modules/rxjs": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.2.tgz", - "integrity": "sha512-PwDt186XaL3QN5qXj/H9DGyHhP3/RYYgZZwqBv9Tv8rsAaiwFH1IsJJlcgD37J7UW5a6O67qX0KWKS3/pu0m4w==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/listr2/node_modules/slice-ansi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", @@ -14141,7 +14153,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz", "integrity": "sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA==", - "optional": true, + "devOptional": true, "dependencies": { "arr-union": "^3.1.0", "clone-deep": "^0.2.4", @@ -14155,13 +14167,13 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "optional": true + "devOptional": true }, "node_modules/merge-deep/node_modules/kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "optional": true, + "devOptional": true, "dependencies": { "is-buffer": "^1.1.5" }, @@ -14873,7 +14885,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", - "optional": true, + "devOptional": true, "dependencies": { "for-in": "^0.1.3", "is-extendable": "^0.1.1" @@ -14886,7 +14898,7 @@ "version": "0.1.8", "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", - "optional": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -15976,7 +15988,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "optional": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -17011,7 +17023,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "optional": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -19075,7 +19087,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", - "optional": true, + "devOptional": true, "dependencies": { "expand-tilde": "^1.2.2", "global-modules": "^0.2.3" @@ -19218,23 +19230,14 @@ } }, "node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "optional": true, + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "dev": true, "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" + "tslib": "^2.1.0" } }, - "node_modules/rxjs/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "optional": true - }, "node_modules/sade": { "version": "1.7.4", "resolved": "https://registry.npmjs.org/sade/-/sade-1.7.4.tgz", @@ -19571,7 +19574,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", "integrity": "sha1-WQnodLp3EG1zrEFM/sH/yofZcGA=", - "optional": true, + "devOptional": true, "dependencies": { "is-extendable": "^0.1.1", "kind-of": "^2.0.1", @@ -19586,13 +19589,13 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "optional": true + "devOptional": true }, "node_modules/shallow-clone/node_modules/kind-of": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", - "optional": true, + "devOptional": true, "dependencies": { "is-buffer": "^1.0.2" }, @@ -19604,7 +19607,7 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U=", - "optional": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -19635,6 +19638,12 @@ "node": ">=8" } }, + "node_modules/shell-exec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shell-exec/-/shell-exec-1.0.2.tgz", + "integrity": "sha512-jyVd+kU2X+mWKMmGhx4fpWbPsjvD53k9ivqetutVW/BQ+WIZoDoP4d8vUMGezV6saZsiNoW2f9GIhg9Dondohg==", + "dev": true + }, "node_modules/shell-quote": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", @@ -19680,9 +19689,9 @@ } }, "node_modules/signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "devOptional": true }, "node_modules/sisteransi": { @@ -19801,7 +19810,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-5.0.0.tgz", "integrity": "sha512-28+AJr82moMVWolQvlAIv3JcYDkjkFTEmfDc503wxrF5l2rQ3dFz6DpbXp3kD4zmgGGldfM4xM4v1sFj/ZaIOA==", - "optional": true, + "devOptional": true, "dependencies": { "exit": "^0.1.2", "signal-exit": "^3.0.3", @@ -19933,21 +19942,6 @@ "node": ">=6" } }, - "node_modules/start-server-and-test/node_modules/rxjs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", - "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", - "dev": true, - "dependencies": { - "tslib": "~2.1.0" - } - }, - "node_modules/start-server-and-test/node_modules/tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", - "dev": true - }, "node_modules/start-server-and-test/node_modules/wait-on": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.0.tgz", @@ -20913,7 +20907,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "optional": true, + "devOptional": true, "bin": { "tree-kill": "cli.js" } @@ -21776,7 +21770,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-5.3.0.tgz", "integrity": "sha512-DwrHrnTK+/0QFaB9a8Ol5Lna3k7WvUR4jzSKmz0YaPBpuN2sACyiPVKVfj6ejnjcajAcvn3wlbTyMIn9AZouOg==", - "optional": true, + "devOptional": true, "dependencies": { "axios": "^0.21.1", "joi": "^17.3.0", @@ -21791,11 +21785,29 @@ "node": ">=8.9.0" } }, + "node_modules/wait-on/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "devOptional": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/wait-on/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "devOptional": true + }, "node_modules/wait-port": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/wait-port/-/wait-port-0.2.9.tgz", "integrity": "sha512-hQ/cVKsNqGZ/UbZB/oakOGFqic00YAMM5/PEj3Bt4vKarv2jWIWzDbqlwT94qMs/exAQAsvMOq99sZblV92zxQ==", - "optional": true, + "devOptional": true, "dependencies": { "chalk": "^2.4.2", "commander": "^3.0.2", @@ -21812,7 +21824,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "optional": true, + "devOptional": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -21824,7 +21836,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "optional": true, + "devOptional": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -21838,7 +21850,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "optional": true, + "devOptional": true, "dependencies": { "color-name": "1.1.3" } @@ -21847,19 +21859,19 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "optional": true + "devOptional": true }, "node_modules/wait-port/node_modules/commander": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", - "optional": true + "devOptional": true }, "node_modules/wait-port/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "optional": true, + "devOptional": true, "engines": { "node": ">=0.8.0" } @@ -21868,7 +21880,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "optional": true, + "devOptional": true, "engines": { "node": ">=4" } @@ -21877,7 +21889,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "optional": true, + "devOptional": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -25192,9 +25204,9 @@ } }, "@sideway/address": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.2.tgz", - "integrity": "sha512-idTz8ibqWFrPU8kMirL0CoPH/A29XOzzAzpyN3zQ4kAWnzmNfFmRaoMNN6VI8ske5M73HZyhIaW4OuSFIdM4oA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz", + "integrity": "sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ==", "devOptional": true, "requires": { "@hapi/hoek": "^9.0.0" @@ -26202,7 +26214,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "optional": true + "devOptional": true }, "array-flatten": { "version": "1.1.1", @@ -27906,7 +27918,7 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", "integrity": "sha1-TnPdCen7lxzDhnDF3O2cGJZIHMY=", - "optional": true, + "devOptional": true, "requires": { "for-own": "^0.1.3", "is-plain-object": "^2.0.1", @@ -27919,13 +27931,13 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "optional": true + "devOptional": true }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "optional": true, + "devOptional": true, "requires": { "isobject": "^3.0.1" } @@ -27934,7 +27946,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "optional": true, + "devOptional": true, "requires": { "is-buffer": "^1.1.5" } @@ -28427,7 +28439,7 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/cwd/-/cwd-0.10.0.tgz", "integrity": "sha1-FyQAaUBXwioTsM8WFix+S3p/5Wc=", - "optional": true, + "devOptional": true, "requires": { "find-pkg": "^0.1.2", "fs-exists-sync": "^0.1.0" @@ -29719,7 +29731,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", - "optional": true, + "devOptional": true, "requires": { "os-homedir": "^1.0.1" } @@ -30006,7 +30018,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-0.1.3.tgz", "integrity": "sha1-z2gJG8+fMApA2kEbN9pczlovvqA=", - "optional": true, + "devOptional": true, "requires": { "fs-exists-sync": "^0.1.0", "resolve-dir": "^0.1.0" @@ -30016,7 +30028,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/find-pkg/-/find-pkg-0.1.2.tgz", "integrity": "sha1-G9wiwG42NlUy4qJIBGhUuXiNpVc=", - "optional": true, + "devOptional": true, "requires": { "find-file-up": "^0.1.2" } @@ -30025,7 +30037,7 @@ "version": "1.4.7", "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.7.tgz", "integrity": "sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==", - "optional": true, + "devOptional": true, "requires": { "chalk": "^4.0.0", "commander": "^5.1.0", @@ -30036,7 +30048,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "optional": true, + "devOptional": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -30046,7 +30058,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "optional": true + "devOptional": true } } }, @@ -30095,13 +30107,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "optional": true + "devOptional": true }, "for-own": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "optional": true, + "devOptional": true, "requires": { "for-in": "^1.0.1" } @@ -30187,7 +30199,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", - "optional": true + "devOptional": true }, "fs-extra": { "version": "10.0.1", @@ -30328,6 +30340,12 @@ "get-intrinsic": "^1.1.1" } }, + "get-them-args": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/get-them-args/-/get-them-args-1.3.2.tgz", + "integrity": "sha1-dKILqKSr7OWuGZrQPyvMaP38m6U=", + "dev": true + }, "gifwrap": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.9.2.tgz", @@ -30499,7 +30517,7 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", - "optional": true, + "devOptional": true, "requires": { "global-prefix": "^0.1.4", "is-windows": "^0.2.0" @@ -30509,7 +30527,7 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", - "optional": true, + "devOptional": true, "requires": { "homedir-polyfill": "^1.0.0", "ini": "^1.3.4", @@ -30521,7 +30539,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "optional": true, + "devOptional": true, "requires": { "isexe": "^2.0.0" } @@ -30943,7 +30961,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "optional": true, + "devOptional": true, "requires": { "parse-passwd": "^1.0.0" } @@ -31544,7 +31562,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", - "optional": true + "devOptional": true }, "is-word-character": { "version": "1.0.4", @@ -31582,7 +31600,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "optional": true + "devOptional": true }, "istanbul-lib-coverage": { "version": "3.2.0", @@ -31814,7 +31832,7 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/jest-dev-server/-/jest-dev-server-5.0.3.tgz", "integrity": "sha512-aJR3a5KdY18Lsz+VbREKwx2HM3iukiui+J9rlv9o6iYTwZCSsJazSTStcD9K1q0AIF3oA+FqLOKDyo/sc7+fJw==", - "optional": true, + "devOptional": true, "requires": { "chalk": "^4.1.1", "cwd": "^0.10.0", @@ -31829,7 +31847,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "optional": true, + "devOptional": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -31928,7 +31946,7 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/jest-environment-puppeteer/-/jest-environment-puppeteer-5.0.4.tgz", "integrity": "sha512-wd4EDOD4QRi11QZ1IV8WsL1wlnnMUtcqtU0BNm+REzRtg78K2XHn3jS6YxGeXIOnsgrJeHxsD7DlRZ/GkFteLg==", - "optional": true, + "devOptional": true, "requires": { "chalk": "^4.1.1", "cwd": "^0.10.0", @@ -31941,7 +31959,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "optional": true, + "devOptional": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -32461,14 +32479,14 @@ } }, "joi": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.2.tgz", - "integrity": "sha512-Lm56PP+n0+Z2A2rfRvsfWVDXGEWjXxatPopkQ8qQ5mxCEhwHG+Ettgg5o98FFaxilOxozoa14cFhrE/hOzh/Nw==", + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz", + "integrity": "sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==", "devOptional": true, "requires": { "@hapi/hoek": "^9.0.0", "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.0", + "@sideway/address": "^4.1.3", "@sideway/formula": "^3.0.0", "@sideway/pinpoint": "^2.0.0" } @@ -32668,6 +32686,16 @@ "json-buffer": "3.0.1" } }, + "kill-port": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/kill-port/-/kill-port-1.6.1.tgz", + "integrity": "sha512-un0Y55cOM7JKGaLnGja28T38tDDop0AQ8N0KlAdyh+B1nmMoX8AnNmqPNZbS3mUMgiST51DCVqmbFT1gNJpVNw==", + "dev": true, + "requires": { + "get-them-args": "1.3.2", + "shell-exec": "1.0.2" + } + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -32712,7 +32740,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "optional": true + "devOptional": true }, "leven": { "version": "3.1.0", @@ -32883,15 +32911,6 @@ "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", "dev": true }, - "rxjs": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.2.tgz", - "integrity": "sha512-PwDt186XaL3QN5qXj/H9DGyHhP3/RYYgZZwqBv9Tv8rsAaiwFH1IsJJlcgD37J7UW5a6O67qX0KWKS3/pu0m4w==", - "dev": true, - "requires": { - "tslib": "^2.1.0" - } - }, "slice-ansi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", @@ -33412,7 +33431,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz", "integrity": "sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA==", - "optional": true, + "devOptional": true, "requires": { "arr-union": "^3.1.0", "clone-deep": "^0.2.4", @@ -33423,13 +33442,13 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "optional": true + "devOptional": true }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "optional": true, + "devOptional": true, "requires": { "is-buffer": "^1.1.5" } @@ -33865,7 +33884,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", - "optional": true, + "devOptional": true, "requires": { "for-in": "^0.1.3", "is-extendable": "^0.1.1" @@ -33875,7 +33894,7 @@ "version": "0.1.8", "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", - "optional": true + "devOptional": true } } }, @@ -34712,7 +34731,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "optional": true + "devOptional": true }, "p-cancelable": { "version": "2.1.1", @@ -35543,7 +35562,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "optional": true + "devOptional": true }, "parse5": { "version": "6.0.1", @@ -37095,7 +37114,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", - "optional": true, + "devOptional": true, "requires": { "expand-tilde": "^1.2.2", "global-modules": "^0.2.3" @@ -37196,20 +37215,12 @@ } }, "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "optional": true, + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "dev": true, "requires": { - "tslib": "^1.9.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "optional": true - } + "tslib": "^2.1.0" } }, "sade": { @@ -37492,7 +37503,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", "integrity": "sha1-WQnodLp3EG1zrEFM/sH/yofZcGA=", - "optional": true, + "devOptional": true, "requires": { "is-extendable": "^0.1.1", "kind-of": "^2.0.1", @@ -37504,13 +37515,13 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "optional": true + "devOptional": true }, "kind-of": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", - "optional": true, + "devOptional": true, "requires": { "is-buffer": "^1.0.2" } @@ -37519,7 +37530,7 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U=", - "optional": true + "devOptional": true } } }, @@ -37543,6 +37554,12 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "shell-exec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shell-exec/-/shell-exec-1.0.2.tgz", + "integrity": "sha512-jyVd+kU2X+mWKMmGhx4fpWbPsjvD53k9ivqetutVW/BQ+WIZoDoP4d8vUMGezV6saZsiNoW2f9GIhg9Dondohg==", + "dev": true + }, "shell-quote": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", @@ -37576,9 +37593,9 @@ } }, "signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "devOptional": true }, "sisteransi": { @@ -37664,7 +37681,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-5.0.0.tgz", "integrity": "sha512-28+AJr82moMVWolQvlAIv3JcYDkjkFTEmfDc503wxrF5l2rQ3dFz6DpbXp3kD4zmgGGldfM4xM4v1sFj/ZaIOA==", - "optional": true, + "devOptional": true, "requires": { "exit": "^0.1.2", "signal-exit": "^3.0.3", @@ -37771,21 +37788,6 @@ "wait-on": "6.0.0" }, "dependencies": { - "rxjs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", - "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", - "dev": true, - "requires": { - "tslib": "~2.1.0" - } - }, - "tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", - "dev": true - }, "wait-on": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.0.tgz", @@ -38519,7 +38521,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "optional": true + "devOptional": true }, "trim-newlines": { "version": "4.0.2", @@ -39172,20 +39174,37 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-5.3.0.tgz", "integrity": "sha512-DwrHrnTK+/0QFaB9a8Ol5Lna3k7WvUR4jzSKmz0YaPBpuN2sACyiPVKVfj6ejnjcajAcvn3wlbTyMIn9AZouOg==", - "optional": true, + "devOptional": true, "requires": { "axios": "^0.21.1", "joi": "^17.3.0", "lodash": "^4.17.21", "minimist": "^1.2.5", "rxjs": "^6.6.3" + }, + "dependencies": { + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "devOptional": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "devOptional": true + } } }, "wait-port": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/wait-port/-/wait-port-0.2.9.tgz", "integrity": "sha512-hQ/cVKsNqGZ/UbZB/oakOGFqic00YAMM5/PEj3Bt4vKarv2jWIWzDbqlwT94qMs/exAQAsvMOq99sZblV92zxQ==", - "optional": true, + "devOptional": true, "requires": { "chalk": "^2.4.2", "commander": "^3.0.2", @@ -39196,7 +39215,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "optional": true, + "devOptional": true, "requires": { "color-convert": "^1.9.0" } @@ -39205,7 +39224,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "optional": true, + "devOptional": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -39216,7 +39235,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "optional": true, + "devOptional": true, "requires": { "color-name": "1.1.3" } @@ -39225,31 +39244,31 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "optional": true + "devOptional": true }, "commander": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", - "optional": true + "devOptional": true }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "optional": true + "devOptional": true }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "optional": true + "devOptional": true }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "optional": true, + "devOptional": true, "requires": { "has-flag": "^3.0.0" } diff --git a/package.json b/package.json index d593750624..a9fcbfbcb6 100644 --- a/package.json +++ b/package.json @@ -142,9 +142,11 @@ "japanese-characters": "^1.1.0", "javascript-stringify": "^2.1.0", "jest": "^27.4.7", + "jest-environment-puppeteer": "5.0.4", "jest-fail-on-console": "^2.2.3", "jest-github-actions-reporter": "^1.0.3", "jest-slow-test-reporter": "^1.0.0", + "kill-port": "1.6.1", "linkinator": "^3.0.3", "lint-staged": "^12.3.3", "make-promises-safe": "^5.1.0", @@ -186,9 +188,7 @@ "private": true, "repository": "https://github.com/github/docs", "scripts": { - "browser-test": "start-server-and-test browser-test-server 4001 browser-test-tests", - "browser-test-server": "cross-env NODE_ENV=production PORT=4001 ENABLED_LANGUAGES=en,ja node server.mjs", - "browser-test-tests": "cross-env BROWSER=1 NODE_OPTIONS=--experimental-vm-modules jest tests/browser/browser.js", + "browser-test": "cross-env BROWSER=1 NODE_OPTIONS=--experimental-vm-modules jest tests/browser/browser.js", "build": "next build", "debug": "cross-env NODE_ENV=development ENABLED_LANGUAGES='en,ja' nodemon --inspect server.mjs", "dev": "npm start", @@ -196,7 +196,6 @@ "lint-translation": "cross-env NODE_OPTIONS=--experimental-vm-modules TEST_TRANSLATION=true jest tests/linting/lint-files.js", "pa11y-ci": "pa11y-ci", "pa11y-test": "start-server-and-test browser-test-server 4001 pa11y-ci", - "prebrowser-test": "npm run build", "prepare": "husky install", "prettier": "prettier -w \"**/*.{ts,tsx,js,mjs,scss,yml,yaml}\"", "prettier-check": "prettier -c \"**/*.{ts,tsx,js,mjs,scss,yml,yaml}\"", diff --git a/script/kill-server-for-jest.mjs b/script/kill-server-for-jest.mjs new file mode 100755 index 0000000000..6795d8fde4 --- /dev/null +++ b/script/kill-server-for-jest.mjs @@ -0,0 +1,24 @@ +#!/usr/bin/env node + +import teardownJestPuppeteer from 'jest-environment-puppeteer/teardown.js' + +import { START_JEST_SERVER, isServerHealthy, killServer } from './server-for-jest.mjs' + +export default async () => { + if (START_JEST_SERVER) { + global.__SERVER__.close() + + if (await isServerHealthy()) { + killServer() + } + } + + // The way jest-puppeteer works is that you add a preset in + // `jest.config.js` but that preset will clash with the execution + // of this script. So we have to manually do what we do normally + // do in `jest.config.js` + // Note, we can delete this when we migrate to Playwright. + if (process.env.BROWSER) { + await teardownJestPuppeteer() + } +} diff --git a/script/server-for-jest.mjs b/script/server-for-jest.mjs new file mode 100644 index 0000000000..73d28d86bb --- /dev/null +++ b/script/server-for-jest.mjs @@ -0,0 +1,35 @@ +import kill from 'kill-port' +import portUsed from 'port-used' +import got, { RequestError } from 'got' + +export const PORT = 4000 + +// By default it's on +export const START_JEST_SERVER = Boolean(JSON.parse(process.env.START_JEST_SERVER || 1)) + +export async function isServerHealthy() { + try { + const res = await got.head(`http://localhost:${PORT}/healthz`, { retry: { limit: 0 } }) + return res.statusCode === 200 + } catch (err) { + // This exception is thrown if you can't even connect. + if (err instanceof RequestError) { + return false + } + throw err + } +} + +export function killServer() { + kill(PORT, 'tcp') + .then(() => { + console.log(`Killed what was on :${PORT}`) + }) + .catch((error) => { + console.log(`Unable to kill whatever was on :${PORT}:`, error) + }) +} + +export async function isPortRunning() { + return await portUsed.check(PORT) +} diff --git a/script/start-server-for-jest.mjs b/script/start-server-for-jest.mjs new file mode 100755 index 0000000000..9f665af7ef --- /dev/null +++ b/script/start-server-for-jest.mjs @@ -0,0 +1,42 @@ +#!/usr/bin/env node + +import setupJestPuppeteer from 'jest-environment-puppeteer/setup.js' + +import { main } from '../start-server.mjs' + +import { PORT, START_JEST_SERVER, isServerHealthy, isPortRunning } from './server-for-jest.mjs' + +export default async () => { + if (START_JEST_SERVER) { + console.log(`Starting a server for jest on port :${PORT}.`) + + process.env.NODE_ENV = 'test' + // Has to be this because that's what the end-to-end tests expect + process.env.PORT = `${PORT}` + + if (await isPortRunning()) { + console.error(`Something's already running on :${PORT}`) + console.log( + 'If you intend to run jest tests with an existing server, set env var START_JEST_SERVER=false' + ) + process.exit(1) + } + + // So it can be accessed from the script that + // is set up by the jest config: `globalTeardown` + global.__SERVER__ = await main() + + console.assert(await isServerHealthy()) + } else { + console.warn(`jest is NOT automatically starting a server on port :${PORT}`) + } + + // The way jest-puppeteer works is that you add a preset in + // `jest.config.js` but that preset will clash with the execution + // of this script. So we have to manually do what we do normally + // do in `jest.config.js`. + // Note, we can delete this when we migrate to Playwright. + if (process.env.BROWSER) { + await setupJestPuppeteer() + } +} diff --git a/server.mjs b/server.mjs index fa4bb2c0fe..ed58037d9d 100644 --- a/server.mjs +++ b/server.mjs @@ -1,55 +1,3 @@ -import dotenv from 'dotenv' -import './lib/feature-flags.js' -import './lib/check-node-version.js' -import './lib/handle-exceptions.js' -import portUsed from 'port-used' -import createApp from './lib/app.js' -import warmServer from './lib/warm-server.js' -import http from 'http' -dotenv.config() - -const { PORT, NODE_ENV } = process.env -const port = Number(PORT) || 4000 - -async function main() { - if (NODE_ENV !== 'production') { - await checkPortAvailability() - } - - await startServer() -} - -async function checkPortAvailability() { - // Check that the development server is not already running - const portInUse = await portUsed.check(port) - if (portInUse) { - console.log(`\n\n\nPort ${port} is not available. You may already have a server running.`) - console.log( - `Try running \`npx kill-port ${port}\` to shut down all your running node processes.\n\n\n` - ) - console.log('\x07') // system 'beep' sound - process.exit(1) - } -} - -async function startServer() { - const app = createApp() - - // Warm up as soon as possible. - // The `warmServer()` function is idempotent and it will soon be used - // by some middleware, but there's no point in having a started server - // without this warmed up. Besides, by starting this slow thing now, - // it can start immediately instead of waiting for the first request - // to trigger it to warm up. That way, when in development and triggering - // a `nodemon` restart, there's a good chance the warm up has come some - // way before you manage to reach for your browser to do a page refresh. - await warmServer() - - // Workaround for https://github.com/expressjs/express/issues/1101 - const server = http.createServer(app) - server - .listen(port, () => console.log(`app running on http://localhost:${port}`)) - .on('error', () => server.close()) -} +import { main } from './start-server.mjs' main() diff --git a/start-server.mjs b/start-server.mjs new file mode 100644 index 0000000000..170b5bf5d2 --- /dev/null +++ b/start-server.mjs @@ -0,0 +1,54 @@ +import dotenv from 'dotenv' +import './lib/feature-flags.js' +import './lib/check-node-version.js' +import './lib/handle-exceptions.js' +import portUsed from 'port-used' +import createApp from './lib/app.js' +import warmServer from './lib/warm-server.js' +import http from 'http' +dotenv.config() + +const { PORT, NODE_ENV } = process.env +const port = Number(PORT) || 4000 + +export async function main() { + if (NODE_ENV !== 'production') { + await checkPortAvailability() + } + + return await startServer() +} + +async function checkPortAvailability() { + // Check that the development server is not already running + const portInUse = await portUsed.check(port) + if (portInUse) { + console.log(`\n\n\nPort ${port} is not available. You may already have a server running.`) + console.log( + `Try running \`npx kill-port ${port}\` to shut down all your running node processes.\n\n\n` + ) + console.log('\x07') // system 'beep' sound + process.exit(1) + } +} + +async function startServer() { + const app = createApp() + + // Warm up as soon as possible. + // The `warmServer()` function is idempotent and it will soon be used + // by some middleware, but there's no point in having a started server + // without this warmed up. Besides, by starting this slow thing now, + // it can start immediately instead of waiting for the first request + // to trigger it to warm up. That way, when in development and triggering + // a `nodemon` restart, there's a good chance the warm up has come some + // way before you manage to reach for your browser to do a page refresh. + await warmServer() + + // Workaround for https://github.com/expressjs/express/issues/1101 + const server = http.createServer(app) + + return server + .listen(port, () => console.log(`app running on http://localhost:${port}`)) + .on('error', () => server.close()) +} diff --git a/tests/README.md b/tests/README.md index 496dc32a63..4377e7a779 100644 --- a/tests/README.md +++ b/tests/README.md @@ -76,3 +76,28 @@ run the linter: ```sh npm run lint ``` + +### Keeping the server running + +When you run `jest` tests, that depend on making real HTTP requests +to `localhost:4000`, the `jest` tests have a hook that starts the +server before running all/any tests, and stops the server when it's done. + +You can disable that, which might make it easier when debugging tests +since the server won't need to start and stop every time you run tests. + +In one terminal type: + +```sh +NODE_ENV=test PORT=4000 node server.mjs +``` + +and then, in another terminal type: + +```sh +START_JEST_SERVER=false jest tests/rendering/foo/bar.js +``` + +Or whatever the testing command you use. Note the `START_JEST_SERVER=false` +environment variable that needs to be set or else, `jest` will try to start +a server on `:4000` too. diff --git a/tests/browser/browser.js b/tests/browser/browser.js index 046ac81fa7..55eba3218f 100644 --- a/tests/browser/browser.js +++ b/tests/browser/browser.js @@ -9,7 +9,7 @@ describe('homepage', () => { jest.setTimeout(60 * 1000) test('should be titled "GitHub Documentation"', async () => { - await page.goto('http://localhost:4001') + await page.goto('http://localhost:4000') await expect(page.title()).resolves.toMatch('GitHub Documentation') }) }) @@ -18,7 +18,7 @@ describe('browser search', () => { jest.setTimeout(60 * 1000) it('works on the homepage', async () => { - await page.goto('http://localhost:4001/en') + await page.goto('http://localhost:4000/en') await page.click('[data-testid=site-search-input]') await page.type('[data-testid=site-search-input]', 'actions') await page.waitForSelector('[data-testid=search-results]') @@ -27,7 +27,7 @@ describe('browser search', () => { }) it('works on mobile landing pages', async () => { - await page.goto('http://localhost:4001/en/actions') + await page.goto('http://localhost:4000/en/actions') await page.click('[data-testid=mobile-menu-button]') await page.click('[data-testid=mobile-header] [data-testid=site-search-input]') await page.type('[data-testid=mobile-header] [data-testid=site-search-input]', 'workflows') @@ -39,7 +39,7 @@ describe('browser search', () => { it('works on desktop landing pages', async () => { const initialViewport = page.viewport() await page.setViewport({ width: 1024, height: 768 }) - await page.goto('http://localhost:4001/en/actions') + await page.goto('http://localhost:4000/en/actions') await page.click('[data-testid=desktop-header] [data-testid=site-search-input]') await page.type('[data-testid=desktop-header] [data-testid=site-search-input]', 'workflows') await page.waitForSelector('[data-testid=search-results]') @@ -50,7 +50,7 @@ describe('browser search', () => { // 404 page is statically generated with next, so search is not available, but may possibly be brought back // Docs Engineering issue: 961 it.skip('works on 404 error page', async () => { - await page.goto('http://localhost:4001/en/404') + await page.goto('http://localhost:4000/en/404') await page.click('[data-testid=search] input[type="search"]') await page.type('[data-testid=search] input[type="search"]', 'actions') await page.waitForSelector('[data-testid=search-results]') @@ -63,7 +63,7 @@ describe('browser search', () => { const newPage = await browser.newPage() await newPage.goto( - `http://localhost:4001/ja/enterprise-server@${oldestSupported}/admin/installation` + `http://localhost:4000/ja/enterprise-server@${oldestSupported}/admin/installation` ) await newPage.setRequestInterception(true) @@ -89,7 +89,7 @@ describe('browser search', () => { expect.assertions(2) const newPage = await browser.newPage() - await newPage.goto('http://localhost:4001/en/enterprise-cloud@latest/admin/overview') + await newPage.goto('http://localhost:4000/en/enterprise-cloud@latest/admin/overview') await newPage.setRequestInterception(true) newPage.on('request', (interceptedRequest) => { @@ -114,7 +114,7 @@ describe('browser search', () => { expect.assertions(2) const newPage = await browser.newPage() - await newPage.goto('http://localhost:4001/en/github-ae@latest/admin/overview') + await newPage.goto('http://localhost:4000/en/github-ae@latest/admin/overview') await newPage.setRequestInterception(true) newPage.on('request', (interceptedRequest) => { @@ -142,7 +142,7 @@ describe('survey', () => { it('sends an event to /events when submitting form', async () => { // Visit a page that displays the prompt await page.goto( - 'http://localhost:4001/en/actions/getting-started-with-github-actions/about-github-actions' + 'http://localhost:4000/en/actions/getting-started-with-github-actions/about-github-actions' ) // Track network requests @@ -177,7 +177,7 @@ describe('survey', () => { describe('csrf meta', () => { it('should have a csrf-token meta tag on the page', async () => { await page.goto( - 'http://localhost:4001/en/actions/getting-started-with-github-actions/about-github-actions' + 'http://localhost:4000/en/actions/getting-started-with-github-actions/about-github-actions' ) await page.waitForSelector('meta[name="csrf-token"]') }) @@ -204,10 +204,10 @@ describe('platform picker', () => { ] const linuxUserAgent = userAgents[2] const pageWithPlatformPicker = - 'http://localhost:4001/en/github/using-git/configuring-git-to-handle-line-endings' - const pageWithoutPlatformPicker = 'http://localhost:4001/en/github/using-git' + 'http://localhost:4000/en/github/using-git/configuring-git-to-handle-line-endings' + const pageWithoutPlatformPicker = 'http://localhost:4000/en/github/using-git' const pageWithDefaultPlatform = - 'http://localhost:4001/en/actions/hosting-your-own-runners/configuring-the-self-hosted-runner-application-as-a-service' + 'http://localhost:4000/en/actions/hosting-your-own-runners/configuring-the-self-hosted-runner-application-as-a-service' it('should have a platform picker', async () => { await page.goto(pageWithPlatformPicker) @@ -286,11 +286,11 @@ describe('platform picker', () => { describe('tool specific content', () => { const pageWithSingleSwitcher = - 'http://localhost:4001/en/actions/managing-workflow-runs/manually-running-a-workflow' + 'http://localhost:4000/en/actions/managing-workflow-runs/manually-running-a-workflow' const pageWithoutSwitcher = - 'http://localhost:4001/en/billing/managing-billing-for-github-sponsors/about-billing-for-github-sponsors' + 'http://localhost:4000/en/billing/managing-billing-for-github-sponsors/about-billing-for-github-sponsors' const pageWithMultipleSwitcher = - 'http://localhost:4001/en/issues/trying-out-the-new-projects-experience/using-the-api-to-manage-projects' + 'http://localhost:4000/en/issues/trying-out-the-new-projects-experience/using-the-api-to-manage-projects' it('should have a tool switcher if a tool switcher is included', async () => { await page.goto(pageWithSingleSwitcher) @@ -373,7 +373,7 @@ describe('tool specific content', () => { describe('code examples', () => { it('loads correctly', async () => { - await page.goto('http://localhost:4001/en/code-security') + await page.goto('http://localhost:4000/en/code-security') const shownCards = await page.$$('[data-testid=code-example-card]') const shownNoResult = await page.$('[data-testid=code-examples-no-results]') expect(shownCards.length).toBeGreaterThan(0) @@ -381,7 +381,7 @@ describe('code examples', () => { }) it('filters cards', async () => { - await page.goto('http://localhost:4001/en/code-security') + await page.goto('http://localhost:4000/en/code-security') await page.click('[data-testid=code-examples-input]') await page.type('[data-testid=code-examples-input]', 'policy') await page.click('[data-testid=code-examples-search-btn]') @@ -390,7 +390,7 @@ describe('code examples', () => { }) it('shows more cards', async () => { - await page.goto('http://localhost:4001/en/code-security') + await page.goto('http://localhost:4000/en/code-security') const initialCards = await page.$$('[data-testid=code-example-card]') await page.click('[data-testid=code-examples-show-more]') const moreCards = await page.$$('[data-testid=code-example-card]') @@ -398,7 +398,7 @@ describe('code examples', () => { }) it('displays no result message', async () => { - await page.goto('http://localhost:4001/en/code-security') + await page.goto('http://localhost:4000/en/code-security') await page.click('[data-testid=code-examples-input]') await page.type('[data-testid=code-examples-input]', 'this should not work') await page.click('[data-testid=code-examples-search-btn]') @@ -411,7 +411,7 @@ describe('code examples', () => { describe('filter cards', () => { it('works with select input', async () => { - await page.goto('http://localhost:4001/en/code-security/guides') + await page.goto('http://localhost:4000/en/code-security/guides') // 2nd element is 'Overview' await page.click('[data-testid=card-filter-types] button') await page.click('[data-testid=types-dropdown] > div > div:nth-child(2)') @@ -424,7 +424,7 @@ describe('filter cards', () => { }) it('works with select input on an Enterprise version', async () => { - await page.goto(`http://localhost:4001/en/enterprise-server@${latest}/code-security/guides`) + await page.goto(`http://localhost:4000/en/enterprise-server@${latest}/code-security/guides`) // 2nd element is 'Overview' await page.click('[data-testid=card-filter-types] button') await page.click('[data-testid=types-dropdown] > div > div:nth-child(2)') @@ -445,7 +445,7 @@ describe('language banner', () => { // run a reliable test. But hey, on the bright side, if we don't have a WIP // language then this code will never run anyway! if (wipLanguageKey) { - const res = await page.goto(`http://localhost:4001/${wipLanguageKey}/actions`) + const res = await page.goto(`http://localhost:4000/${wipLanguageKey}/actions`) expect(res.ok()).toBe(true) const href = await page.$eval('a#to-english-doc', (el) => el.href) expect(href.endsWith('/en/actions')).toBe(true) @@ -461,11 +461,11 @@ describe.skip('next/link client-side navigation', () => { it('should have 200 response to /_next/data when link is clicked', async () => { const initialViewport = page.viewport() await page.setViewport({ width: 1024, height: 768 }) - await page.goto('http://localhost:4001/en/actions/guides') + await page.goto('http://localhost:4000/en/actions/guides') const [response] = await Promise.all([ page.waitForResponse((response) => - response.url().startsWith('http://localhost:4001/_next/data') + response.url().startsWith('http://localhost:4000/_next/data') ), page.waitForNavigation({ waitUntil: 'networkidle2' }), page.click( @@ -496,7 +496,7 @@ describe('iframe pages', () => { }) // Hardcoded path to a page where we know we have a YouTube embed - const res = await newPage.goto('http://localhost:4001/en/codespaces') + const res = await newPage.goto('http://localhost:4000/en/codespaces') expect(res.ok()).toBeTruthy() expect(failedURLs.length, `Following URLs ${failedURLs.join(', ')} failed`).toBeFalsy()