diff --git a/package.json b/package.json index 8042b7b175..6f5c33f1b9 100644 --- a/package.json +++ b/package.json @@ -24,12 +24,12 @@ "db:seed": "prisma db seed", "db:init": "run-s db:migrate db:seed", "test": "pnpm turbo run test", + "e2e": "pnpm turbo run e2e", "jest": "jest -c jest.config.js --", - "jest:e2e": "jest -c jest.config.e2e.js --forceExit --", + "jest:e2e": "pnpm turbo run e2e", "coverage": "jest -c jest.config.js --collectCoverage --", "jest-watch": "jest -c jest.config.js --watch --", "jest-update": "jest -c jest.config.js --updateSnapshot --", - "jest:e2e-watch": "jest -c jest.config.e2e.js --watch --", "test-ci": "run-s prettier-check test", "pre-commit": "pretty-quick --staged", "preversion": "node tools/collect-dependencies.js -- -o src/api/dependency-discovery/deps.txt && git add src/api/dependency-discovery/deps.txt", @@ -67,14 +67,10 @@ "eslint": "7.32.0", "husky": "7.0.4", "jest": "27.5.1", - "jest-circus": "27.5.1", "jest-environment-node": "27.5.1", "jest-fetch-mock": "3.0.3", - "jest-playwright-preset": "1.7.0", - "jest-runner": "27.5.1", "nock": "13.2.4", "npm-run-all": "4.1.5", - "playwright": "1.20.2", "prettier": "2.5.1", "pretty-quick": "3.1.3", "prisma": "4.9.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a9e1d974f3..1cd783b618 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,14 +20,10 @@ importers: eslint: 7.32.0 husky: 7.0.4 jest: 27.5.1 - jest-circus: 27.5.1 jest-environment-node: 27.5.1 jest-fetch-mock: 3.0.3 - jest-playwright-preset: 1.7.0 - jest-runner: 27.5.1 nock: 13.2.4 npm-run-all: 4.1.5 - playwright: 1.20.2 prettier: 2.5.1 pretty-quick: 3.1.3 prisma: 4.9.0 @@ -55,14 +51,10 @@ importers: eslint: 7.32.0 husky: 7.0.4 jest: 27.5.1 - jest-circus: 27.5.1 jest-environment-node: 27.5.1 jest-fetch-mock: 3.0.3 - jest-playwright-preset: 1.7.0_l32tkdczjgqxuqrrxonq2y4q5e - jest-runner: 27.5.1 nock: 13.2.4 npm-run-all: 4.1.5 - playwright: 1.20.2 prettier: 2.5.1 pretty-quick: 3.1.3_prettier@2.5.1 prisma: 4.9.0 @@ -265,6 +257,7 @@ importers: src/api/sso: specifiers: + '@playwright/test': 1.29.2 '@senecacdot/eslint-config-telescope': 1.1.0 '@senecacdot/satellite': ^1.29.0 '@slack/bolt': 3.12.2 @@ -278,10 +271,11 @@ importers: minimatch: 3.0.5 nodemon: 2.0.20 normalize-url: 6.1.0 - passport: 0.5.2 + passport: 0.6.0 passport-saml: 3.2.4 + playwright: 1.29.2 rimraf: 3.0.2 - supertest: 6.1.6 + supertest: 6.3.2 dependencies: '@senecacdot/satellite': 1.29.0 '@slack/bolt': 3.12.2 @@ -292,15 +286,17 @@ importers: jsonwebtoken: 9.0.0 minimatch: 3.0.5 normalize-url: 6.1.0 - passport: 0.5.2 + passport: 0.6.0 passport-saml: 3.2.4 devDependencies: + '@playwright/test': 1.29.2 '@senecacdot/eslint-config-telescope': 1.1.0_eslint@7.32.0 env-cmd: 10.1.0 eslint: 7.32.0 nodemon: 2.0.20 + playwright: 1.29.2 rimraf: 3.0.2 - supertest: 6.1.6 + supertest: 6.3.2 src/api/status: specifiers: @@ -7190,6 +7186,15 @@ packages: nullthrows: 1.1.1 dev: true + /@playwright/test/1.29.2: + resolution: {integrity: sha512-+3/GPwOgcoF0xLz/opTnahel1/y42PdcgZ4hs+BZGIUjtmEFSXGg+nFoaH3NSmuc7a6GSFwXDJ5L7VXpqzigNg==} + engines: {node: '>=14'} + hasBin: true + dependencies: + '@types/node': 18.11.8 + playwright-core: 1.29.2 + dev: true + /@pm2/agent/2.0.1: resolution: {integrity: sha512-QKHMm6yexcvdDfcNE7PL9D6uEjoQPGRi+8dh+rc4Hwtbpsbh5IAvZbz3BVGjcd4HaX6pt2xGpOohG7/Y2L4QLw==} dependencies: @@ -8181,12 +8186,6 @@ packages: /@types/unist/2.0.6: resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} - /@types/wait-on/5.3.1: - resolution: {integrity: sha512-2FFOKCF/YydrMUaqg+fkk49qf0e5rDgwt6aQsMzFQzbS419h2gNOXyiwp/o2yYy27bi/C1z+HgfncryjGzlvgQ==} - dependencies: - '@types/node': 18.11.8 - dev: true - /@types/ws/7.4.7: resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} dependencies: @@ -8213,14 +8212,6 @@ packages: '@types/yargs-parser': 21.0.0 dev: false - /@types/yauzl/2.10.0: - resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} - requiresBuild: true - dependencies: - '@types/node': 18.11.8 - dev: true - optional: true - /@types/yup/0.29.14: resolution: {integrity: sha512-Ynb/CjHhE/Xp/4bhHmQC4U1Ox+I2OpfRYF3dnNgQqn1cHa6LK3H1wJMNPT02tSVZA6FYuXE2ITORfbnb6zBCSA==} dev: false @@ -8713,6 +8704,7 @@ packages: dependencies: clean-stack: 2.2.0 indent-string: 4.0.0 + dev: false /ajv-formats/2.1.1_ajv@8.11.0: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} @@ -8863,17 +8855,6 @@ packages: normalize-path: 3.0.0 picomatch: 2.3.1 - /append-transform/2.0.0: - resolution: {integrity: sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==} - engines: {node: '>=8'} - dependencies: - default-require-extensions: 3.0.1 - dev: true - - /archy/1.0.0: - resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} - dev: true - /arg/4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} dev: true @@ -9004,7 +8985,6 @@ packages: /asap/2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} - dev: false /ast-types-flow/0.0.7: resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} @@ -9078,14 +9058,6 @@ packages: engines: {node: '>=4'} dev: true - /axios/0.21.4: - resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} - dependencies: - follow-redirects: 1.15.2 - transitivePeerDependencies: - - debug - dev: true - /axios/0.21.4_debug@4.3.4: resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} dependencies: @@ -9599,10 +9571,6 @@ packages: resolution: {integrity: sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==} dev: false - /buffer-crc32/0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - dev: true - /buffer-equal-constant-time/1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} dev: false @@ -9706,16 +9674,6 @@ packages: responselike: 2.0.1 dev: false - /caching-transform/4.0.0: - resolution: {integrity: sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==} - engines: {node: '>=8'} - dependencies: - hasha: 5.2.2 - make-dir: 3.1.0 - package-hash: 4.0.0 - write-file-atomic: 3.0.3 - dev: true - /call-bind/1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} dependencies: @@ -9903,6 +9861,7 @@ packages: /clean-stack/2.2.0: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} + dev: false /clean-webpack-plugin/4.0.0_webpack@5.9.0: resolution: {integrity: sha512-WuWE1nyTNAyW5T7oNyys2EN0cfP2fdRxhxnIQWiAp0bMabPdHhoGxM8A6YL2GhqwgrPnnaemVE7nv5XJ2Fhh2w==} @@ -9943,14 +9902,6 @@ packages: chalk: 3.0.0 dev: false - /cliui/6.0.0: - resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - dev: true - /cliui/7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} dependencies: @@ -10045,11 +9996,6 @@ packages: resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==} dev: false - /colors/1.4.0: - resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} - engines: {node: '>=0.1.90'} - dev: true - /combine-promises/1.1.0: resolution: {integrity: sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg==} engines: {node: '>=10'} @@ -10072,10 +10018,6 @@ packages: /commander/2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - /commander/3.0.2: - resolution: {integrity: sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==} - dev: true - /commander/4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} @@ -10092,6 +10034,7 @@ packages: /commander/8.3.0: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} + dev: false /common-tags/1.8.2: resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} @@ -10534,14 +10477,6 @@ packages: resolution: {integrity: sha512-yi1x3EAWKjQTreYWeSd98431AV+IEE0qoDyOoaHJ7KJ21gv6HtBXHVLX74opVSGqcR8/AbjJBHAHpcOy2bj5Gg==} dev: false - /cwd/0.10.0: - resolution: {integrity: sha512-YGZxdTTL9lmLkCUTpg4j0zQ7IhRB5ZmqNBbGCl3Tg6MP/d5/6sY7L5mmTjzbc6JKgVZYiqTQTNhPFsbXNGlRaA==} - engines: {node: '>=0.8'} - dependencies: - find-pkg: 0.1.2 - fs-exists-sync: 0.1.0 - dev: true - /d/1.0.1: resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} dependencies: @@ -11101,18 +11036,6 @@ packages: supports-color: 5.5.0 dev: true - /debug/4.3.3: - resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: true - /debug/4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -11214,13 +11137,6 @@ packages: execa: 5.1.1 dev: false - /default-require-extensions/3.0.1: - resolution: {integrity: sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==} - engines: {node: '>=8'} - dependencies: - strip-bom: 4.0.0 - dev: true - /defer-to-connect/1.1.3: resolution: {integrity: sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==} @@ -11363,6 +11279,13 @@ packages: - supports-color dev: false + /dezalgo/1.0.4: + resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} + dependencies: + asap: 2.0.6 + wrappy: 1.0.2 + dev: true + /diff-sequences/27.5.1: resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -11711,10 +11634,6 @@ packages: next-tick: 1.1.0 dev: false - /es6-error/4.1.1: - resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} - dev: true - /es6-iterator/2.0.3: resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} dependencies: @@ -12464,17 +12383,6 @@ packages: engines: {node: '>=6'} dev: false - /expand-tilde/1.2.2: - resolution: {integrity: sha512-rtmc+cjLZqnu9dSYosX9EWmSJhTwpACgJQTfj4hgg2JjOD/6SIQalZrt4a3aQeh++oNxkazcaxrhPUj6+g5G/Q==} - engines: {node: '>=0.10.0'} - dependencies: - os-homedir: 1.0.2 - dev: true - - /expect-playwright/0.7.2: - resolution: {integrity: sha512-5o9si+8SUi68QVI0CRVv8tvTjZinpJWRSfQ3GP6v0DvlK55lDgFvD79r6A/NU+EUawrBc62qP30MxzOUnXNJZQ==} - dev: true - /expect/27.5.1: resolution: {integrity: sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -12634,20 +12542,6 @@ packages: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} dev: false - /extract-zip/2.0.1: - resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} - engines: {node: '>= 10.17.0'} - hasBin: true - dependencies: - debug: 4.3.4 - get-stream: 5.2.0 - yauzl: 2.10.0 - optionalDependencies: - '@types/yauzl': 2.10.0 - transitivePeerDependencies: - - supports-color - dev: true - /fast-copy/3.0.0: resolution: {integrity: sha512-4HzS+9pQ5Yxtv13Lhs1Z1unMXamBdn5nA4bEi1abYpDNSpSp7ODYQ1KPMF6nTatfEzgH6/zPvXKU1zvHiUjWlA==} dev: false @@ -12752,12 +12646,6 @@ packages: resolution: {integrity: sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==} dev: false - /fd-slicer/1.1.0: - resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} - dependencies: - pend: 1.2.0 - dev: true - /feed/4.2.2: resolution: {integrity: sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==} engines: {node: '>=0.4.0'} @@ -12863,14 +12751,6 @@ packages: make-dir: 3.1.0 pkg-dir: 4.2.0 - /find-file-up/0.1.3: - resolution: {integrity: sha512-mBxmNbVyjg1LQIIpgO8hN+ybWBgDQK8qjht+EbrTCGmmPV/sc7RF1i9stPTD6bpvXZywBdrwRYxhSdJv867L6A==} - engines: {node: '>=0.10.0'} - dependencies: - fs-exists-sync: 0.1.0 - resolve-dir: 0.1.1 - dev: true - /find-my-way/5.6.0: resolution: {integrity: sha512-pFTzbl2u+iSrvVOGtfKenvDmNIhNtEcwbzvRMfx3TGO69fbO5udgTKtAZAaUfIUrHQWLkkWvhNafNz179kaCIw==} engines: {node: '>=12'} @@ -12880,24 +12760,6 @@ packages: safe-regex2: 2.0.0 dev: false - /find-pkg/0.1.2: - resolution: {integrity: sha512-0rnQWcFwZr7eO0513HahrWafsc3CTFioEB7DRiEYCUM/70QXSY8f3mCST17HXLcPvEhzH/Ty/Bxd72ZZsr/yvw==} - engines: {node: '>=0.10.0'} - dependencies: - find-file-up: 0.1.3 - dev: true - - /find-process/1.4.7: - resolution: {integrity: sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==} - hasBin: true - dependencies: - chalk: 4.1.2 - commander: 5.1.0 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - /find-root/1.1.0: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} dev: false @@ -12957,6 +12819,7 @@ packages: peerDependenciesMeta: debug: optional: true + dev: false /follow-redirects/1.15.2_debug@4.3.4: resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} @@ -12976,14 +12839,6 @@ packages: is-callable: 1.2.7 dev: false - /foreground-child/2.0.0: - resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} - engines: {node: '>=8.0.0'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 3.0.7 - dev: true - /fork-ts-checker-webpack-plugin/6.5.2_x4yu7ubf2kzyfubmn4ib5i74pq: resolution: {integrity: sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA==} engines: {node: '>=10', yarn: '>=1.0.0'} @@ -13045,6 +12900,15 @@ packages: resolution: {integrity: sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==} deprecated: 'Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau' + /formidable/2.1.1: + resolution: {integrity: sha512-0EcS9wCFEzLvfiks7omJ+SiYJAiD+TzK4Pcw1UlUoGnhUxDcMKjt0P7x8wEb0u6OHu8Nb98WG3nxtlF5C7bvUQ==} + dependencies: + dezalgo: 1.0.4 + hexoid: 1.0.0 + once: 1.4.0 + qs: 6.11.0 + dev: true + /formik/2.2.9_react@17.0.2: resolution: {integrity: sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==} peerDependencies: @@ -13083,16 +12947,12 @@ packages: /fromentries/1.3.2: resolution: {integrity: sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==} + dev: false /fs-constants/1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} dev: false - /fs-exists-sync/0.1.0: - resolution: {integrity: sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==} - engines: {node: '>=0.10.0'} - dev: true - /fs-extra/10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} @@ -13309,14 +13169,6 @@ packages: dependencies: ini: 2.0.0 - /global-modules/0.2.3: - resolution: {integrity: sha512-JeXuCbvYzYXcwE6acL9V2bAOeSIGl4dD+iwLY9iUx2VBJJ80R18HCn+JCwHM9Oegdfya3lEkGCdaRkSyc10hDA==} - engines: {node: '>=0.10.0'} - dependencies: - global-prefix: 0.1.5 - is-windows: 0.2.0 - dev: true - /global-modules/2.0.0: resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} engines: {node: '>=6'} @@ -13324,16 +13176,6 @@ packages: global-prefix: 3.0.0 dev: false - /global-prefix/0.1.5: - resolution: {integrity: sha512-gOPiyxcD9dJGCEArAhF4Hd0BAqvAe/JzERP7tYumE4yIkmIedPUVXcJFWbV3/p/ovIIvKjkrTk+f1UVkq7vvbw==} - engines: {node: '>=0.10.0'} - dependencies: - homedir-polyfill: 1.0.3 - ini: 1.3.8 - is-windows: 0.2.0 - which: 1.3.1 - dev: true - /global-prefix/3.0.0: resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} engines: {node: '>=6'} @@ -13517,14 +13359,6 @@ packages: dependencies: function-bind: 1.1.1 - /hasha/5.2.2: - resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==} - engines: {node: '>=8'} - dependencies: - is-stream: 2.0.1 - type-fest: 0.8.1 - dev: true - /hast-to-hyperscript/9.0.1: resolution: {integrity: sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==} dependencies: @@ -13604,6 +13438,11 @@ packages: readable-stream: 3.6.0 dev: false + /hexoid/1.0.0: + resolution: {integrity: sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==} + engines: {node: '>=8'} + dev: true + /highlight.js/11.4.0: resolution: {integrity: sha512-nawlpCBCSASs7EdvZOYOYVkJpGmAOKMYZgZtUqSRqodZE0GRVcFKwo1RcpeOemqh9hyttTdd5wDBwHkuSyUfnA==} engines: {node: '>=12.0.0'} @@ -13626,13 +13465,6 @@ packages: react-is: 16.13.1 dev: false - /homedir-polyfill/1.0.3: - resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} - engines: {node: '>=0.10.0'} - dependencies: - parse-passwd: 1.0.0 - dev: true - /hosted-git-info/2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} @@ -13883,16 +13715,6 @@ packages: resolve-alpn: 1.2.1 dev: false - /https-proxy-agent/5.0.0: - resolution: {integrity: sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==} - engines: {node: '>= 6'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - /https-proxy-agent/5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} @@ -14017,6 +13839,7 @@ packages: /indent-string/4.0.0: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} + dev: false /indent-string/5.0.0: resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} @@ -14142,6 +13965,7 @@ packages: /ip/2.0.0: resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} + dev: false /ipaddr.js/1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} @@ -14462,16 +14286,6 @@ packages: resolution: {integrity: sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==} dev: false - /is-windows/0.2.0: - resolution: {integrity: sha512-n67eJYmXbniZB7RF4I/FTjK1s6RPOCTxhYrVYLRaCt3lF0mpWZPKr3T2LSZAqyjQsxR2qMmGYXXzK0YWwcPM1Q==} - engines: {node: '>=0.10.0'} - dev: true - - /is-windows/1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - dev: true - /is-word-character/1.0.4: resolution: {integrity: sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==} dev: false @@ -14518,25 +14332,6 @@ packages: resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} engines: {node: '>=8'} - /istanbul-lib-hook/3.0.0: - resolution: {integrity: sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==} - engines: {node: '>=8'} - dependencies: - append-transform: 2.0.0 - dev: true - - /istanbul-lib-instrument/4.0.3: - resolution: {integrity: sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==} - engines: {node: '>=8'} - dependencies: - '@babel/core': 7.17.10 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.0 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - dev: true - /istanbul-lib-instrument/5.2.1: resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} engines: {node: '>=8'} @@ -14549,18 +14344,6 @@ packages: transitivePeerDependencies: - supports-color - /istanbul-lib-processinfo/2.0.3: - resolution: {integrity: sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==} - engines: {node: '>=8'} - dependencies: - archy: 1.0.0 - cross-spawn: 7.0.3 - istanbul-lib-coverage: 3.2.0 - p-map: 3.0.0 - rimraf: 3.0.2 - uuid: 8.3.2 - dev: true - /istanbul-lib-report/3.0.0: resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} engines: {node: '>=8'} @@ -14627,7 +14410,7 @@ packages: '@jest/environment': 27.5.1 '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 18.11.7 + '@types/node': 18.11.8 chalk: 4.1.2 co: 4.6.0 dedent: 0.7.0 @@ -14874,29 +14657,6 @@ packages: '@types/node': 18.11.8 dev: true - /jest-playwright-preset/1.7.0_l32tkdczjgqxuqrrxonq2y4q5e: - resolution: {integrity: sha512-G25Nik+By0SNniMDdkouDL/yA1LdqjzsXNSVU4xnRX1typjXRmzRE0aSgqxas2sRi8cwG3M1ioHdkLLsp6sang==} - peerDependencies: - jest: '>=26.6.3' - jest-circus: '>=26.6.3' - jest-environment-node: '>=26.6.3' - jest-runner: '>=26.6.3' - dependencies: - expect-playwright: 0.7.2 - jest: 27.5.1 - jest-circus: 27.5.1 - jest-environment-node: 27.5.1 - jest-process-manager: 0.3.1 - jest-runner: 27.5.1 - nyc: 15.1.0 - playwright-core: 1.27.1 - rimraf: 3.0.2 - uuid: 8.3.2 - transitivePeerDependencies: - - debug - - supports-color - dev: true - /jest-pnp-resolver/1.2.2_jest-resolve@27.5.1: resolution: {integrity: sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==} engines: {node: '>=6'} @@ -14909,24 +14669,6 @@ packages: jest-resolve: 27.5.1 dev: true - /jest-process-manager/0.3.1: - resolution: {integrity: sha512-x9W54UgZ7IkzUHgXtnI1x4GKOVjxtwW0CA/7yGbTHtT/YhENO0Lic2yfVyC/gekn7OIEMcQmy0L1r9WLQABfqw==} - dependencies: - '@types/wait-on': 5.3.1 - chalk: 4.1.2 - cwd: 0.10.0 - exit: 0.1.2 - find-process: 1.4.7 - prompts: 2.4.2 - signal-exit: 3.0.7 - spawnd: 5.0.0 - tree-kill: 1.2.2 - wait-on: 5.3.0 - transitivePeerDependencies: - - debug - - supports-color - dev: true - /jest-regex-util/27.5.1: resolution: {integrity: sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -14967,7 +14709,7 @@ packages: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 18.11.7 + '@types/node': 18.11.8 chalk: 4.1.2 emittery: 0.8.1 graceful-fs: 4.2.10 @@ -15167,10 +14909,6 @@ packages: engines: {node: '>=10'} dev: false - /jpeg-js/0.4.3: - resolution: {integrity: sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==} - dev: true - /js-cookie/2.2.1: resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} dev: false @@ -15731,10 +15469,6 @@ packages: resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} dev: false - /lodash.flattendeep/4.4.0: - resolution: {integrity: sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==} - dev: true - /lodash.flow/3.5.0: resolution: {integrity: sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==} dev: false @@ -16026,12 +15760,6 @@ packages: engines: {node: '>=4.0.0'} hasBin: true - /mime/3.0.0: - resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} - engines: {node: '>=10.0.0'} - hasBin: true - dev: true - /mimic-fn/2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -16417,13 +16145,6 @@ packages: /node-int64/0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - /node-preload/0.2.1: - resolution: {integrity: sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==} - engines: {node: '>=8'} - dependencies: - process-on-spawn: 1.0.0 - dev: true - /node-releases/2.0.6: resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} @@ -16550,42 +16271,6 @@ packages: /nwsapi/2.2.2: resolution: {integrity: sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==} - /nyc/15.1.0: - resolution: {integrity: sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==} - engines: {node: '>=8.9'} - hasBin: true - dependencies: - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - caching-transform: 4.0.0 - convert-source-map: 1.9.0 - decamelize: 1.2.0 - find-cache-dir: 3.3.2 - find-up: 4.1.0 - foreground-child: 2.0.0 - get-package-type: 0.1.0 - glob: 7.2.3 - istanbul-lib-coverage: 3.2.0 - istanbul-lib-hook: 3.0.0 - istanbul-lib-instrument: 4.0.3 - istanbul-lib-processinfo: 2.0.3 - istanbul-lib-report: 3.0.0 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.5 - make-dir: 3.1.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.2 - signal-exit: 3.0.7 - spawn-wrap: 2.0.0 - test-exclude: 6.0.0 - yargs: 15.4.1 - transitivePeerDependencies: - - supports-color - dev: true - /object-assign/4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -16768,11 +16453,6 @@ packages: resolution: {integrity: sha512-EHQ/jk4/a9hLupIKxTfUsQRej1Yd/0QLQs3vGvIqg5ZtCYSzNhkzHoZc7Zf4e4kUlDaC3Uw8Q/1opOLNN2OKRQ==} dev: true - /os-homedir/1.0.2: - resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==} - engines: {node: '>=0.10.0'} - dev: true - /os-tmpdir/1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} @@ -16833,13 +16513,6 @@ packages: engines: {node: '>=6'} dev: false - /p-map/3.0.0: - resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==} - engines: {node: '>=8'} - dependencies: - aggregate-error: 3.1.0 - dev: true - /p-map/4.0.0: resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} engines: {node: '>=10'} @@ -16909,16 +16582,6 @@ packages: netmask: 2.0.2 dev: false - /package-hash/4.0.0: - resolution: {integrity: sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==} - engines: {node: '>=8'} - dependencies: - graceful-fs: 4.2.10 - hasha: 5.2.2 - lodash.flattendeep: 4.4.0 - release-zalgo: 1.0.0 - dev: true - /package-json/6.5.0: resolution: {integrity: sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==} engines: {node: '>=8'} @@ -17008,11 +16671,6 @@ packages: resolution: {integrity: sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==} dev: false - /parse-passwd/1.0.0: - resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} - engines: {node: '>=0.10.0'} - dev: true - /parse-path/4.0.4: resolution: {integrity: sha512-Z2lWUis7jlmXC1jeOG9giRO2+FsuyNipeQ43HAjqAZjwSe3SEf+q/84FGPHoso3kyntbxa4c4i77t3m6fGf8cw==} dependencies: @@ -17083,12 +16741,13 @@ packages: engines: {node: '>= 0.4.0'} dev: false - /passport/0.5.2: - resolution: {integrity: sha512-w9n/Ot5I7orGD4y+7V3EFJCQEznE5RxHamUxcqLT2QoJY0f2JdN8GyHonYFvN0Vz+L6lUJfVhrk2aZz2LbuREw==} + /passport/0.6.0: + resolution: {integrity: sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==} engines: {node: '>= 0.4.0'} dependencies: passport-strategy: 1.0.0 pause: 0.0.1 + utils-merge: 1.0.1 dev: false /path-exists/3.0.0: @@ -17147,10 +16806,6 @@ packages: resolution: {integrity: sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=} dev: false - /pend/1.2.0: - resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} - dev: true - /perfect-scrollbar/1.5.5: resolution: {integrity: sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g==} dev: false @@ -17274,13 +16929,6 @@ packages: resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==} engines: {node: '>= 6'} - /pixelmatch/5.2.1: - resolution: {integrity: sha512-WjcAdYSnKrrdDdqTcVEY7aB7UhhwjYQKYhHiBXdJef0MOaQeYpUdQ+iVyBLa5YBKS8MPVPPMX7rpOByISLpeEQ==} - hasBin: true - dependencies: - pngjs: 4.0.1 - dev: true - /pkg-dir/4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -17294,52 +16942,19 @@ packages: find-up: 3.0.0 dev: false - /playwright-core/1.20.2: - resolution: {integrity: sha512-iV6+HftSPalynkq0CYJala1vaTOq7+gU9BRfKCdM9bAxNq/lFLrwbluug2Wt5OoUwbMABcnTThIEm3/qUhCdJQ==} - engines: {node: '>=12'} - hasBin: true - dependencies: - colors: 1.4.0 - commander: 8.3.0 - debug: 4.3.3 - extract-zip: 2.0.1 - https-proxy-agent: 5.0.0 - jpeg-js: 0.4.3 - mime: 3.0.0 - pixelmatch: 5.2.1 - pngjs: 6.0.0 - progress: 2.0.3 - proper-lockfile: 4.1.2 - proxy-from-env: 1.1.0 - rimraf: 3.0.2 - socks-proxy-agent: 6.1.1 - stack-utils: 2.0.5 - ws: 8.4.2 - yauzl: 2.10.0 - yazl: 2.5.1 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /playwright-core/1.27.1: - resolution: {integrity: sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q==} + /playwright-core/1.29.2: + resolution: {integrity: sha512-94QXm4PMgFoHAhlCuoWyaBYKb92yOcGVHdQLoxQ7Wjlc7Flg4aC/jbFW7xMR52OfXMVkWicue4WXE7QEegbIRA==} engines: {node: '>=14'} hasBin: true dev: true - /playwright/1.20.2: - resolution: {integrity: sha512-p6GE8A/f2G7t8FIk/AwQ94nT7R7tyPRJyKt1FwRjwBDf4WdpgoAr4hDfMgHy+CkClR22adFjopGwhxXAPsewhg==} - engines: {node: '>=12'} + /playwright/1.29.2: + resolution: {integrity: sha512-hKBYJUtdmYzcjdhYDkP9WGtORwwZBBKAW8+Lz7sr0ZMxtJr04ASXVzH5eBWtDkdb0c3LLFsehfPBTRfvlfKJOA==} + engines: {node: '>=14'} hasBin: true requiresBuild: true dependencies: - playwright-core: 1.20.2 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate + playwright-core: 1.29.2 dev: true /please-upgrade-node/3.2.0: @@ -17439,16 +17054,6 @@ packages: - utf-8-validate dev: false - /pngjs/4.0.1: - resolution: {integrity: sha512-rf5+2/ioHeQxR6IxuYNYGFytUyG3lma/WW1nsmjeHlWwtb2aByla6dkVc8pmJ9nplzkTA0q2xx7mMWrOTqT4Gg==} - engines: {node: '>=8.0.0'} - dev: true - - /pngjs/6.0.0: - resolution: {integrity: sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==} - engines: {node: '>=12.13.0'} - dev: true - /popper.js/1.16.1-lts: resolution: {integrity: sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==} dev: false @@ -18008,13 +17613,6 @@ packages: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} dev: false - /process-on-spawn/1.0.0: - resolution: {integrity: sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==} - engines: {node: '>=8'} - dependencies: - fromentries: 1.3.2 - dev: true - /process-warning/2.0.0: resolution: {integrity: sha512-+MmoAXoUX+VTHAlwns0h+kFUWFs/3FZy+ZuchkgjyOu3oioLAo2LB5aCfKPh2+P9O18i3m43tUEv3YqttSy0Ww==} dev: false @@ -18084,14 +17682,6 @@ packages: engines: {node: '>= 8'} dev: true - /proper-lockfile/4.1.2: - resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} - dependencies: - graceful-fs: 4.2.10 - retry: 0.12.0 - signal-exit: 3.0.7 - dev: true - /property-expr/2.0.5: resolution: {integrity: sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==} dev: false @@ -18136,6 +17726,7 @@ packages: /proxy-from-env/1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false /psl/1.9.0: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} @@ -18782,13 +18373,6 @@ packages: engines: {node: '>= 0.10'} dev: false - /release-zalgo/1.0.0: - resolution: {integrity: sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==} - engines: {node: '>=4'} - dependencies: - es6-error: 4.1.1 - dev: true - /remark-emoji/2.2.0: resolution: {integrity: sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w==} dependencies: @@ -18882,10 +18466,6 @@ packages: resolution: {integrity: sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==} dev: false - /require-main-filename/2.0.0: - resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} - dev: true - /requires-port/1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} @@ -18909,14 +18489,6 @@ packages: resolve-from: 5.0.0 dev: true - /resolve-dir/0.1.1: - resolution: {integrity: sha512-QxMPqI6le2u0dCLyiGzgy92kjkkL6zO0XyvHzjdTNH3zM6e5Hz3BwG6+aEyNgiQ5Xz6PwTwgQEj3U50dByPKIA==} - engines: {node: '>=0.10.0'} - dependencies: - expand-tilde: 1.2.2 - global-modules: 0.2.3 - dev: true - /resolve-from/4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -18967,11 +18539,6 @@ packages: engines: {node: '>=4'} dev: false - /retry/0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - dev: true - /retry/0.13.1: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} engines: {node: '>= 4'} @@ -19079,13 +18646,6 @@ packages: resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} dev: false - /rxjs/6.6.7: - resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} - engines: {npm: '>=2.0.0'} - dependencies: - tslib: 1.14.1 - dev: true - /rxjs/7.5.7: resolution: {integrity: sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==} dependencies: @@ -19361,10 +18921,6 @@ packages: - supports-color dev: false - /set-blocking/2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: true - /set-harmonic-interval/1.0.1: resolution: {integrity: sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==} engines: {node: '>=6.9'} @@ -19520,6 +19076,7 @@ packages: /smart-buffer/4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + dev: false /smoothscroll-polyfill/0.4.4: resolution: {integrity: sha512-TK5ZA9U5RqCwMpfoMq/l1mrH0JAR7y7KRvOBx0n2869aLxch+gT9GhN3yUfjiw+d/DiF1mKo14+hd62JyMmoBg==} @@ -19544,23 +19101,13 @@ packages: - supports-color dev: false - /socks-proxy-agent/6.1.1: - resolution: {integrity: sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==} - engines: {node: '>= 10'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - socks: 2.7.1 - transitivePeerDependencies: - - supports-color - dev: true - /socks/2.7.1: resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==} engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} dependencies: ip: 2.0.0 smart-buffer: 4.2.0 + dev: false /sonic-boom/3.2.0: resolution: {integrity: sha512-SbbZ+Kqj/XIunvIAgUZRlqd6CGQYq71tRRbXR92Za8J/R3Yh4Av+TWENiSiEgnlwckYLyP0YZQWVfyNC0dzLaA==} @@ -19628,29 +19175,6 @@ packages: resolution: {integrity: sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==} dev: false - /spawn-wrap/2.0.0: - resolution: {integrity: sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==} - engines: {node: '>=8'} - dependencies: - foreground-child: 2.0.0 - is-windows: 1.0.2 - make-dir: 3.1.0 - rimraf: 3.0.2 - signal-exit: 3.0.7 - which: 2.0.2 - dev: true - - /spawnd/5.0.0: - resolution: {integrity: sha512-28+AJr82moMVWolQvlAIv3JcYDkjkFTEmfDc503wxrF5l2rQ3dFz6DpbXp3kD4zmgGGldfM4xM4v1sFj/ZaIOA==} - dependencies: - exit: 0.1.2 - signal-exit: 3.0.7 - tree-kill: 1.2.2 - wait-port: 0.2.14 - transitivePeerDependencies: - - supports-color - dev: true - /spdx-correct/3.1.1: resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} dependencies: @@ -19976,6 +19500,24 @@ packages: transitivePeerDependencies: - supports-color + /superagent/8.0.5: + resolution: {integrity: sha512-lQVE0Praz7nHiSaJLKBM/cZyi7J0E4io8tWnGSBdBrqAzhzrjQ/F5iGP9Zr29CJC8N5zYdhG2kKaNcB6dKxp7g==} + engines: {node: '>=6.4.0 <13 || >=14'} + dependencies: + component-emitter: 1.3.0 + cookiejar: 2.1.3 + debug: 4.3.4 + fast-safe-stringify: 2.1.1 + form-data: 4.0.0 + formidable: 2.1.1 + methods: 1.1.2 + mime: 2.6.0 + qs: 6.11.0 + semver: 7.3.8 + transitivePeerDependencies: + - supports-color + dev: true + /supertest/6.1.6: resolution: {integrity: sha512-0hACYGNJ8OHRg8CRITeZOdbjur7NLuNs0mBjVhdpxi7hP6t3QIbOzLON5RTUmZcy2I9riuII3+Pr2C7yztrIIg==} engines: {node: '>=6.0.0'} @@ -19985,6 +19527,16 @@ packages: transitivePeerDependencies: - supports-color + /supertest/6.3.2: + resolution: {integrity: sha512-mSmbW/sPpBU6K8w8189ZiHdc62zMe7dCHpC2ktS9tc0/d2DN0FaxNbDJJNFknZD4jCrGJpxkiFoVyemvKgOdwA==} + engines: {node: '>=6.4.0'} + dependencies: + methods: 1.1.2 + superagent: 8.0.5 + transitivePeerDependencies: + - supports-color + dev: true + /supports-color/5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -20301,11 +19853,6 @@ packages: dependencies: punycode: 2.1.1 - /tree-kill/1.2.2: - resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} - hasBin: true - dev: true - /trim-newlines/4.0.2: resolution: {integrity: sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==} engines: {node: '>=12'} @@ -20585,11 +20132,6 @@ packages: engines: {node: '>=10'} dev: true - /type-fest/0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: true - /type-fest/1.4.0: resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} engines: {node: '>=10'} @@ -20939,7 +20481,7 @@ packages: engines: {node: '>= 4'} /utils-merge/1.0.1: - resolution: {integrity: sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=} + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} dev: false @@ -20952,6 +20494,7 @@ packages: /uuid/8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true + dev: false /v8-compile-cache/2.3.0: resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} @@ -21082,20 +20625,6 @@ packages: dependencies: xml-name-validator: 4.0.0 - /wait-on/5.3.0: - resolution: {integrity: sha512-DwrHrnTK+/0QFaB9a8Ol5Lna3k7WvUR4jzSKmz0YaPBpuN2sACyiPVKVfj6ejnjcajAcvn3wlbTyMIn9AZouOg==} - engines: {node: '>=8.9.0'} - hasBin: true - dependencies: - axios: 0.21.4 - joi: 17.6.4 - lodash: 4.17.21 - minimist: 1.2.7 - rxjs: 6.6.7 - transitivePeerDependencies: - - debug - dev: true - /wait-on/6.0.1: resolution: {integrity: sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==} engines: {node: '>=10.0.0'} @@ -21110,18 +20639,6 @@ packages: - debug dev: false - /wait-port/0.2.14: - resolution: {integrity: sha512-kIzjWcr6ykl7WFbZd0TMae8xovwqcqbx6FM9l+7agOgUByhzdjfzZBPK2CPufldTOMxbUivss//Sh9MFawmPRQ==} - engines: {node: '>=8'} - hasBin: true - dependencies: - chalk: 2.4.2 - commander: 3.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - /walker/1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} dependencies: @@ -21469,10 +20986,6 @@ packages: is-weakset: 2.0.2 dev: false - /which-module/2.0.0: - resolution: {integrity: sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==} - dev: true - /which-typed-array/1.1.8: resolution: {integrity: sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==} engines: {node: '>= 0.4'} @@ -21685,15 +21198,6 @@ packages: workbox-core: 6.5.4 dev: false - /wrap-ansi/6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - /wrap-ansi/7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -21759,19 +21263,6 @@ packages: utf-8-validate: optional: true - /ws/8.4.2: - resolution: {integrity: sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - /xdg-basedir/4.0.0: resolution: {integrity: sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==} engines: {node: '>=8'} @@ -21875,10 +21366,6 @@ packages: resolution: {integrity: sha512-/eyHVRJQCirEkSZ1agRSCwriMhwlyUcFkXD5TPVSLP+IPzjsqMVzZwdoczLp1SoQU0R3dxz1RpIK+4YNQbCVOA==} dev: true - /y18n/4.0.3: - resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - dev: true - /y18n/5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -21908,36 +21395,11 @@ packages: glob: 7.2.3 dev: false - /yargs-parser/18.1.3: - resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} - engines: {node: '>=6'} - dependencies: - camelcase: 5.3.1 - decamelize: 1.2.0 - dev: true - /yargs-parser/20.2.9: resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} engines: {node: '>=10'} dev: true - /yargs/15.4.1: - resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} - engines: {node: '>=8'} - dependencies: - cliui: 6.0.0 - decamelize: 1.2.0 - find-up: 4.1.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - require-main-filename: 2.0.0 - set-blocking: 2.0.0 - string-width: 4.2.3 - which-module: 2.0.0 - y18n: 4.0.3 - yargs-parser: 18.1.3 - dev: true - /yargs/16.2.0: resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} engines: {node: '>=10'} @@ -21951,19 +21413,6 @@ packages: yargs-parser: 20.2.9 dev: true - /yauzl/2.10.0: - resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} - dependencies: - buffer-crc32: 0.2.13 - fd-slicer: 1.1.0 - dev: true - - /yazl/2.5.1: - resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==} - dependencies: - buffer-crc32: 0.2.13 - dev: true - /yn/3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} diff --git a/src/api/sso/env.local b/src/api/sso/env.local index 7d76343f95..ba0c17e228 100644 --- a/src/api/sso/env.local +++ b/src/api/sso/env.local @@ -7,6 +7,12 @@ LOG_LEVEL=debug SSO_PORT=7777 +# SSO Service URL +SSO_URL=http://localhost/v1/auth + +# Feed Discovery Service URL +FEED_DISCOVERY_URL=http://localhost/v1/feed-discovery + # The Single Sign On (SSO) login service URL SSO_LOGIN_URL=http://localhost:8081/simplesaml/saml2/idp/SSOService.php @@ -43,7 +49,15 @@ JWT_AUDIENCE=http://localhost # How long should a JWT work before it expires JWT_EXPIRES_IN=1h +# Signing key for JWTs +JWT_SECRET=your-super-secret-jwt-token-with-at-least-32-characters-long + # Supabase connection https://supabase.com/docs/guides/database/connecting-to-postgres -SUPABASE_URL=http://kong:8000 +SUPABASE_URL=http://localhost/v1/supabase + +# Anonymous key +ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE + # Admin key, able to bypass security rules SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q + diff --git a/src/api/sso/jest-playwright.config.js b/src/api/sso/jest-playwright.config.js deleted file mode 100644 index 5c5ce13d26..0000000000 --- a/src/api/sso/jest-playwright.config.js +++ /dev/null @@ -1,2 +0,0 @@ -// Due to https://github.com/playwright-community/jest-playwright/issues/446 -// we put our jest-playwright config in the Telescope root, see ./jest-playwright.config.js diff --git a/src/api/sso/jest.config.e2e.js b/src/api/sso/jest.config.e2e.js deleted file mode 100644 index 7edce0a4d9..0000000000 --- a/src/api/sso/jest.config.e2e.js +++ /dev/null @@ -1,14 +0,0 @@ -const baseConfig = require('../../../jest.config.base'); - -module.exports = () => ({ - ...baseConfig, - rootDir: '../../..', - testMatch: ['/src/api/sso/test/e2e/**/*.test.js'], - collectCoverageFrom: ['/src/api/sso/src/**/*.js'], - // We use jest-playwright to do browser tests, https://github.com/playwright-community/jest-playwright - // See the jest-playwright config in the Telescope root ./jest-playwright.config.js - preset: 'jest-playwright-preset', - // Try reducing the number of tests that can run at once down to 1 - maxConcurrency: 1, - maxWorkers: 1, -}); diff --git a/src/api/sso/package.json b/src/api/sso/package.json index 31fbbf4b2a..9226e66d30 100644 --- a/src/api/sso/package.json +++ b/src/api/sso/package.json @@ -12,7 +12,9 @@ "lint": "pnpm eslint", "lint-time": "pnpm eslint-time", "test": "jest -c jest.config.js", - "clean": "pnpm rimraf .turbo node_modules || pnpm rimraf node_modules" + "clean": "pnpm rimraf .turbo node_modules || pnpm rimraf node_modules", + "e2e": "pnpm playwright", + "playwright": "env-cmd -f env.local playwright test --" }, "repository": "Seneca-CDOT/telescope", "license": "BSD-2-Clause", @@ -30,18 +32,20 @@ "jsonwebtoken": "9.0.0", "minimatch": "3.0.5", "normalize-url": "6.1.0", - "passport": "0.5.2", + "passport": "0.6.0", "passport-saml": "3.2.4" }, "engines": { "node": ">=16" }, "devDependencies": { + "@playwright/test": "1.29.2", "@senecacdot/eslint-config-telescope": "1.1.0", "env-cmd": "10.1.0", "eslint": "7.32.0", "nodemon": "2.0.20", + "playwright": "1.29.2", "rimraf": "3.0.2", - "supertest": "6.1.6" + "supertest": "6.3.2" } } diff --git a/src/api/sso/playwright.config.js b/src/api/sso/playwright.config.js new file mode 100644 index 0000000000..82ad79728a --- /dev/null +++ b/src/api/sso/playwright.config.js @@ -0,0 +1,33 @@ +/* eslint-disable import/no-extraneous-dependencies */ +const { devices } = require('@playwright/test'); + +/** @type {import('@playwright/test').PlaywrightTestConfig} */ +const config = { + testDir: './test/e2e', + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + use: { + trace: 'on-first-retry', + video: 'on-first-retry', + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + ], + // Disable parallel tests, since they depend on DB state + workers: 1, + // 'github' for GitHub Actions CI to generate annotations + reporter: process.env.CI ? 'github' : 'list', +}; + +module.exports = config; diff --git a/src/api/sso/test/e2e/auth-flows.test.js b/src/api/sso/test/e2e/auth-flows.test.js index 49b999114a..4a5df93c70 100644 --- a/src/api/sso/test/e2e/auth-flows.test.js +++ b/src/api/sso/test/e2e/auth-flows.test.js @@ -1,11 +1,13 @@ +const { test, expect } = require('@playwright/test'); + // NOTE: you need to run the sso and login services in docker for these to work const { hash } = require('@senecacdot/satellite'); // We need to get the URL to the sso service running in docker, and the list // of allowed origins, to compare with assumptions in the tests below. const { SSO_URL, ALLOWED_APP_ORIGINS } = process.env; -const { login, logout, getTokenAndState } = require('./browser-util'); -const { createTelescopeUsers, cleanupTelescopeUsers, ensureUsers } = require('./supabase-util'); +const { login, logout, getTokenAndState } = require('./lib/browser-util'); +const { createTelescopeUsers, cleanupTelescopeUsers, ensureUsers } = require('./lib/supabase-util'); // We have 3 SSO user accounts in the login service (see config/simplesamlphp-users.php): // @@ -52,47 +54,40 @@ const galileoGalilei = { // Create 2 Telescope accounts, one for user1@example.com and one for hans-lippershey@example.com. const users = [johannesKepler, hansLippershey]; -describe('Authentication Flows', () => { - beforeEach(async () => { +test.describe('Authentication Flows', () => { + test.beforeEach(async ({ page }) => { await createTelescopeUsers(users); - - context = await browser.newContext(); - page = await browser.newPage(); - await page.goto(`http://localhost:8888/auth.html`); + return page.goto(`http://localhost:8888/auth.html`); }); - afterEach(async () => { - await cleanupTelescopeUsers(users); - await context.close(); - await page.close(); - }); + test.afterEach(() => cleanupTelescopeUsers(users)); - it('should use the same origin in .env for ALLOWED_APP_ORIGINS that test cases use', () => { + test('should use the same origin in .env for ALLOWED_APP_ORIGINS that test cases use', () => { const origins = ALLOWED_APP_ORIGINS.split(' '); expect(origins).toContain('http://localhost:8888'); }); - it('should use the same SSO_URL as we have hard-coded in the test HTML', () => { + test('should use the same SSO_URL as we have hard-coded in the test HTML', () => { expect(SSO_URL).toEqual('http://localhost/v1/auth'); }); - it('should have all expected Telescope users in Users service for test data accounts', () => + test('should have all expected Telescope users in Users service for test data accounts', () => ensureUsers(users)); - it('Login flow preserves state param', async () => { + test('Login flow preserves state param', async ({ page }) => { const { state } = await login(page, 'user1', 'user1pass'); // Expect the state to match what we sent originally (see index.html ) expect(state).toEqual('abc123'); }); - it('Login flow issues JWT access token with with expected sub claim', async () => { + test('Login flow issues JWT access token with with expected sub claim', async ({ page }) => { const { jwt } = await login(page, 'user1', 'user1pass'); // The sub claim should match our user's email expect(typeof jwt === 'object').toBe(true); expect(jwt.sub).toEqual(hash(johannesKepler.email)); }); - it('Admin user can login, and has expected token payload', async () => { + test('Admin user can login, and has expected token payload', async ({ page }) => { const { jwt } = await login(page, 'user1', 'user1pass'); expect(jwt.sub).toEqual(hash(johannesKepler.email)); expect(jwt.email).toEqual(johannesKepler.email); @@ -105,7 +100,7 @@ describe('Authentication Flows', () => { expect(jwt.picture).toEqual(johannesKepler.githubAvatarUrl); }); - it('Telescope user can login, and has expected token payload', async () => { + test('Telescope user can login, and has expected token payload', async ({ page }) => { const { jwt } = await login(page, 'lippersheyh', 'telescope'); expect(jwt.sub).toEqual(hash(hansLippershey.email)); expect(jwt.email).toEqual(hansLippershey.email); @@ -118,7 +113,7 @@ describe('Authentication Flows', () => { expect(jwt.picture).toEqual(hansLippershey.githubAvatarUrl); }); - it('Seneca user can login, and has expected token payload', async () => { + test('Seneca user can login, and has expected token payload', async ({ page }) => { const { jwt } = await login(page, 'user2', 'user2pass'); expect(jwt.sub).toEqual(hash(galileoGalilei.email)); expect(jwt.email).toEqual(galileoGalilei.email); @@ -131,7 +126,7 @@ describe('Authentication Flows', () => { expect(jwt.picture).toBe(undefined); }); - it("Logging in twice doesn't require username and password again", async () => { + test("Logging in twice doesn't require username and password again", async ({ page }) => { const firstLogin = await login(page, 'user1', 'user1pass'); expect(firstLogin.jwt.sub).toEqual(hash(johannesKepler.email)); @@ -149,8 +144,8 @@ describe('Authentication Flows', () => { expect(secondLogin.jwt.sub).toEqual(firstLogin.jwt.sub); }); - describe('Logout', () => { - it('Logout works after logging in', async () => { + test.describe('Logout', () => { + test('Logout works after logging in', async ({ page }) => { const firstLogin = await login(page, 'user1', 'user1pass'); expect(firstLogin.jwt.sub).toEqual(hash(johannesKepler.email)); @@ -160,7 +155,7 @@ describe('Authentication Flows', () => { expect(logoutResult.token).toEqual(undefined); }); - it('Logging in works after logout', async () => { + test('Logging in works after logout', async ({ page }) => { const firstLogin = await login(page, 'user1', 'user1pass'); expect(firstLogin.jwt.sub).toEqual(hash(johannesKepler.email)); diff --git a/src/api/sso/test/e2e/browser-util.js b/src/api/sso/test/e2e/lib/browser-util.js similarity index 100% rename from src/api/sso/test/e2e/browser-util.js rename to src/api/sso/test/e2e/lib/browser-util.js diff --git a/src/api/sso/test/e2e/supabase-util.js b/src/api/sso/test/e2e/lib/supabase-util.js similarity index 98% rename from src/api/sso/test/e2e/supabase-util.js rename to src/api/sso/test/e2e/lib/supabase-util.js index bf31431318..61f095b215 100644 --- a/src/api/sso/test/e2e/supabase-util.js +++ b/src/api/sso/test/e2e/lib/supabase-util.js @@ -1,3 +1,4 @@ +const { expect } = require('@playwright/test'); const { createClient } = require('@supabase/supabase-js'); const { hash } = require('@senecacdot/satellite'); const normalizeUrl = require('normalize-url'); diff --git a/src/api/sso/test/e2e/routes.test.js b/src/api/sso/test/e2e/routes.test.js index 529b0a9c8d..768afe3576 100644 --- a/src/api/sso/test/e2e/routes.test.js +++ b/src/api/sso/test/e2e/routes.test.js @@ -1,53 +1,43 @@ +const { test, expect } = require('@playwright/test'); + // NOTE: you need to run the sso and login services in docker for these to work const request = require('supertest'); const { app } = require('../../src'); -it('should use the same origin in .env for ALLOWED_APP_ORIGINS that test cases use', () => { +test('should use the same origin in .env for ALLOWED_APP_ORIGINS that test cases use', () => { const origins = process.env.ALLOWED_APP_ORIGINS.split(' '); expect(origins).toContain('http://localhost:8888'); }); -describe('/login', () => { - it('should respond with 400 to non-URI in redirect_uri param', (done) => { - request(app).get('/login').expect(400, done); - }); +test.describe('/login', () => { + test('should respond with 400 to non-URI in redirect_uri param', () => + request(app).get('/login').expect(400)); - it('should respond with 401 to unknown URI in redirect_uri param', (done) => { - request(app).get('/login?redirect_uri=http://unknown.com').expect(401, done); - }); + test('should respond with 401 to unknown URI in redirect_uri param', () => + request(app).get('/login?redirect_uri=http://unknown.com').expect(401)); - it('should respond with 302 to known app URI in redirect_uri param', (done) => { - request(app).get('/login?redirect_uri=http://localhost:8888').expect(302, done); - }); + test('should respond with 302 to known app URI in redirect_uri param', () => + request(app).get('/login?redirect_uri=http://localhost:8888').expect(302)); - it('should respond with 302 to known app URI in redirect_uri param with state', (done) => { - request(app).get('/login?redirect_uri=http://localhost:8888&state=abc123').expect(302, done); - }); + test('should respond with 302 to known app URI in redirect_uri param with state', () => + request(app).get('/login?redirect_uri=http://localhost:8888&state=abc123').expect(302)); - it('should respond with 302 to POST login callback without proper flow', (done) => { - request(app).post('/login/callback').expect(302, done); - }); + test('should respond with 302 to POST login callback without proper flow', () => + request(app).post('/login/callback').expect(302)); }); -describe('/logout', () => { - it('should respond with 400 to logout request without token', (done) => { - request(app).get('/logout').expect(400, done); - }); +test.describe('/logout', () => { + test('should respond with 400 to logout request without token', () => + request(app).get('/logout').expect(400)); - it('should respond with 400 to GET logout callback without proper flow', (done) => { - request(app).get('/logout/callback').expect(400, done); - }); + test('should respond with 400 to GET logout callback without proper flow', () => + request(app).get('/logout/callback').expect(400)); - it('should respond with 400 to POST logout callback without proper flow', (done) => { - request(app).post('/logout/callback').expect(400, done); - }); + test('should respond with 400 to POST logout callback without proper flow', () => + request(app).post('/logout/callback').expect(400)); }); -describe('/sp', () => { - it('should respond with XML', (done) => { - request(app) - .get('/sp') - .expect('Content-Type', 'application/xml; charset=utf-8') - .expect(200, done); - }); +test.describe('/sp', () => { + test('should respond with XML', () => + request(app).get('/sp').expect('Content-Type', 'application/xml; charset=utf-8').expect(200)); }); diff --git a/src/api/sso/test/e2e/row-level-policies.test.js b/src/api/sso/test/e2e/row-level-policies.test.js index 0c58a7e327..2d9cbff54f 100644 --- a/src/api/sso/test/e2e/row-level-policies.test.js +++ b/src/api/sso/test/e2e/row-level-policies.test.js @@ -1,14 +1,17 @@ +const { test, expect } = require('@playwright/test'); + const { hash } = require('@senecacdot/satellite'); const { createClient } = require('@supabase/supabase-js'); const normalizeUrl = require('normalize-url'); const { SUPABASE_URL, ANON_KEY } = process.env; + const { createTelescopeUsers, cleanupTelescopeUsers, addFeeds, cleanFeeds, -} = require('./supabase-util'); +} = require('./lib/supabase-util'); const { createToken } = require('../../src/token'); const createSupabaseClient = () => createClient(SUPABASE_URL, ANON_KEY); @@ -70,15 +73,15 @@ const feedList = [ }, ]; -describe('Test Row Level Security Policies', () => { - describe('Unauthenticated users with public anon_key', () => { +test.describe('Test Row Level Security Policies', () => { + test.describe('Unauthenticated users with public anon_key', () => { const supabase = createSupabaseClient(); - describe('"telescope_profiles" security policies', () => { - beforeEach(() => createTelescopeUsers(users)); + test.describe('"telescope_profiles" security policies', () => { + test.beforeEach(() => createTelescopeUsers(users)); - afterEach(() => cleanupTelescopeUsers(users)); + test.afterEach(() => cleanupTelescopeUsers(users)); - it('should return no users', async () => { + test('should return no users', async () => { const { status, count } = await supabase .from('telescope_profiles') .select('*', { count: 'exact' }); @@ -88,7 +91,7 @@ describe('Test Row Level Security Policies', () => { expect(count).toBe(0); }); - it('should not allow creating new users', async () => { + test('should not allow creating new users', async () => { const { status } = await supabase.from('telescope_profiles').insert( { id: hash(unregisteredUser.email), @@ -106,7 +109,7 @@ describe('Test Row Level Security Policies', () => { expect(status).toBe(403); }); - it('should not allow updating users', async () => { + test('should not allow updating users', async () => { const { status } = await supabase .from('telescope_profiles') .update({ display_name: 'my name' }) @@ -116,7 +119,7 @@ describe('Test Row Level Security Policies', () => { expect(status).toBe(404); }); - it('should not allow deleting users', async () => { + test('should not allow deleting users', async () => { const { status, count } = await supabase .from('telescope_profiles') .delete({ count: 'exact' }) @@ -130,26 +133,33 @@ describe('Test Row Level Security Policies', () => { }); }); - describe('"feeds" security policies', () => { + test.describe('"feeds" security policies', () => { // Create feeds for HansLippershey and an unregistered user - beforeEach(async () => { + test.beforeEach(async () => { await createTelescopeUsers([telescopeUser1]); await addFeeds(feedList); }); - afterEach(async () => { + test.afterEach(async () => { await cleanFeeds(feedList); await cleanupTelescopeUsers([telescopeUser1]); }); - it('should allow reading the feeds list', async () => { - const { status, count } = await supabase.from('feeds').select('url', { count: 'exact' }); - + test('should allow reading the feeds list', async () => { + const { status, data } = await supabase.from('feeds').select(); expect(status).toBe(200); - expect(count).toBe(feedList.length); + expect(data).toEqual( + expect.arrayContaining( + feedList.map((feed) => + expect.objectContaining({ + url: feed.url, + }) + ) + ) + ); }); - it('should not allow adding new feeds', async () => { + test('should not allow adding new feeds', async () => { const { status } = await supabase.from('feeds').insert( { url: 'http://dev.to/devto', @@ -163,7 +173,7 @@ describe('Test Row Level Security Policies', () => { expect(status).toBe(403); }); - it('should not allow updating feeds', async () => { + test('should not allow updating feeds', async () => { const { status } = await supabase .from('feeds') .update({ html_url: 'http://dev.to/' }, { returning: 'minimal' }) @@ -172,7 +182,7 @@ describe('Test Row Level Security Policies', () => { expect(status).toBe(404); }); - it('should not allow deleting feeds', async () => { + test('should not allow deleting feeds', async () => { const { status, count } = await supabase.from('feeds').delete({ count: 'exact' }).match({ url: feedList[0].url, }); @@ -184,7 +194,7 @@ describe('Test Row Level Security Policies', () => { }); }); - describe('Authenticated users through Seneca SSO', () => { + test.describe('Authenticated users through Seneca SSO', () => { const { email, firstName, lastName, displayName, githubAvatarUrl } = telescopeUser1; const accessToken = createToken( email, @@ -198,12 +208,12 @@ describe('Test Row Level Security Policies', () => { // Override the JWT on the public client supabase.auth.setAuth(accessToken); - describe('"telescope_profiles" security policies', () => { - beforeEach(() => createTelescopeUsers(users)); + test.describe('"telescope_profiles" security policies', () => { + test.beforeEach(() => createTelescopeUsers(users)); - afterEach(() => cleanupTelescopeUsers(users)); + test.afterEach(() => cleanupTelescopeUsers(users)); - it('should return all users', async () => { + test('should return all users', async () => { const { status, count } = await supabase .from('telescope_profiles') .select('id', { count: 'exact' }); @@ -212,7 +222,7 @@ describe('Test Row Level Security Policies', () => { expect(count).toBe(users.length); }); - it('should not allow creating new users', async () => { + test('should not allow creating new users', async () => { const { status } = await supabase.from('telescope_profiles').insert( { id: hash(unregisteredUser.email), @@ -229,7 +239,7 @@ describe('Test Row Level Security Policies', () => { expect(status).toBe(401); }); - it('should allow users to update their own profiles', async () => { + test('should allow users to update their own profiles', async () => { const { status, data: profiles } = await supabase .from('telescope_profiles') .update({ display_name: 'my name' }, { returning: 'representation' }) @@ -240,7 +250,7 @@ describe('Test Row Level Security Policies', () => { expect(profiles[0].display_name).toBe('my name'); }); - it("should not allow users to update others' profiles", async () => { + test("should not allow users to update others' profiles", async () => { const { status } = await supabase .from('telescope_profiles') .update({ display_name: 'my name' }) @@ -249,7 +259,7 @@ describe('Test Row Level Security Policies', () => { expect(status).toBe(404); }); - it('should not allow deleting users', async () => { + test('should not allow deleting users', async () => { const { status, count } = await supabase .from('telescope_profiles') .delete({ count: 'exact' }) @@ -262,26 +272,34 @@ describe('Test Row Level Security Policies', () => { }); }); - describe('"feeds" security policies', () => { + test.describe('"feeds" security policies', () => { // Create feeds for HansLippershey and an unregistered user - beforeEach(async () => { + test.beforeEach(async () => { await createTelescopeUsers([telescopeUser1]); await addFeeds(feedList); }); - afterEach(async () => { + test.afterEach(async () => { await cleanFeeds(feedList); await cleanupTelescopeUsers([telescopeUser1]); }); - it('should allow reading the feeds list', async () => { - const { status, count } = await supabase.from('feeds').select('url', { count: 'exact' }); + test('should allow reading the feeds list', async () => { + const { status, data } = await supabase.from('feeds').select(); expect(status).toBe(200); - expect(count).toBe(feedList.length); + expect(data).toEqual( + expect.arrayContaining( + feedList.map((feed) => + expect.objectContaining({ + url: feed.url, + }) + ) + ) + ); }); - it('should allow users to add feeds linked to their account', async () => { + test('should allow users to add feeds linked to their account', async () => { const { status, data: feeds } = await supabase.from('feeds').insert( { url: 'http://dev.to/devto', @@ -296,7 +314,7 @@ describe('Test Row Level Security Policies', () => { expect(feeds[0].url).toBe('http://dev.to/devto'); }); - it('should not allow users to add feeds not linked to their account', async () => { + test('should not allow users to add feeds not linked to their account', async () => { const { status } = await supabase.from('feeds').insert( { url: 'http://dev.to/devto', @@ -310,7 +328,7 @@ describe('Test Row Level Security Policies', () => { expect(status).toBe(401); }); - it('should allow user to update their own feeds', async () => { + test('should allow user to update their own feeds', async () => { const { status, data: feeds } = await supabase .from('feeds') .update({ type: 'youtube' }, { returning: 'representation' }) @@ -321,7 +339,7 @@ describe('Test Row Level Security Policies', () => { expect(feeds[0].type).toBe('youtube'); }); - it("should not allow users to update others' feeds", async () => { + test("should not allow users to update others' feeds", async () => { const { status } = await supabase .from('feeds') .update({ type: 'youtube' }) @@ -330,7 +348,7 @@ describe('Test Row Level Security Policies', () => { expect(status).toBe(404); }); - it('should allow users to delete their own feeds', async () => { + test('should allow users to delete their own feeds', async () => { const { status, count } = await supabase.from('feeds').delete({ count: 'exact' }).match({ url: telescopeUser1.feeds[0], }); @@ -339,7 +357,7 @@ describe('Test Row Level Security Policies', () => { expect(count).toBe(1); }); - it("should not allow users to delete others' feeds", async () => { + test("should not allow users to delete others' feeds", async () => { const { status, count } = await supabase .from('feeds') .delete({ count: 'exact' }) diff --git a/src/api/sso/test/e2e/signup-flow.test.js b/src/api/sso/test/e2e/signup-flow.test.js index 9f08031aea..f1de3dd560 100644 --- a/src/api/sso/test/e2e/signup-flow.test.js +++ b/src/api/sso/test/e2e/signup-flow.test.js @@ -1,11 +1,13 @@ +const { test, expect } = require('@playwright/test'); + // NOTE: you need to run the sso and login services in docker for these to work const { hash, fetch } = require('@senecacdot/satellite'); const { decode } = require('jsonwebtoken'); // We need to get the URL to the sso service running in docker, and the list // of allowed origins, to compare with assumptions in the tests below. -const { login, logout } = require('./browser-util'); -const { cleanupTelescopeUsers, ensureUsers } = require('./supabase-util'); +const { login, logout } = require('./lib/browser-util'); +const { cleanupTelescopeUsers, ensureUsers } = require('./lib/supabase-util'); const { SSO_URL, FEED_DISCOVERY_URL } = process.env; @@ -43,27 +45,18 @@ const galileoGalilei = { const users = [galileoGalilei, johannesKepler]; -describe('Signup Flow', () => { - afterAll(async () => { - await browser.close(); - await cleanupTelescopeUsers(users); - }); +test.describe('Signup Flow', () => { + test.afterAll(() => cleanupTelescopeUsers(users)); - beforeEach(async () => { + test.beforeEach(async ({ page }) => { await cleanupTelescopeUsers(users); - context = await browser.newContext(); - page = await browser.newPage(); - await page.goto(`http://localhost:8888/auth.html`); - }); - afterEach(async () => { - await context.close(); - await page.close(); + return page.goto(`http://localhost:8888/auth.html`); }); - it('should have none of the users in the Users service for test data accounts', () => + test('should have none of the users in the Users service for test data accounts', () => ensureUsers(users, false)); - it('signup flow works to login and register a new Telescope user', async () => { + test('signup flow works to login and register a new Telescope user', async ({ page }) => { // Part 1: login using SSO, as a user who does not have a Telescope account. // Confirm that the payload of the token we get back matches what we expect. // NOTE: the data comes from config/simplesamlphp-users.php. @@ -141,7 +134,7 @@ describe('Signup Flow', () => { await partThree(feedUrls, accessToken); }); - it('signup flow fails if user is not authenticated', async () => { + test('signup flow fails if user is not authenticated', async () => { const invalidUser = { ...galileoGalilei, email: 'wrong@email.com' }; const res = await fetch(`${SSO_URL}/register`, { method: 'POST', @@ -153,7 +146,7 @@ describe('Signup Flow', () => { expect(res.status).toBe(401); }); - it('signup flow fails if user data is missing required properties', async () => { + test('signup flow fails if user data is missing required properties', async ({ page }) => { const { accessToken } = await login(page, 'user2', 'user2pass'); const invalidUser = { ...galileoGalilei }; // Delete the firstName, which is required @@ -169,7 +162,7 @@ describe('Signup Flow', () => { expect(res.status).toBe(400); }); - it('signup flow fails if user is already a Telescope user', async () => { + test('signup flow fails if user is already a Telescope user', async ({ page }) => { const { accessToken } = await login(page, 'user2', 'user2pass'); const res = await fetch(`${SSO_URL}/register`, { method: 'POST', @@ -193,7 +186,7 @@ describe('Signup Flow', () => { expect(res2.status).toBe(403); }); - it('Signup flow fails if feed is already used by another Telescope user', async () => { + test('Signup flow fails if feed is already used by another Telescope user', async ({ page }) => { // create the user1(johannes) account. const account1 = await login(page, 'user1', 'user1pass'); const res = await fetch(`${SSO_URL}/register`, { diff --git a/src/api/sso/test/e2e/super-user.test.js b/src/api/sso/test/e2e/super-user.test.js index 23614c57ae..3511de990e 100644 --- a/src/api/sso/test/e2e/super-user.test.js +++ b/src/api/sso/test/e2e/super-user.test.js @@ -1,8 +1,10 @@ +const { test, expect } = require('@playwright/test'); + // NOTE: you need to run the sso and login services in docker for these to work const { hash } = require('@senecacdot/satellite'); -const { login } = require('./browser-util'); -const { createTelescopeUsers, cleanupTelescopeUsers, ensureUsers } = require('./supabase-util'); +const { login } = require('./lib/browser-util'); +const { createTelescopeUsers, cleanupTelescopeUsers, ensureUsers } = require('./lib/supabase-util'); // We have 3 SSO user accounts in the login service (see config/simplesamlphp-users.php): // @@ -12,20 +14,11 @@ const { createTelescopeUsers, cleanupTelescopeUsers, ensureUsers } = require('./ // | user2 | user2@example.com | user2pass | Galileo Galilei | // | lippersheyh | hans-lippershey@example.com | telescope | Hans Lippershey | -describe('Super User Authentication', () => { - describe('Seneca Super User', () => { - beforeEach(async () => { - context = await browser.newContext(); - page = await browser.newPage(); - await page.goto(`http://localhost:8888/auth.html`); - }); - - afterEach(async () => { - await context.close(); - await page.close(); - }); +test.describe('Super User Authentication', () => { + test.describe('Seneca Super User', () => { + test.beforeEach(({ page }) => page.goto(`http://localhost:8888/auth.html`)); - it('Super user can login, and has expected token payload', async () => { + test('Super user can login, and has expected token payload', async ({ page }) => { const email = 'user1@example.com'; const { jwt } = await login(page, 'user1', 'user1pass'); expect(jwt.sub).toEqual(hash(email)); @@ -37,7 +30,7 @@ describe('Super User Authentication', () => { }); }); - describe('Telescope Admin User', () => { + test.describe('Telescope Admin User', () => { const johannesKepler = { firstName: 'Johannes', lastName: 'Kepler', @@ -53,24 +46,17 @@ describe('Super User Authentication', () => { }; const users = [johannesKepler]; - beforeEach(async () => { + test.beforeEach(async ({ page }) => { await createTelescopeUsers(users); - - context = await browser.newContext(); - page = await browser.newPage(); - await page.goto(`http://localhost:8888/auth.html`); + return page.goto(`http://localhost:8888/auth.html`); }); - afterEach(async () => { - await cleanupTelescopeUsers(users); - await context.close(); - await page.close(); - }); + test.afterEach(() => cleanupTelescopeUsers(users)); - it('should have all expected Telescope users in Users service for test data accounts', () => + test('should have all expected Telescope users in Users service for test data accounts', () => ensureUsers(users)); - it('Super user can login, and has expected token payload', async () => { + test('Super user can login, and has expected token payload', async ({ page }) => { const { jwt } = await login(page, 'user1', 'user1pass'); expect(jwt.sub).toEqual(hash(johannesKepler.email)); expect(jwt.email).toEqual(johannesKepler.email); @@ -81,7 +67,7 @@ describe('Super User Authentication', () => { }); }); - describe('Telescope Non-Admin, Super User', () => { + test.describe('Telescope Non-Admin, Super User', () => { const johannesKepler = { firstName: 'Johannes', lastName: 'Kepler', @@ -98,24 +84,17 @@ describe('Super User Authentication', () => { }; const users = [johannesKepler]; - beforeEach(async () => { + test.beforeEach(async ({ page }) => { await createTelescopeUsers(users); - - context = await browser.newContext(); - page = await browser.newPage(); - await page.goto(`http://localhost:8888/auth.html`); + return page.goto(`http://localhost:8888/auth.html`); }); - afterEach(async () => { - await cleanupTelescopeUsers(users); - await context.close(); - await page.close(); - }); + test.afterEach(() => cleanupTelescopeUsers(users)); - it('should have all expected Telescope users in Users service for test data accounts', () => + test('should have all expected Telescope users in Users service for test data accounts', () => ensureUsers(users)); - it('Super user can login, and has expected token payload', async () => { + test('Super user can login, and has expected token payload', async ({ page }) => { const { jwt } = await login(page, 'user1', 'user1pass'); expect(jwt.sub).toEqual(hash(johannesKepler.email)); expect(jwt.email).toEqual(johannesKepler.email); diff --git a/turbo.json b/turbo.json index ea1928dd47..6c9b8fdb31 100644 --- a/turbo.json +++ b/turbo.json @@ -23,6 +23,9 @@ "test": { "outputs": [] }, + "e2e": { + "outputs": [] + }, "lint": { "outputs": [] },