From b6f718d4a28e8c3e1ec3b72dc2d046f4ba6120ef Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 29 Aug 2022 11:19:57 +0530 Subject: [PATCH 01/20] Install cypress as dev dependency --- package.json | 1 + yarn.lock | 913 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 906 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 2143ebd0..f7fb040f 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "aes-js": "^3.1.2", "bs58": "^4.0.1", "core-js": "^3.6.5", + "cypress": "^10.6.0", "es6-promise": "https://github.com/bwindels/es6-promise.git#bwindels/expose-flush", "escodegen": "^2.0.0", "eslint": "^7.32.0", diff --git a/yarn.lock b/yarn.lock index c48d2719..994657f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23,6 +23,43 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + +"@cypress/request@^2.88.10": + version "2.88.10" + resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.10.tgz#b66d76b07f860d3a4b8d7a0604d020c662752cce" + integrity sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + http-signature "~1.3.6" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^8.3.2" + +"@cypress/xvfb@^1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.4.tgz#2daf42e8275b39f4aa53c14214e557bd14e7748a" + integrity sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q== + dependencies: + debug "^3.1.0" + lodash.once "^4.1.1" + "@eslint/eslintrc@^0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" @@ -87,6 +124,33 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== +"@types/node@*": + version "18.7.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.13.tgz#23e6c5168333480d454243378b69e861ab5c011a" + integrity sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw== + +"@types/node@^14.14.31": + version "14.18.26" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.26.tgz#239e19f8b4ea1a9eb710528061c1d733dc561996" + integrity sha512-0b+utRBSYj8L7XAp0d+DX7lI4cSmowNaaTkk6/1SKzbKkG+doLuPusB9EOvzLJ8ahJSk03bTLIL6cWaEd4dBKA== + +"@types/sinonjs__fake-timers@8.1.1": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3" + integrity sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g== + +"@types/sizzle@^2.3.2": + version "2.3.3" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef" + integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ== + +"@types/yauzl@^2.9.1": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599" + integrity sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw== + dependencies: + "@types/node" "*" + "@typescript-eslint/eslint-plugin@^4.29.2": version "4.29.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.2.tgz#f54dc0a32b8f61c6024ab8755da05363b733838d" @@ -181,6 +245,14 @@ aes-js@^3.1.2: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + ajv@^6.10.0, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -211,11 +283,23 @@ ansi-colors@^4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-regex@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -230,6 +314,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +arch@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" + integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -242,11 +331,48 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +async@^3.2.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" + integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== + +aws4@^1.8.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -269,6 +395,28 @@ base64-arraybuffer@^0.2.0: resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz#4b944fac0191aa5907afe2d8c999ccc57ce80f45" integrity sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ== +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + +blob-util@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" + integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ== + +bluebird@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -296,11 +444,34 @@ bs58@^4.0.1: dependencies: base-x "^3.0.2" +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== + +buffer@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +cachedir@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" + integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + chalk@^2.0.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -318,6 +489,53 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +check-more-types@^2.24.0: + version "2.24.0" + resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" + integrity sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA== + +ci-info@^3.2.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.2.tgz#6d2967ffa407466481c6c90b6e16b3098f080128" + integrity sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg== + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-table3@~0.6.1: + version "0.6.2" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.2.tgz#aaf5df9d8b5bf12634dc8b3040806a0c07120d2a" + integrity sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -342,11 +560,28 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colorette@^2.0.16: + version "2.0.19" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + colors@^1.3.3: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== + commander@^6.1.0: version "6.2.1" resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" @@ -357,6 +592,11 @@ commander@^7.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== +common-tags@^1.8.0: + version "1.8.2" + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6" + integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -372,7 +612,12 @@ core-js@^3.6.5: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.19.3.tgz#6df8142a996337503019ff3235a7022d7cdf4559" integrity sha512-LeLBMgEGSsG7giquSzvgBrTS7V5UL6ks3eQlUSbN8dJStlLFiRzUm5iqsRyzUB8carhfKjkJ2vzKqE6z1Vga9g== -cross-spawn@^7.0.2: +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== + +cross-spawn@^7.0.0, cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -417,6 +662,73 @@ cuint@^0.2.2: resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b" integrity sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs= +cypress@^10.6.0: + version "10.6.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-10.6.0.tgz#13f46867febf2c3715874ed5dce9c2e946b175fe" + integrity sha512-6sOpHjostp8gcLO34p6r/Ci342lBs8S5z9/eb3ZCQ22w2cIhMWGUoGKkosabPBfKcvRS9BE4UxybBtlIs8gTQA== + dependencies: + "@cypress/request" "^2.88.10" + "@cypress/xvfb" "^1.2.4" + "@types/node" "^14.14.31" + "@types/sinonjs__fake-timers" "8.1.1" + "@types/sizzle" "^2.3.2" + arch "^2.2.0" + blob-util "^2.0.2" + bluebird "^3.7.2" + buffer "^5.6.0" + cachedir "^2.3.0" + chalk "^4.1.0" + check-more-types "^2.24.0" + cli-cursor "^3.1.0" + cli-table3 "~0.6.1" + commander "^5.1.0" + common-tags "^1.8.0" + dayjs "^1.10.4" + debug "^4.3.2" + enquirer "^2.3.6" + eventemitter2 "^6.4.3" + execa "4.1.0" + executable "^4.1.1" + extract-zip "2.0.1" + figures "^3.2.0" + fs-extra "^9.1.0" + getos "^3.2.1" + is-ci "^3.0.0" + is-installed-globally "~0.4.0" + lazy-ass "^1.6.0" + listr2 "^3.8.3" + lodash "^4.17.21" + log-symbols "^4.0.0" + minimist "^1.2.6" + ospath "^1.2.2" + pretty-bytes "^5.6.0" + proxy-from-env "1.0.0" + request-progress "^3.0.0" + semver "^7.3.2" + supports-color "^8.1.1" + tmp "~0.2.1" + untildify "^4.0.0" + yauzl "^2.10.0" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== + dependencies: + assert-plus "^1.0.0" + +dayjs@^1.10.4: + version "1.11.5" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.5.tgz#00e8cc627f231f9499c19b38af49f56dc0ac5e93" + integrity sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA== + +debug@^3.1.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + debug@^4.0.1, debug@^4.1.1: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" @@ -431,6 +743,13 @@ debug@^4.3.1: dependencies: ms "2.1.2" +debug@^4.3.2: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + deep-is@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -441,6 +760,11 @@ deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -502,12 +826,27 @@ domutils@^2.6.0: domelementtype "^2.2.0" domhandler "^4.2.0" +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -enquirer@^2.3.5: +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enquirer@^2.3.5, enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -907,11 +1246,59 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -extend@^3.0.1: +eventemitter2@^6.4.3: + version "6.4.7" + resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.7.tgz#a7f6c4d7abf28a14c1ef3442f21cb306a054271d" + integrity sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg== + +execa@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + +executable@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" + integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg== + dependencies: + pify "^2.2.0" + +extend@^3.0.1, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== +extract-zip@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== + dependencies: + debug "^4.1.1" + get-stream "^5.1.0" + yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + fake-indexeddb@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/fake-indexeddb/-/fake-indexeddb-3.1.2.tgz#8073a12ed3b254f7afc064f3cc2629f0110a5303" @@ -953,6 +1340,20 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== + dependencies: + pend "~1.2.0" + +figures@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -980,6 +1381,30 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1000,6 +1425,27 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +get-stream@^5.0.0, get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +getos@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/getos/-/getos-3.2.1.tgz#0134d1f4e00eb46144c5a9c0ac4dc087cbb27dc5" + integrity sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q== + dependencies: + async "^3.2.0" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== + dependencies: + assert-plus "^1.0.0" + glob-parent@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -1019,6 +1465,13 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" +global-dirs@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" + integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA== + dependencies: + ini "2.0.0" + globals@^13.6.0: version "13.8.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.8.0.tgz#3e20f504810ce87a8d72e55aecf8435b50f4c1b3" @@ -1045,6 +1498,11 @@ globby@^11.0.3: merge2 "^1.3.0" slash "^3.0.0" +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -1067,6 +1525,25 @@ he@1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +http-signature@~1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.3.6.tgz#cb6fbfdf86d1c974f343be94e87f7fc128662cf9" + integrity sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw== + dependencies: + assert-plus "^1.0.0" + jsprim "^2.0.2" + sshpk "^1.14.1" + +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -1099,6 +1576,11 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -1112,6 +1594,18 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ini@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" + integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== + +is-ci@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867" + integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ== + dependencies: + ci-info "^3.2.0" + is-core-module@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" @@ -1136,21 +1630,54 @@ is-glob@^4.0.0, is-glob@^4.0.1: dependencies: is-extglob "^2.1.1" +is-installed-globally@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" + integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== + dependencies: + global-dirs "^3.0.0" + is-path-inside "^3.0.2" + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-path-inside@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-plain-obj@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -1164,6 +1691,11 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -1174,11 +1706,45 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsprim@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d" + integrity sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +lazy-ass@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" + integrity sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw== + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -1195,6 +1761,20 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +listr2@^3.8.3: + version "3.14.0" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e" + integrity sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g== + dependencies: + cli-truncate "^2.1.0" + colorette "^2.0.16" + log-update "^4.0.0" + p-map "^4.0.0" + rfdc "^1.3.0" + rxjs "^7.5.1" + through "^2.3.8" + wrap-ansi "^7.0.0" + lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" @@ -1205,16 +1785,39 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lodash.once@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== + lodash.truncate@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= -lodash@^4.7.0: +lodash@^4.17.21, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +log-symbols@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +log-update@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" + integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== + dependencies: + ansi-escapes "^4.3.0" + cli-cursor "^3.1.0" + slice-ansi "^4.0.0" + wrap-ansi "^6.2.0" + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -1239,6 +1842,11 @@ merge-options@^3.0.4: dependencies: is-plain-obj "^2.1.0" +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -1252,6 +1860,23 @@ micromatch@^4.0.4: braces "^3.0.1" picomatch "^2.2.3" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -1259,11 +1884,21 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" +minimist@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + nanoid@^3.3.3: version "3.3.4" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" @@ -1282,6 +1917,13 @@ node-html-parser@^4.0.0: css-select "^4.1.3" he "1.2.0" +npm-run-path@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + nth-check@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.0.tgz#1bb4f6dac70072fc313e8c9cd1417b5074c0a125" @@ -1296,13 +1938,20 @@ off-color@^2.0.0: dependencies: core-js "^3.6.5" -once@^1.3.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -1327,6 +1976,18 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +ospath@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" + integrity sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA== + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -1339,7 +2000,7 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-key@^3.1.0: +path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== @@ -1354,6 +2015,16 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -1364,6 +2035,11 @@ picomatch@^2.2.3: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== +pify@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + postcss-css-variables@^0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/postcss-css-variables/-/postcss-css-variables-0.18.0.tgz#d97b6da19e86245eb817006e11117382f997bb93" @@ -1402,16 +2078,44 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= +pretty-bytes@^5.6.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" + integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== + progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== +proxy-from-env@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" + integrity sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A== + +psl@^1.1.28: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -1437,6 +2141,13 @@ regexpp@^3.1.0: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== +request-progress@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe" + integrity sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg== + dependencies: + throttleit "^1.0.0" + require-from-string@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" @@ -1456,12 +2167,25 @@ resolve@^1.22.0: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^3.0.2: +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + +rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -1482,11 +2206,23 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-buffer@^5.0.1: +rxjs@^7.5.1: + version "7.5.6" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.6.tgz#0446577557862afd6903517ce7cae79ecb9662bc" + integrity sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw== + dependencies: + tslib "^2.1.0" + +safe-buffer@^5.0.1, safe-buffer@^5.1.2: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + semver@^7.2.1, semver@^7.3.5: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" @@ -1494,6 +2230,13 @@ semver@^7.2.1, semver@^7.3.5: dependencies: lru-cache "^6.0.0" +semver@^7.3.2: + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== + dependencies: + lru-cache "^6.0.0" + setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -1511,11 +2254,25 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" + integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" @@ -1540,11 +2297,35 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +sshpk@^1.14.1: + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + stable@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== +string-width@^4.1.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^4.2.0: version "4.2.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" @@ -1561,6 +2342,18 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -1580,6 +2373,13 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" @@ -1620,6 +2420,23 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= +throttleit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" + integrity sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g== + +through@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + +tmp@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -1627,6 +2444,14 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + tr46@^2.0.2: version "2.1.0" resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" @@ -1639,6 +2464,11 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -1646,6 +2476,18 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -1665,6 +2507,11 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + typescript@^4.7.0: version "4.7.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" @@ -1689,6 +2536,16 @@ typeson@^6.0.0: resolved "https://registry.yarnpkg.com/typeson/-/typeson-6.1.0.tgz#5b2a53705a5f58ff4d6f82f965917cabd0d7448b" integrity sha512-6FTtyGr8ldU0pfbvW/eOZrEtEkczHRUtduBnA90Jh9kMPCiFNnXIon3vF41N0S4tV1HHQt4Hk1j4srpESziCaA== +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -1696,11 +2553,25 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + v8-compile-cache@^2.0.3: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + vite@^2.9.8: version "2.9.8" resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.8.tgz#2c2cb0790beb0fbe4b8c0995b80fe691a91c2545" @@ -1744,6 +2615,24 @@ word-wrap@^1.2.3, word-wrap@~1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -1760,3 +2649,11 @@ yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yauzl@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" From badfc84eb8abaf17de51c69ea832e77a2a1ef71a Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 29 Aug 2022 14:26:13 +0530 Subject: [PATCH 02/20] Write initial passing test --- cypress.config.ts | 8 ++++++++ cypress/e2e/startup.cy.ts | 22 ++++++++++++++++++++++ cypress/tsconfig.json | 8 ++++++++ package.json | 3 ++- 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 cypress.config.ts create mode 100644 cypress/e2e/startup.cy.ts create mode 100644 cypress/tsconfig.json diff --git a/cypress.config.ts b/cypress.config.ts new file mode 100644 index 00000000..fe5b673f --- /dev/null +++ b/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "cypress"; + +export default defineConfig({ + e2e: { + baseUrl: "http://localhost:3000", + supportFile: false, + }, +}); diff --git a/cypress/e2e/startup.cy.ts b/cypress/e2e/startup.cy.ts new file mode 100644 index 00000000..e7bf9c2c --- /dev/null +++ b/cypress/e2e/startup.cy.ts @@ -0,0 +1,22 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +describe("App has no startup errors that prevent UI render", () => { + it("passes", () => { + cy.visit("/"); + cy.contains("Log In"); + }) +}) diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json new file mode 100644 index 00000000..18edb199 --- /dev/null +++ b/cypress/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress", "node"] + }, + "include": ["**/*.ts"] +} diff --git a/package.json b/package.json index f7fb040f..fbba3b2e 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "start": "vite --port 3000", "build": "vite build && ./scripts/cleanup.sh", "build:sdk": "./scripts/sdk/build.sh", - "watch:sdk": "./scripts/sdk/build.sh && yarn run vite build -c vite.sdk-lib-config.js --watch" + "watch:sdk": "./scripts/sdk/build.sh && yarn run vite build -c vite.sdk-lib-config.js --watch", + "test:app": "vite --port 3000 & yarn run cypress open" }, "repository": { "type": "git", From 9f53962f552099ffa17583a779aa7a170b095abb Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 30 Aug 2022 11:39:39 +0530 Subject: [PATCH 03/20] Port plugin from eleweb + write test for login --- .gitignore | 1 + cypress.config.ts | 11 +- cypress/e2e/login.cy.ts | 39 ++++ cypress/plugins/docker/index.ts | 138 +++++++++++++ cypress/plugins/index.ts | 36 ++++ cypress/plugins/log.ts | 35 ++++ cypress/plugins/performance.ts | 47 +++++ cypress/plugins/synapsedocker/index.ts | 187 ++++++++++++++++++ .../synapsedocker/templates/COPYME/README.md | 3 + .../templates/COPYME/homeserver.yaml | 72 +++++++ .../synapsedocker/templates/COPYME/log.config | 50 +++++ .../synapsedocker/templates/consent/README.md | 1 + .../templates/consent/homeserver.yaml | 84 ++++++++ .../templates/consent/log.config | 50 +++++ .../consent/res/templates/privacy/en/1.0.html | 23 +++ .../res/templates/privacy/en/success.html | 9 + .../synapsedocker/templates/default/README.md | 1 + .../templates/default/homeserver.yaml | 76 +++++++ .../templates/default/log.config | 50 +++++ cypress/plugins/utils/port.ts | 27 +++ cypress/plugins/webserver.ts | 52 +++++ cypress/support/e2e.ts | 19 ++ cypress/support/synapse.ts | 122 ++++++++++++ cypress/tsconfig.json | 1 + 24 files changed, 1130 insertions(+), 4 deletions(-) create mode 100644 cypress/e2e/login.cy.ts create mode 100644 cypress/plugins/docker/index.ts create mode 100644 cypress/plugins/index.ts create mode 100644 cypress/plugins/log.ts create mode 100644 cypress/plugins/performance.ts create mode 100644 cypress/plugins/synapsedocker/index.ts create mode 100644 cypress/plugins/synapsedocker/templates/COPYME/README.md create mode 100644 cypress/plugins/synapsedocker/templates/COPYME/homeserver.yaml create mode 100644 cypress/plugins/synapsedocker/templates/COPYME/log.config create mode 100644 cypress/plugins/synapsedocker/templates/consent/README.md create mode 100644 cypress/plugins/synapsedocker/templates/consent/homeserver.yaml create mode 100644 cypress/plugins/synapsedocker/templates/consent/log.config create mode 100644 cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html create mode 100644 cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html create mode 100644 cypress/plugins/synapsedocker/templates/default/README.md create mode 100644 cypress/plugins/synapsedocker/templates/default/homeserver.yaml create mode 100644 cypress/plugins/synapsedocker/templates/default/log.config create mode 100644 cypress/plugins/utils/port.ts create mode 100644 cypress/plugins/webserver.ts create mode 100644 cypress/support/e2e.ts create mode 100644 cypress/support/synapse.ts diff --git a/.gitignore b/.gitignore index 78f9f348..b0714d24 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ lib *.tar.gz .eslintcache .tmp +cypress/videos diff --git a/cypress.config.ts b/cypress.config.ts index fe5b673f..6761d05d 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -1,8 +1,11 @@ import { defineConfig } from "cypress"; export default defineConfig({ - e2e: { - baseUrl: "http://localhost:3000", - supportFile: false, - }, + e2e: { + setupNodeEvents(on, config) { + require("./cypress/plugins/index.ts").default(on, config); + return config; + }, + baseUrl: "http://localhost:3000", + }, }); diff --git a/cypress/e2e/login.cy.ts b/cypress/e2e/login.cy.ts new file mode 100644 index 00000000..36badebf --- /dev/null +++ b/cypress/e2e/login.cy.ts @@ -0,0 +1,39 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +import type { SynapseInstance } from "../plugins/synapsedocker"; + +describe("Login", () => { + let synapse: SynapseInstance; + + beforeEach(() => { + cy.startSynapse("consent").then((data) => { + synapse = data; + }); + }); + + it("Login using username/password", () => { + const username = "foobaraccount"; + const password = "password123"; + cy.registerUser(synapse, username, password); + cy.visit("/"); + cy.get("#homeserver").clear().type(synapse.baseUrl); + cy.get("#username").clear().type(username); + cy.get("#password").clear().type(password); + cy.contains("Log In").click(); + cy.get(".SessionView"); + }); +}); + diff --git a/cypress/plugins/docker/index.ts b/cypress/plugins/docker/index.ts new file mode 100644 index 00000000..024cb9d4 --- /dev/null +++ b/cypress/plugins/docker/index.ts @@ -0,0 +1,138 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/// + +import * as os from "os"; +import * as childProcess from "child_process"; +import * as fse from "fs-extra"; + +import PluginEvents = Cypress.PluginEvents; +import PluginConfigOptions = Cypress.PluginConfigOptions; + +// A cypress plugin to run docker commands + +export function dockerRun(args: { + image: string; + containerName: string; + params?: string[]; +}): Promise { + const userInfo = os.userInfo(); + const params = args.params ?? []; + + if (userInfo.uid >= 0) { + // On *nix we run the docker container as our uid:gid otherwise cleaning it up its media_store can be difficult + params.push("-u", `${userInfo.uid}:${userInfo.gid}`); + } + + return new Promise((resolve, reject) => { + childProcess.execFile('docker', [ + "run", + "--name", args.containerName, + "-d", + ...params, + args.image, + "run", + ], (err, stdout) => { + console.log("error", err, "stdout", stdout); + if (err) reject(err); + resolve(stdout.trim()); + }); + }); +} + +export function dockerExec(args: { + containerId: string; + params: string[]; +}): Promise { + return new Promise((resolve, reject) => { + childProcess.execFile("docker", [ + "exec", args.containerId, + ...args.params, + ], { encoding: 'utf8' }, (err, stdout, stderr) => { + if (err) { + console.log(stdout); + console.log(stderr); + reject(err); + return; + } + resolve(); + }); + }); +} + +export async function dockerLogs(args: { + containerId: string; + stdoutFile?: string; + stderrFile?: string; +}): Promise { + const stdoutFile = args.stdoutFile ? await fse.open(args.stdoutFile, "w") : "ignore"; + const stderrFile = args.stderrFile ? await fse.open(args.stderrFile, "w") : "ignore"; + + await new Promise((resolve) => { + childProcess.spawn("docker", [ + "logs", + args.containerId, + ], { + stdio: ["ignore", stdoutFile, stderrFile], + }).once('close', resolve); + }); + + if (args.stdoutFile) await fse.close(stdoutFile); + if (args.stderrFile) await fse.close(stderrFile); +} + +export function dockerStop(args: { + containerId: string; +}): Promise { + return new Promise((resolve, reject) => { + childProcess.execFile('docker', [ + "stop", + args.containerId, + ], err => { + if (err) reject(err); + resolve(); + }); + }); +} + +export function dockerRm(args: { + containerId: string; +}): Promise { + return new Promise((resolve, reject) => { + childProcess.execFile('docker', [ + "rm", + args.containerId, + ], err => { + if (err) reject(err); + resolve(); + }); + }); +} + +/** + * @type {Cypress.PluginConfig} + */ +export function docker(on: PluginEvents, config: PluginConfigOptions) { + console.log("Code gets to here!"); + on("task", { + dockerRun, + dockerExec, + dockerLogs, + dockerStop, + dockerRm, + }); +} diff --git a/cypress/plugins/index.ts b/cypress/plugins/index.ts new file mode 100644 index 00000000..44dd93b8 --- /dev/null +++ b/cypress/plugins/index.ts @@ -0,0 +1,36 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/// + +import PluginEvents = Cypress.PluginEvents; +import PluginConfigOptions = Cypress.PluginConfigOptions; +import { performance } from "./performance"; +import { synapseDocker } from "./synapsedocker"; +import { webserver } from "./webserver"; +import { docker } from "./docker"; +import { log } from "./log"; + +/** + * @type {Cypress.PluginConfig} + */ +export default function(on: PluginEvents, config: PluginConfigOptions) { + docker(on, config); + performance(on, config); + synapseDocker(on, config); + webserver(on, config); + log(on, config); +} diff --git a/cypress/plugins/log.ts b/cypress/plugins/log.ts new file mode 100644 index 00000000..4b16c9b8 --- /dev/null +++ b/cypress/plugins/log.ts @@ -0,0 +1,35 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/// + +import PluginEvents = Cypress.PluginEvents; +import PluginConfigOptions = Cypress.PluginConfigOptions; + +export function log(on: PluginEvents, config: PluginConfigOptions) { + on("task", { + log(message: string) { + console.log(message); + + return null; + }, + table(message: string) { + console.table(message); + + return null; + }, + }); +} diff --git a/cypress/plugins/performance.ts b/cypress/plugins/performance.ts new file mode 100644 index 00000000..c6bd3e4c --- /dev/null +++ b/cypress/plugins/performance.ts @@ -0,0 +1,47 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/// + +import * as path from "path"; +import * as fse from "fs-extra"; + +import PluginEvents = Cypress.PluginEvents; +import PluginConfigOptions = Cypress.PluginConfigOptions; + +// This holds all the performance measurements throughout the run +let bufferedMeasurements: PerformanceEntry[] = []; + +function addMeasurements(measurements: PerformanceEntry[]): void { + bufferedMeasurements = bufferedMeasurements.concat(measurements); + return null; +} + +async function writeMeasurementsFile() { + try { + const measurementsPath = path.join("cypress", "performance", "measurements.json"); + await fse.outputJSON(measurementsPath, bufferedMeasurements, { + spaces: 4, + }); + } finally { + bufferedMeasurements = []; + } +} + +export function performance(on: PluginEvents, config: PluginConfigOptions) { + on("task", { addMeasurements }); + on("after:run", writeMeasurementsFile); +} diff --git a/cypress/plugins/synapsedocker/index.ts b/cypress/plugins/synapsedocker/index.ts new file mode 100644 index 00000000..5227b5e4 --- /dev/null +++ b/cypress/plugins/synapsedocker/index.ts @@ -0,0 +1,187 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/// + +import * as path from "path"; +import * as os from "os"; +import * as crypto from "crypto"; +import * as fse from "fs-extra"; + +import PluginEvents = Cypress.PluginEvents; +import PluginConfigOptions = Cypress.PluginConfigOptions; +import { getFreePort } from "../utils/port"; +import { dockerExec, dockerLogs, dockerRun, dockerStop } from "../docker"; + +// A cypress plugins to add command to start & stop synapses in +// docker with preset templates. + +interface SynapseConfig { + configDir: string; + registrationSecret: string; + // Synapse must be configured with its public_baseurl so we have to allocate a port & url at this stage + baseUrl: string; + port: number; +} + +export interface SynapseInstance extends SynapseConfig { + synapseId: string; +} + +const synapses = new Map(); + +function randB64Bytes(numBytes: number): string { + return crypto.randomBytes(numBytes).toString("base64").replace(/=*$/, ""); +} + +async function cfgDirFromTemplate(template: string): Promise { + const templateDir = path.join(__dirname, "templates", template); + + const stats = await fse.stat(templateDir); + if (!stats?.isDirectory) { + throw new Error(`No such template: ${template}`); + } + const tempDir = await fse.mkdtemp(path.join(os.tmpdir(), 'react-sdk-synapsedocker-')); + + // copy the contents of the template dir, omitting homeserver.yaml as we'll template that + console.log(`Copy ${templateDir} -> ${tempDir}`); + await fse.copy(templateDir, tempDir, { filter: f => path.basename(f) !== 'homeserver.yaml' }); + + const registrationSecret = randB64Bytes(16); + const macaroonSecret = randB64Bytes(16); + const formSecret = randB64Bytes(16); + + const port = await getFreePort(); + const baseUrl = `http://localhost:${port}`; + + // now copy homeserver.yaml, applying substitutions + console.log(`Gen ${path.join(templateDir, "homeserver.yaml")}`); + let hsYaml = await fse.readFile(path.join(templateDir, "homeserver.yaml"), "utf8"); + hsYaml = hsYaml.replace(/{{REGISTRATION_SECRET}}/g, registrationSecret); + hsYaml = hsYaml.replace(/{{MACAROON_SECRET_KEY}}/g, macaroonSecret); + hsYaml = hsYaml.replace(/{{FORM_SECRET}}/g, formSecret); + hsYaml = hsYaml.replace(/{{PUBLIC_BASEURL}}/g, baseUrl); + await fse.writeFile(path.join(tempDir, "homeserver.yaml"), hsYaml); + + // now generate a signing key (we could use synapse's config generation for + // this, or we could just do this...) + // NB. This assumes the homeserver.yaml specifies the key in this location + const signingKey = randB64Bytes(32); + console.log(`Gen ${path.join(templateDir, "localhost.signing.key")}`); + await fse.writeFile(path.join(tempDir, "localhost.signing.key"), `ed25519 x ${signingKey}`); + + return { + port, + baseUrl, + configDir: tempDir, + registrationSecret, + }; +} + +// Start a synapse instance: the template must be the name of +// one of the templates in the cypress/plugins/synapsedocker/templates +// directory +async function synapseStart(template: string): Promise { + const synCfg = await cfgDirFromTemplate(template); + + console.log(`Starting synapse with config dir ${synCfg.configDir}...`); + + const synapseId = await dockerRun({ + image: "matrixdotorg/synapse:develop", + containerName: `react-sdk-cypress-synapse-${crypto.randomBytes(4).toString("hex")}`, + params: [ + "--rm", + "-v", `${synCfg.configDir}:/data`, + "-p", `${synCfg.port}:8008/tcp`, + ], + }); + + console.log(`Started synapse with id ${synapseId} on port ${synCfg.port}.`); + + // Await Synapse healthcheck + await dockerExec({ + containerId: synapseId, + params: [ + "curl", + "--connect-timeout", "30", + "--retry", "30", + "--retry-delay", "1", + "--retry-all-errors", + "--silent", + "http://localhost:8008/health", + ], + }); + + const synapse: SynapseInstance = { synapseId, ...synCfg }; + synapses.set(synapseId, synapse); + return synapse; +} + +async function synapseStop(id: string): Promise { + const synCfg = synapses.get(id); + + if (!synCfg) throw new Error("Unknown synapse ID"); + + const synapseLogsPath = path.join("cypress", "synapselogs", id); + await fse.ensureDir(synapseLogsPath); + + await dockerLogs({ + containerId: id, + stdoutFile: path.join(synapseLogsPath, "stdout.log"), + stderrFile: path.join(synapseLogsPath, "stderr.log"), + }); + + await dockerStop({ + containerId: id, + }); + + await fse.remove(synCfg.configDir); + + synapses.delete(id); + + console.log(`Stopped synapse id ${id}.`); + // cypress deliberately fails if you return 'undefined', so + // return null to signal all is well, and we've handled the task. + return null; +} + +/** + * @type {Cypress.PluginConfig} + */ +export function synapseDocker(on: PluginEvents, config: PluginConfigOptions) { + on("task", { + synapseStart, + synapseStop, + }); + + on("after:spec", async (spec) => { + // Cleans up any remaining synapse instances after a spec run + // This is on the theory that we should avoid re-using synapse + // instances between spec runs: they should be cheap enough to + // start that we can have a separate one for each spec run or even + // test. If we accidentally re-use synapses, we could inadvertently + // make our tests depend on each other. + for (const synId of synapses.keys()) { + console.warn(`Cleaning up synapse ID ${synId} after ${spec.name}`); + await synapseStop(synId); + } + }); + + on("before:run", async () => { + // tidy up old synapse log files before each run + await fse.emptyDir(path.join("cypress", "synapselogs")); + }); +} diff --git a/cypress/plugins/synapsedocker/templates/COPYME/README.md b/cypress/plugins/synapsedocker/templates/COPYME/README.md new file mode 100644 index 00000000..df1ed89e --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/COPYME/README.md @@ -0,0 +1,3 @@ +# Meta-template for synapse templates + +To make another template, you can copy this directory diff --git a/cypress/plugins/synapsedocker/templates/COPYME/homeserver.yaml b/cypress/plugins/synapsedocker/templates/COPYME/homeserver.yaml new file mode 100644 index 00000000..fab1bc1c --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/COPYME/homeserver.yaml @@ -0,0 +1,72 @@ +server_name: "localhost" +pid_file: /data/homeserver.pid +# XXX: This won't actually be right: it lets docker allocate an ephemeral port, +# so we have a chicken-and-egg problem +public_baseurl: http://localhost:8008/ +# Listener is always port 8008 (configured in the container) +listeners: + - port: 8008 + tls: false + bind_addresses: ['::'] + type: http + x_forwarded: true + + resources: + - names: [client, federation, consent] + compress: false + +# An sqlite in-memory database is fast & automatically wipes each time +database: + name: "sqlite3" + args: + database: ":memory:" + +# Needs to be configured to log to the console like a good docker process +log_config: "/data/log.config" + +rc_messages_per_second: 10000 +rc_message_burst_count: 10000 +rc_registration: + per_second: 10000 + burst_count: 10000 + +rc_login: + address: + per_second: 10000 + burst_count: 10000 + account: + per_second: 10000 + burst_count: 10000 + failed_attempts: + per_second: 10000 + burst_count: 10000 + +media_store_path: "/data/media_store" +uploads_path: "/data/uploads" +enable_registration: true +enable_registration_without_verification: true +disable_msisdn_registration: false +# These placeholders will be be replaced with values generated at start +registration_shared_secret: "{{REGISTRATION_SECRET}}" +report_stats: false +macaroon_secret_key: "{{MACAROON_SECRET_KEY}}" +form_secret: "{{FORM_SECRET}}" +# Signing key must be here: it will be generated to this file +signing_key_path: "/data/localhost.signing.key" +email: + enable_notifs: false + smtp_host: "localhost" + smtp_port: 25 + smtp_user: "exampleusername" + smtp_pass: "examplepassword" + require_transport_security: False + notif_from: "Your Friendly %(app)s homeserver " + app_name: Matrix + notif_template_html: notif_mail.html + notif_template_text: notif_mail.txt + notif_for_new_users: True + client_base_url: "http://localhost/element" + +trusted_key_servers: + - server_name: "matrix.org" +suppress_key_server_warning: true diff --git a/cypress/plugins/synapsedocker/templates/COPYME/log.config b/cypress/plugins/synapsedocker/templates/COPYME/log.config new file mode 100644 index 00000000..ac232762 --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/COPYME/log.config @@ -0,0 +1,50 @@ +# Log configuration for Synapse. +# +# This is a YAML file containing a standard Python logging configuration +# dictionary. See [1] for details on the valid settings. +# +# Synapse also supports structured logging for machine readable logs which can +# be ingested by ELK stacks. See [2] for details. +# +# [1]: https://docs.python.org/3.7/library/logging.config.html#configuration-dictionary-schema +# [2]: https://matrix-org.github.io/synapse/latest/structured_logging.html + +version: 1 + +formatters: + precise: + format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' + +handlers: + # A handler that writes logs to stderr. Unused by default, but can be used + # instead of "buffer" and "file" in the logger handlers. + console: + class: logging.StreamHandler + formatter: precise + +loggers: + synapse.storage.SQL: + # beware: increasing this to DEBUG will make synapse log sensitive + # information such as access tokens. + level: INFO + + twisted: + # We send the twisted logging directly to the file handler, + # to work around https://github.com/matrix-org/synapse/issues/3471 + # when using "buffer" logger. Use "console" to log to stderr instead. + handlers: [console] + propagate: false + +root: + level: INFO + + # Write logs to the `buffer` handler, which will buffer them together in memory, + # then write them to a file. + # + # Replace "buffer" with "console" to log to stderr instead. (Note that you'll + # also need to update the configuration for the `twisted` logger above, in + # this case.) + # + handlers: [console] + +disable_existing_loggers: false diff --git a/cypress/plugins/synapsedocker/templates/consent/README.md b/cypress/plugins/synapsedocker/templates/consent/README.md new file mode 100644 index 00000000..713e55f9 --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/consent/README.md @@ -0,0 +1 @@ +A synapse configured with user privacy consent enabled diff --git a/cypress/plugins/synapsedocker/templates/consent/homeserver.yaml b/cypress/plugins/synapsedocker/templates/consent/homeserver.yaml new file mode 100644 index 00000000..6decaeb5 --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/consent/homeserver.yaml @@ -0,0 +1,84 @@ +server_name: "localhost" +pid_file: /data/homeserver.pid +public_baseurl: "{{PUBLIC_BASEURL}}" +listeners: + - port: 8008 + tls: false + bind_addresses: ['::'] + type: http + x_forwarded: true + + resources: + - names: [client, federation, consent] + compress: false + +database: + name: "sqlite3" + args: + database: ":memory:" + +log_config: "/data/log.config" + +rc_messages_per_second: 10000 +rc_message_burst_count: 10000 +rc_registration: + per_second: 10000 + burst_count: 10000 + +rc_login: + address: + per_second: 10000 + burst_count: 10000 + account: + per_second: 10000 + burst_count: 10000 + failed_attempts: + per_second: 10000 + burst_count: 10000 + +media_store_path: "/data/media_store" +uploads_path: "/data/uploads" +enable_registration: true +enable_registration_without_verification: true +disable_msisdn_registration: false +registration_shared_secret: "{{REGISTRATION_SECRET}}" +report_stats: false +macaroon_secret_key: "{{MACAROON_SECRET_KEY}}" +form_secret: "{{FORM_SECRET}}" +signing_key_path: "/data/localhost.signing.key" +email: + enable_notifs: false + smtp_host: "localhost" + smtp_port: 25 + smtp_user: "exampleusername" + smtp_pass: "examplepassword" + require_transport_security: False + notif_from: "Your Friendly %(app)s homeserver " + app_name: Matrix + notif_template_html: notif_mail.html + notif_template_text: notif_mail.txt + notif_for_new_users: True + client_base_url: "http://localhost/element" + +user_consent: + template_dir: /data/res/templates/privacy + version: 1.0 + server_notice_content: + msgtype: m.text + body: >- + To continue using this homeserver you must review and agree to the + terms and conditions at %(consent_uri)s + send_server_notice_to_guests: True + block_events_error: >- + To continue using this homeserver you must review and agree to the + terms and conditions at %(consent_uri)s + require_at_registration: true + +server_notices: + system_mxid_localpart: notices + system_mxid_display_name: "Server Notices" + system_mxid_avatar_url: "mxc://localhost:5005/oumMVlgDnLYFaPVkExemNVVZ" + room_name: "Server Notices" +trusted_key_servers: + - server_name: "matrix.org" +suppress_key_server_warning: true diff --git a/cypress/plugins/synapsedocker/templates/consent/log.config b/cypress/plugins/synapsedocker/templates/consent/log.config new file mode 100644 index 00000000..b9123d0f --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/consent/log.config @@ -0,0 +1,50 @@ +# Log configuration for Synapse. +# +# This is a YAML file containing a standard Python logging configuration +# dictionary. See [1] for details on the valid settings. +# +# Synapse also supports structured logging for machine readable logs which can +# be ingested by ELK stacks. See [2] for details. +# +# [1]: https://docs.python.org/3.7/library/logging.config.html#configuration-dictionary-schema +# [2]: https://matrix-org.github.io/synapse/latest/structured_logging.html + +version: 1 + +formatters: + precise: + format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' + +handlers: + # A handler that writes logs to stderr. Unused by default, but can be used + # instead of "buffer" and "file" in the logger handlers. + console: + class: logging.StreamHandler + formatter: precise + +loggers: + synapse.storage.SQL: + # beware: increasing this to DEBUG will make synapse log sensitive + # information such as access tokens. + level: DEBUG + + twisted: + # We send the twisted logging directly to the file handler, + # to work around https://github.com/matrix-org/synapse/issues/3471 + # when using "buffer" logger. Use "console" to log to stderr instead. + handlers: [console] + propagate: false + +root: + level: DEBUG + + # Write logs to the `buffer` handler, which will buffer them together in memory, + # then write them to a file. + # + # Replace "buffer" with "console" to log to stderr instead. (Note that you'll + # also need to update the configuration for the `twisted` logger above, in + # this case.) + # + handlers: [console] + +disable_existing_loggers: false diff --git a/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html b/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html new file mode 100644 index 00000000..d4959b4b --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html @@ -0,0 +1,23 @@ + + + + Test Privacy policy + + + {% if has_consented %} +

+ Thank you, you've already accepted the license. +

+ {% else %} +

+ Please accept the license! +

+
+ + + + +
+ {% endif %} + + \ No newline at end of file diff --git a/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html b/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html new file mode 100644 index 00000000..abe27d87 --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html @@ -0,0 +1,9 @@ + + + + Test Privacy policy + + +

Danke schon

+ + \ No newline at end of file diff --git a/cypress/plugins/synapsedocker/templates/default/README.md b/cypress/plugins/synapsedocker/templates/default/README.md new file mode 100644 index 00000000..8f6b11f9 --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/default/README.md @@ -0,0 +1 @@ +A synapse configured with user privacy consent disabled diff --git a/cypress/plugins/synapsedocker/templates/default/homeserver.yaml b/cypress/plugins/synapsedocker/templates/default/homeserver.yaml new file mode 100644 index 00000000..347dadc8 --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/default/homeserver.yaml @@ -0,0 +1,76 @@ +server_name: "localhost" +pid_file: /data/homeserver.pid +public_baseurl: "{{PUBLIC_BASEURL}}" +listeners: + - port: 8008 + tls: false + bind_addresses: ['::'] + type: http + x_forwarded: true + + resources: + - names: [client] + compress: false + +database: + name: "sqlite3" + args: + database: ":memory:" + +log_config: "/data/log.config" + +rc_messages_per_second: 10000 +rc_message_burst_count: 10000 +rc_registration: + per_second: 10000 + burst_count: 10000 +rc_joins: + local: + per_second: 9999 + burst_count: 9999 + remote: + per_second: 9999 + burst_count: 9999 +rc_joins_per_room: + per_second: 9999 + burst_count: 9999 +rc_3pid_validation: + per_second: 1000 + burst_count: 1000 + +rc_invites: + per_room: + per_second: 1000 + burst_count: 1000 + per_user: + per_second: 1000 + burst_count: 1000 + +rc_login: + address: + per_second: 10000 + burst_count: 10000 + account: + per_second: 10000 + burst_count: 10000 + failed_attempts: + per_second: 10000 + burst_count: 10000 + +media_store_path: "/data/media_store" +uploads_path: "/data/uploads" +enable_registration: true +enable_registration_without_verification: true +disable_msisdn_registration: false +registration_shared_secret: "{{REGISTRATION_SECRET}}" +report_stats: false +macaroon_secret_key: "{{MACAROON_SECRET_KEY}}" +form_secret: "{{FORM_SECRET}}" +signing_key_path: "/data/localhost.signing.key" + +trusted_key_servers: + - server_name: "matrix.org" +suppress_key_server_warning: true + +ui_auth: + session_timeout: "300s" diff --git a/cypress/plugins/synapsedocker/templates/default/log.config b/cypress/plugins/synapsedocker/templates/default/log.config new file mode 100644 index 00000000..b9123d0f --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/default/log.config @@ -0,0 +1,50 @@ +# Log configuration for Synapse. +# +# This is a YAML file containing a standard Python logging configuration +# dictionary. See [1] for details on the valid settings. +# +# Synapse also supports structured logging for machine readable logs which can +# be ingested by ELK stacks. See [2] for details. +# +# [1]: https://docs.python.org/3.7/library/logging.config.html#configuration-dictionary-schema +# [2]: https://matrix-org.github.io/synapse/latest/structured_logging.html + +version: 1 + +formatters: + precise: + format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' + +handlers: + # A handler that writes logs to stderr. Unused by default, but can be used + # instead of "buffer" and "file" in the logger handlers. + console: + class: logging.StreamHandler + formatter: precise + +loggers: + synapse.storage.SQL: + # beware: increasing this to DEBUG will make synapse log sensitive + # information such as access tokens. + level: DEBUG + + twisted: + # We send the twisted logging directly to the file handler, + # to work around https://github.com/matrix-org/synapse/issues/3471 + # when using "buffer" logger. Use "console" to log to stderr instead. + handlers: [console] + propagate: false + +root: + level: DEBUG + + # Write logs to the `buffer` handler, which will buffer them together in memory, + # then write them to a file. + # + # Replace "buffer" with "console" to log to stderr instead. (Note that you'll + # also need to update the configuration for the `twisted` logger above, in + # this case.) + # + handlers: [console] + +disable_existing_loggers: false diff --git a/cypress/plugins/utils/port.ts b/cypress/plugins/utils/port.ts new file mode 100644 index 00000000..064ccc7c --- /dev/null +++ b/cypress/plugins/utils/port.ts @@ -0,0 +1,27 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import * as net from "net"; + +export async function getFreePort(): Promise { + return new Promise(resolve => { + const srv = net.createServer(); + srv.listen(0, () => { + const port = (srv.address()).port; + srv.close(() => resolve(port)); + }); + }); +} diff --git a/cypress/plugins/webserver.ts b/cypress/plugins/webserver.ts new file mode 100644 index 00000000..55a25a31 --- /dev/null +++ b/cypress/plugins/webserver.ts @@ -0,0 +1,52 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/// + +import * as http from "http"; +import { AddressInfo } from "net"; + +import PluginEvents = Cypress.PluginEvents; +import PluginConfigOptions = Cypress.PluginConfigOptions; + +const servers: http.Server[] = []; + +function serveHtmlFile(html: string): string { + const server = http.createServer((req, res) => { + res.writeHead(200, { + "Content-Type": "text/html", + }); + res.end(html); + }); + server.listen(); + servers.push(server); + + return `http://localhost:${(server.address() as AddressInfo).port}/`; +} + +function stopWebServers(): null { + for (const server of servers) { + server.close(); + } + servers.splice(0, servers.length); // clear + + return null; // tell cypress we did the task successfully (doesn't allow undefined) +} + +export function webserver(on: PluginEvents, config: PluginConfigOptions) { + on("task", { serveHtmlFile, stopWebServers }); + on("after:run", stopWebServers); +} diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts new file mode 100644 index 00000000..289319fe --- /dev/null +++ b/cypress/support/e2e.ts @@ -0,0 +1,19 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/// + +import "./synapse"; diff --git a/cypress/support/synapse.ts b/cypress/support/synapse.ts new file mode 100644 index 00000000..5696e8c0 --- /dev/null +++ b/cypress/support/synapse.ts @@ -0,0 +1,122 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/// + +import * as crypto from 'crypto'; + +import Chainable = Cypress.Chainable; +import AUTWindow = Cypress.AUTWindow; +import { SynapseInstance } from "../plugins/synapsedocker"; + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace Cypress { + interface Chainable { + /** + * Start a synapse instance with a given config template. + * @param template path to template within cypress/plugins/synapsedocker/template/ directory. + */ + startSynapse(template: string): Chainable; + + /** + * Custom command wrapping task:synapseStop whilst preventing uncaught exceptions + * for if Synapse stopping races with the app's background sync loop. + * @param synapse the synapse instance returned by startSynapse + */ + stopSynapse(synapse: SynapseInstance): Chainable; + + /** + * Register a user on the given Synapse using the shared registration secret. + * @param synapse the synapse instance returned by startSynapse + * @param username the username of the user to register + * @param password the password of the user to register + * @param displayName optional display name to set on the newly registered user + */ + registerUser( + synapse: SynapseInstance, + username: string, + password: string, + displayName?: string, + ): Chainable; + } + } +} + +function startSynapse(template: string): Chainable { + return cy.task("synapseStart", template); +} + +function stopSynapse(synapse?: SynapseInstance): Chainable { + if (!synapse) return; + // Navigate away from app to stop the background network requests which will race with Synapse shutting down + return cy.window({ log: false }).then((win) => { + win.location.href = 'about:blank'; + cy.task("synapseStop", synapse.synapseId); + }); +} + +interface Credentials { + accessToken: string; + userId: string; + deviceId: string; + homeServer: string; +} + +function registerUser( + synapse: SynapseInstance, + username: string, + password: string, + displayName?: string, +): Chainable { + const url = `${synapse.baseUrl}/_synapse/admin/v1/register`; + return cy.then(() => { + // get a nonce + return cy.request<{ nonce: string }>({ url }); + }).then(response => { + const { nonce } = response.body; + const mac = crypto.createHmac('sha1', synapse.registrationSecret).update( + `${nonce}\0${username}\0${password}\0notadmin`, + ).digest('hex'); + + return cy.request<{ + access_token: string; + user_id: string; + home_server: string; + device_id: string; + }>({ + url, + method: "POST", + body: { + nonce, + username, + password, + mac, + admin: false, + displayname: displayName, + }, + }); + }).then(response => ({ + homeServer: response.body.home_server, + accessToken: response.body.access_token, + userId: response.body.user_id, + deviceId: response.body.device_id, + })); +} + +Cypress.Commands.add("startSynapse", startSynapse); +Cypress.Commands.add("stopSynapse", stopSynapse); +Cypress.Commands.add("registerUser", registerUser); diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json index 18edb199..6bd44918 100644 --- a/cypress/tsconfig.json +++ b/cypress/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "downlevelIteration": true, "target": "es5", "lib": ["es5", "dom"], "types": ["cypress", "node"] From d98a3e43bf30aba0dbed66b27b33c843987f6ff7 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 6 Sep 2022 01:24:57 +0530 Subject: [PATCH 04/20] Ignore synapse logs --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b0714d24..20f09f19 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ lib .eslintcache .tmp cypress/videos +cypress/synapselogs From 193415ac1d4d93875f19a5640d758a140011b266 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 6 Sep 2022 01:25:28 +0530 Subject: [PATCH 05/20] Add configurable variables --- cypress.config.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cypress.config.ts b/cypress.config.ts index 6761d05d..02f39392 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -6,6 +6,12 @@ export default defineConfig({ require("./cypress/plugins/index.ts").default(on, config); return config; }, - baseUrl: "http://localhost:3000", + baseUrl: "http://127.0.0.1:3000", + }, + env: { + SYNAPSE_IP_ADDRESS: "172.18.0.5", + SYNAPSE_PORT: "8008", + DEX_IP_ADDRESS: "172.18.0.4", + DEX_PORT: "5556", }, }); From 2376ef8b8ce9f62ff97bbfd0439beac1158b8508 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 6 Sep 2022 01:26:45 +0530 Subject: [PATCH 06/20] Write plugin for Dex --- cypress/plugins/dex/index.ts | 132 +++++++++++++++++++++++ cypress/plugins/dex/template/config.yaml | 56 ++++++++++ cypress/plugins/dex/template/dev.db | Bin 0 -> 110592 bytes cypress/plugins/index.ts | 2 + cypress/support/dex.ts | 51 +++++++++ cypress/support/e2e.ts | 1 + 6 files changed, 242 insertions(+) create mode 100644 cypress/plugins/dex/index.ts create mode 100755 cypress/plugins/dex/template/config.yaml create mode 100755 cypress/plugins/dex/template/dev.db create mode 100644 cypress/support/dex.ts diff --git a/cypress/plugins/dex/index.ts b/cypress/plugins/dex/index.ts new file mode 100644 index 00000000..b07a78e8 --- /dev/null +++ b/cypress/plugins/dex/index.ts @@ -0,0 +1,132 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/// + +import * as path from "path"; +import * as os from "os"; +import * as fse from "fs-extra"; + +import PluginEvents = Cypress.PluginEvents; +import PluginConfigOptions = Cypress.PluginConfigOptions; +import {dockerRun, dockerStop } from "../docker"; + +// A cypress plugins to add command to start & stop dex instances + +interface DexConfig { + configDir: string; + baseUrl: string; + port: number; + host: string; +} + +export interface DexInstance extends DexConfig { + dexId: string; +} + +const dexConfigs = new Map(); +let env; + +async function produceConfigWithSynapseURLAdded(): Promise { + const templateDir = path.join(__dirname, "template"); + + const stats = await fse.stat(templateDir); + if (!stats?.isDirectory) { + throw new Error(`Template directory at ${templateDir} not found!`); + } + const tempDir = await fse.mkdtemp(path.join(os.tmpdir(), 'hydrogen-testing-dex-')); + + // copy the contents of the template dir, omitting config.yaml as we'll template that + console.log(`Copy ${templateDir} -> ${tempDir}`); + await fse.copy(templateDir, tempDir, { filter: f => path.basename(f) !== 'config.yaml' }); + + // now copy config.yaml, applying substitutions + console.log(`Gen ${path.join(templateDir, "config.yaml")}`); + let hsYaml = await fse.readFile(path.join(templateDir, "config.yaml"), "utf8"); + const synapseAddress = `${env.SYNAPSE_IP_ADDRESS}:${env.SYNAPSE_PORT}`; + hsYaml = hsYaml.replace(/{{SYNAPSE_ADDRESS}}/g, synapseAddress); + const host = env.DEX_IP_ADDRESS; + const port = env.DEX_PORT; + const dexAddress = `${host}:${port}`; + hsYaml = hsYaml.replace(/{{DEX_ADDRESS}}/g, dexAddress); + await fse.writeFile(path.join(tempDir, "config.yaml"), hsYaml); + + const baseUrl = `http://${host}:${port}`; + return { + host, + port, + baseUrl, + configDir: tempDir, + }; +} + +async function dexStart(): Promise { + const dexCfg = await produceConfigWithSynapseURLAdded(); + console.log(`Starting dex with config dir ${dexCfg.configDir}...`); + const dexId = await dockerRun({ + image: "bitnami/dex:latest", + containerName: "dex", + dockerParams: [ + "--rm", + "-v", `${dexCfg.configDir}:/data`, + `--ip=${dexCfg.host}`, + "-p", `${dexCfg.port}:5556/tcp`, + "--network=hydrogen" + ], + applicationParams: [ + "serve", + "data/config.yaml", + ] + }); + + console.log(`Started dex with id ${dexId} on port ${dexCfg.port}.`); + + const dex: DexInstance = { dexId, ...dexCfg }; + dexConfigs.set(dexId, dex); + return dex; +} + +async function dexStop(id: string): Promise { + const dexCfg = dexConfigs.get(id); + if (!dexCfg) throw new Error("Unknown dex ID"); + await dockerStop({ containerId: id, }); + await fse.remove(dexCfg.configDir); + dexConfigs.delete(id); + console.log(`Stopped dex id ${id}.`); + // cypress deliberately fails if you return 'undefined', so + // return null to signal all is well, and we've handled the task. + return null; +} + +/** + * @type {Cypress.PluginConfig} + */ +export function dexDocker(on: PluginEvents, config: PluginConfigOptions) { + env = config.env; + + on("task", { + dexStart, + dexStop, + }); + + on("after:spec", async (spec) => { + for (const dexId of dexConfigs.keys()) { + console.warn(`Cleaning up dex ID ${dexId} after ${spec.name}`); + await dexStop(dexId); + } + }); +} + diff --git a/cypress/plugins/dex/template/config.yaml b/cypress/plugins/dex/template/config.yaml new file mode 100755 index 00000000..f773eb76 --- /dev/null +++ b/cypress/plugins/dex/template/config.yaml @@ -0,0 +1,56 @@ +issuer: http://{{DEX_ADDRESS}}/dex + +storage: + type: sqlite3 + config: + file: data/dev.db + + +# Configuration for the HTTP endpoints. +web: + http: 0.0.0.0:5556 + # Uncomment for HTTPS options. + # https: 127.0.0.1:5554 + # tlsCert: /etc/dex/tls.crt + # tlsKey: /etc/dex/tls.key + +# Configuration for telemetry +telemetry: + http: 0.0.0.0:5558 + # enableProfiling: true + +staticClients: +- id: synapse + secret: secret + redirectURIs: + - 'http://{{SYNAPSE_ADDRESS}}/_synapse/client/oidc/callback' + name: 'Synapse' +connectors: +- type: mockCallback + id: mock + name: Example +# - type: google +# id: google +# name: Google +# config: +# issuer: https://accounts.google.com +# # Connector config values starting with a "$" will read from the environment. +# clientID: $GOOGLE_CLIENT_ID +# clientSecret: $GOOGLE_CLIENT_SECRET +# redirectURI: http://127.0.0.1:5556/dex/callback +# hostedDomains: +# - $GOOGLE_HOSTED_DOMAIN + +# Let dex keep a list of passwords which can be used to login to dex. +enablePasswordDB: true + +# A static list of passwords to login the end user. By identifying here, dex +# won't look in its underlying storage for passwords. +# +# If this option isn't chosen users may be added through the gRPC API. +staticPasswords: +- email: "admin@example.com" + # bcrypt hash of the string "password": $(echo password | htpasswd -BinC 10 admin | cut -d: -f2) + hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W" + username: "admin" + userID: "08a8684b-db88-4b73-90a9-3cd1661f5466" diff --git a/cypress/plugins/dex/template/dev.db b/cypress/plugins/dex/template/dev.db new file mode 100755 index 0000000000000000000000000000000000000000..95a42aedb495111cfc33e6e614237d869a7373da GIT binary patch literal 110592 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 + +import Chainable = Cypress.Chainable; +import AUTWindow = Cypress.AUTWindow; +import { DexInstance } from "../plugins/dex"; + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace Cypress { + interface Chainable { + /** + * Start the dex server + */ + startDex(): Chainable; + + /** + * Stop the dex server + * @param dex the dex instance returned by startSynapse + */ + stopDex(dex: DexInstance): Chainable; + } + } +} + +function startDex(): Chainable { + return cy.task("dexStart"); +} + +function stopDex(dex?: DexInstance): Chainable { + if (!dex) return; + cy.task("dexStop", dex.dexId); +} + +Cypress.Commands.add("startDex", startDex); +Cypress.Commands.add("stopDex", stopDex); diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index 289319fe..d186c5a0 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -17,3 +17,4 @@ limitations under the License. /// import "./synapse"; +import "./dex"; From 2d1e8f10b76eb9159126e1060999b4c1f5eef38c Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 6 Sep 2022 01:27:47 +0530 Subject: [PATCH 07/20] Support app params and docker params separately --- cypress/plugins/docker/index.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/cypress/plugins/docker/index.ts b/cypress/plugins/docker/index.ts index 024cb9d4..8a429b67 100644 --- a/cypress/plugins/docker/index.ts +++ b/cypress/plugins/docker/index.ts @@ -28,10 +28,12 @@ import PluginConfigOptions = Cypress.PluginConfigOptions; export function dockerRun(args: { image: string; containerName: string; - params?: string[]; + dockerParams?: string[]; + applicationParams?: string[]; }): Promise { const userInfo = os.userInfo(); - const params = args.params ?? []; + const params = args.dockerParams ?? []; + const appParams = args.applicationParams ?? []; if (userInfo.uid >= 0) { // On *nix we run the docker container as our uid:gid otherwise cleaning it up its media_store can be difficult @@ -45,10 +47,12 @@ export function dockerRun(args: { "-d", ...params, args.image, - "run", - ], (err, stdout) => { - console.log("error", err, "stdout", stdout); - if (err) reject(err); + ... appParams + ], (err, stdout, stderr) => { + console.log("error", err, "stdout", stdout, "stderr", stderr); + if (err) { + reject(err); + } resolve(stdout.trim()); }); }); From 3ff83f3d3dc21fbddb01174a6b74bf1fe3481480 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 6 Sep 2022 01:28:36 +0530 Subject: [PATCH 08/20] Add braces for if-else --- cypress/plugins/docker/index.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cypress/plugins/docker/index.ts b/cypress/plugins/docker/index.ts index 8a429b67..fe9c24ae 100644 --- a/cypress/plugins/docker/index.ts +++ b/cypress/plugins/docker/index.ts @@ -107,7 +107,9 @@ export function dockerStop(args: { "stop", args.containerId, ], err => { - if (err) reject(err); + if (err) { + reject(err); + } resolve(); }); }); @@ -121,7 +123,9 @@ export function dockerRm(args: { "rm", args.containerId, ], err => { - if (err) reject(err); + if (err) { + reject(err); + } resolve(); }); }); From 888a509c372d9a173148d2776191edd5d1fe761c Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 6 Sep 2022 01:29:37 +0530 Subject: [PATCH 09/20] Support creating docker networks from the plugin --- cypress/plugins/docker/index.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/cypress/plugins/docker/index.ts b/cypress/plugins/docker/index.ts index fe9c24ae..a55f341e 100644 --- a/cypress/plugins/docker/index.ts +++ b/cypress/plugins/docker/index.ts @@ -78,6 +78,31 @@ export function dockerExec(args: { }); } +/** + * Create a docker network; does not fail if network already exists + */ +export function dockerCreateNetwork(args: { + networkName: string; +}): Promise { + return new Promise((resolve, reject) => { + childProcess.execFile("docker", [ + "network", + "create", + args.networkName + ], { encoding: 'utf8' }, (err, stdout, stderr) => { + if(err) { + if (stderr.includes(`network with name ${args.networkName} already exists`)) { + // Don't consider this as error + resolve(); + } + reject(err); + return; + } + resolve(); + }) + }); +} + export async function dockerLogs(args: { containerId: string; stdoutFile?: string; @@ -142,5 +167,6 @@ export function docker(on: PluginEvents, config: PluginConfigOptions) { dockerLogs, dockerStop, dockerRm, + dockerCreateNetwork }); } From ca350470b307724e89952f6af3eea555a752c22d Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 6 Sep 2022 01:31:09 +0530 Subject: [PATCH 10/20] Remove unused code --- cypress/plugins/utils/port.ts | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 cypress/plugins/utils/port.ts diff --git a/cypress/plugins/utils/port.ts b/cypress/plugins/utils/port.ts deleted file mode 100644 index 064ccc7c..00000000 --- a/cypress/plugins/utils/port.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import * as net from "net"; - -export async function getFreePort(): Promise { - return new Promise(resolve => { - const srv = net.createServer(); - srv.listen(0, () => { - const port = (srv.address()).port; - srv.close(() => resolve(port)); - }); - }); -} From 096c42198dcecf352a32d8a6c29a0fc7342abf25 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 6 Sep 2022 01:38:02 +0530 Subject: [PATCH 11/20] Make synapse plugin modifications --- cypress/plugins/synapsedocker/index.ts | 30 ++++++++++++++++++++------ 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/cypress/plugins/synapsedocker/index.ts b/cypress/plugins/synapsedocker/index.ts index 5227b5e4..268f7320 100644 --- a/cypress/plugins/synapsedocker/index.ts +++ b/cypress/plugins/synapsedocker/index.ts @@ -23,8 +23,8 @@ import * as fse from "fs-extra"; import PluginEvents = Cypress.PluginEvents; import PluginConfigOptions = Cypress.PluginConfigOptions; -import { getFreePort } from "../utils/port"; -import { dockerExec, dockerLogs, dockerRun, dockerStop } from "../docker"; +import { dockerCreateNetwork, dockerExec, dockerLogs, dockerRun, dockerStop } from "../docker"; + // A cypress plugins to add command to start & stop synapses in // docker with preset templates. @@ -35,6 +35,7 @@ interface SynapseConfig { // Synapse must be configured with its public_baseurl so we have to allocate a port & url at this stage baseUrl: string; port: number; + host: string; } export interface SynapseInstance extends SynapseConfig { @@ -42,6 +43,7 @@ export interface SynapseInstance extends SynapseConfig { } const synapses = new Map(); +let env; function randB64Bytes(numBytes: number): string { return crypto.randomBytes(numBytes).toString("base64").replace(/=*$/, ""); @@ -64,8 +66,9 @@ async function cfgDirFromTemplate(template: string): Promise { const macaroonSecret = randB64Bytes(16); const formSecret = randB64Bytes(16); - const port = await getFreePort(); - const baseUrl = `http://localhost:${port}`; + const host = env["SYNAPSE_IP_ADDRESS"]; + const port = parseInt(env["SYNAPSE_PORT"], 10); + const baseUrl = `http://${host}:${port}`; // now copy homeserver.yaml, applying substitutions console.log(`Gen ${path.join(templateDir, "homeserver.yaml")}`); @@ -74,6 +77,8 @@ async function cfgDirFromTemplate(template: string): Promise { hsYaml = hsYaml.replace(/{{MACAROON_SECRET_KEY}}/g, macaroonSecret); hsYaml = hsYaml.replace(/{{FORM_SECRET}}/g, formSecret); hsYaml = hsYaml.replace(/{{PUBLIC_BASEURL}}/g, baseUrl); + const dexUrl = `http://${env["DEX_IP_ADDRESS"]}:${env["DEX_PORT"]}/dex`; + hsYaml = hsYaml.replace(/{{OIDC_ISSUER}}/g, dexUrl); await fse.writeFile(path.join(tempDir, "homeserver.yaml"), hsYaml); // now generate a signing key (we could use synapse's config generation for @@ -85,6 +90,7 @@ async function cfgDirFromTemplate(template: string): Promise { return { port, + host, baseUrl, configDir: tempDir, registrationSecret, @@ -96,17 +102,24 @@ async function cfgDirFromTemplate(template: string): Promise { // directory async function synapseStart(template: string): Promise { const synCfg = await cfgDirFromTemplate(template); - console.log(`Starting synapse with config dir ${synCfg.configDir}...`); - + await dockerCreateNetwork({ networkName: "hydrogen" }); const synapseId = await dockerRun({ image: "matrixdotorg/synapse:develop", containerName: `react-sdk-cypress-synapse-${crypto.randomBytes(4).toString("hex")}`, - params: [ + dockerParams: [ "--rm", "-v", `${synCfg.configDir}:/data`, + `--ip=${synCfg.host}`, + /** + * When using -p flag with --ip, the docker internal port must be used to access from the host + */ "-p", `${synCfg.port}:8008/tcp`, + "--network=hydrogen", ], + applicationParams: [ + "run" + ] }); console.log(`Started synapse with id ${synapseId} on port ${synCfg.port}.`); @@ -162,6 +175,9 @@ async function synapseStop(id: string): Promise { * @type {Cypress.PluginConfig} */ export function synapseDocker(on: PluginEvents, config: PluginConfigOptions) { + env = config.env; + + on("task", { synapseStart, synapseStop, From 66532a9693110fc4596787fc293129dbcefd3770 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 6 Sep 2022 01:38:46 +0530 Subject: [PATCH 12/20] Add sso template --- .../templates/sso/homeserver.yaml | 89 +++++++++++++++++++ .../synapsedocker/templates/sso/log.config | 50 +++++++++++ 2 files changed, 139 insertions(+) create mode 100644 cypress/plugins/synapsedocker/templates/sso/homeserver.yaml create mode 100644 cypress/plugins/synapsedocker/templates/sso/log.config diff --git a/cypress/plugins/synapsedocker/templates/sso/homeserver.yaml b/cypress/plugins/synapsedocker/templates/sso/homeserver.yaml new file mode 100644 index 00000000..10246f5c --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/sso/homeserver.yaml @@ -0,0 +1,89 @@ +server_name: "localhost" +pid_file: /data/homeserver.pid +public_baseurl: "{{PUBLIC_BASEURL}}" +listeners: + - port: 8008 + tls: false + bind_addresses: ['::'] + type: http + x_forwarded: true + + resources: + - names: [client] + compress: false + +database: + name: "sqlite3" + args: + database: ":memory:" + +log_config: "/data/log.config" + +rc_messages_per_second: 10000 +rc_message_burst_count: 10000 +rc_registration: + per_second: 10000 + burst_count: 10000 +rc_joins: + local: + per_second: 9999 + burst_count: 9999 + remote: + per_second: 9999 + burst_count: 9999 +rc_joins_per_room: + per_second: 9999 + burst_count: 9999 +rc_3pid_validation: + per_second: 1000 + burst_count: 1000 + +rc_invites: + per_room: + per_second: 1000 + burst_count: 1000 + per_user: + per_second: 1000 + burst_count: 1000 + +rc_login: + address: + per_second: 10000 + burst_count: 10000 + account: + per_second: 10000 + burst_count: 10000 + failed_attempts: + per_second: 10000 + burst_count: 10000 + +media_store_path: "/data/media_store" +uploads_path: "/data/uploads" +enable_registration: true +enable_registration_without_verification: true +disable_msisdn_registration: false +registration_shared_secret: "{{REGISTRATION_SECRET}}" +report_stats: false +macaroon_secret_key: "{{MACAROON_SECRET_KEY}}" +form_secret: "{{FORM_SECRET}}" +signing_key_path: "/data/localhost.signing.key" + +trusted_key_servers: + - server_name: "matrix.org" +suppress_key_server_warning: true + +ui_auth: + session_timeout: "300s" + +oidc_providers: + - idp_id: dex + idp_name: "My Dex server" + skip_verification: true # This is needed as Dex is served on an insecure endpoint + issuer: "{{OIDC_ISSUER}}" + client_id: "synapse" + client_secret: "secret" + scopes: ["openid", "profile"] + user_mapping_provider: + config: + localpart_template: "{{ user.name }}" + display_name_template: "{{ user.name|capitalize }}" diff --git a/cypress/plugins/synapsedocker/templates/sso/log.config b/cypress/plugins/synapsedocker/templates/sso/log.config new file mode 100644 index 00000000..b9123d0f --- /dev/null +++ b/cypress/plugins/synapsedocker/templates/sso/log.config @@ -0,0 +1,50 @@ +# Log configuration for Synapse. +# +# This is a YAML file containing a standard Python logging configuration +# dictionary. See [1] for details on the valid settings. +# +# Synapse also supports structured logging for machine readable logs which can +# be ingested by ELK stacks. See [2] for details. +# +# [1]: https://docs.python.org/3.7/library/logging.config.html#configuration-dictionary-schema +# [2]: https://matrix-org.github.io/synapse/latest/structured_logging.html + +version: 1 + +formatters: + precise: + format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' + +handlers: + # A handler that writes logs to stderr. Unused by default, but can be used + # instead of "buffer" and "file" in the logger handlers. + console: + class: logging.StreamHandler + formatter: precise + +loggers: + synapse.storage.SQL: + # beware: increasing this to DEBUG will make synapse log sensitive + # information such as access tokens. + level: DEBUG + + twisted: + # We send the twisted logging directly to the file handler, + # to work around https://github.com/matrix-org/synapse/issues/3471 + # when using "buffer" logger. Use "console" to log to stderr instead. + handlers: [console] + propagate: false + +root: + level: DEBUG + + # Write logs to the `buffer` handler, which will buffer them together in memory, + # then write them to a file. + # + # Replace "buffer" with "console" to log to stderr instead. (Note that you'll + # also need to update the configuration for the `twisted` logger above, in + # this case.) + # + handlers: [console] + +disable_existing_loggers: false From 9be9d85d5d48df586398c4efcdc1ce42756e6af9 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 6 Sep 2022 01:39:17 +0530 Subject: [PATCH 13/20] Write test for SSO --- cypress/e2e/login.cy.ts | 52 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/cypress/e2e/login.cy.ts b/cypress/e2e/login.cy.ts index 36badebf..5ec34749 100644 --- a/cypress/e2e/login.cy.ts +++ b/cypress/e2e/login.cy.ts @@ -13,17 +13,27 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +import type { DexInstance } from "../plugins/dex"; import type { SynapseInstance } from "../plugins/synapsedocker"; describe("Login", () => { let synapse: SynapseInstance; + let dex: DexInstance; beforeEach(() => { - cy.startSynapse("consent").then((data) => { - synapse = data; + cy.startDex().then((data) => { + dex = data; + cy.startSynapse("sso").then((data) => { + synapse = data; + }); }); }); + afterEach(() => { + cy.stopSynapse(synapse); + cy.stopDex(dex); + }) + it("Login using username/password", () => { const username = "foobaraccount"; const password = "password123"; @@ -35,5 +45,43 @@ describe("Login", () => { cy.contains("Log In").click(); cy.get(".SessionView"); }); + + it.only("Login using SSO", () => { + /** + * Add the homeserver to the localStorage manually; clicking on the start sso button would normally do this but we can't + * use two different origins in a single cypress test! + */ + cy.visit("/"); + cy.window().then(win => win.localStorage.setItem("hydrogen_setting_v1_sso_ongoing_login_homeserver", synapse.baseUrl)); + // Perform the SSO login manually using requests + const synapseAddress = synapse.baseUrl; + const dexAddress = dex.baseUrl; + // const dexAddress = `${Cypress.env("DEX_IP_ADDRESS")}:${Cypress.env("DEX_PORT")}`; + const redirectAddress = Cypress.config().baseUrl; + const ssoLoginUrl = `${synapseAddress}/_matrix/client/r0/login/sso/redirect?redirectUrl=${encodeURIComponent(redirectAddress)}`; + cy.request(ssoLoginUrl).then(response => { + // Request the Dex page + const dexPageHtml = response.body; + const loginWithExampleLink = Cypress.$(dexPageHtml).find(`a:contains("Log in with Example")`).attr("href"); + cy.log("Login with example link", loginWithExampleLink); + + // Proceed to next page + cy.request(`${dexAddress}${loginWithExampleLink}`).then(response => { + const secondDexPageHtml = response.body; + // This req token is used to approve this login in Dex + const req = Cypress.$(secondDexPageHtml).find(`input[name=req]`).attr("value"); + cy.log("req for sso login", req); + + // Next request will redirect us back to Synapse page with "Continue" link + cy.request("POST", `${dexAddress}/dex/approval?req=${req}&approval=approve`).then(response => { + const synapseHtml = response.body; + const hydrogenLinkWithToken = Cypress.$(synapseHtml).find(`a:contains("Continue")`).attr("href"); + cy.log("SSO redirect link", hydrogenLinkWithToken); + cy.visit(hydrogenLinkWithToken); + cy.get(".SessionView"); + }); + }); + }); + }) }); From a10025ddb2a023143d319dd660089f163861947d Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 6 Sep 2022 01:41:39 +0530 Subject: [PATCH 14/20] Run both tests --- cypress/e2e/login.cy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/e2e/login.cy.ts b/cypress/e2e/login.cy.ts index 5ec34749..969c1884 100644 --- a/cypress/e2e/login.cy.ts +++ b/cypress/e2e/login.cy.ts @@ -46,7 +46,7 @@ describe("Login", () => { cy.get(".SessionView"); }); - it.only("Login using SSO", () => { + it("Login using SSO", () => { /** * Add the homeserver to the localStorage manually; clicking on the start sso button would normally do this but we can't * use two different origins in a single cypress test! From 3ee26e14d74a915578048b233368a056cef84477 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 18 Oct 2022 23:44:58 +0530 Subject: [PATCH 15/20] Convert Cypress --> Playwright --- .gitignore | 3 +- cypress.config.ts | 17 --- cypress/e2e/login.cy.ts | 87 ------------- cypress/plugins/index.ts | 38 ------ cypress/plugins/log.ts | 35 ----- cypress/plugins/performance.ts | 47 ------- cypress/plugins/webserver.ts | 52 -------- cypress/support/dex.ts | 51 -------- cypress/support/synapse.ts | 122 ------------------ cypress/tsconfig.json | 9 -- package.json | 3 +- playwright.config.ts | 16 +++ .../global-setup.ts | 18 ++- {cypress => playwright}/plugins/dex/index.ts | 46 ++----- .../plugins/dex/template/config.yaml | 0 .../plugins/dex/template/dev.db | Bin .../plugins/docker/index.ts | 23 +--- .../plugins/synapsedocker/index.ts | 88 ++++++------- .../synapsedocker/templates/COPYME/README.md | 0 .../templates/COPYME/homeserver.yaml | 0 .../synapsedocker/templates/COPYME/log.config | 0 .../synapsedocker/templates/consent/README.md | 0 .../templates/consent/homeserver.yaml | 0 .../templates/consent/log.config | 0 .../consent/res/templates/privacy/en/1.0.html | 0 .../res/templates/privacy/en/success.html | 0 .../synapsedocker/templates/default/README.md | 0 .../templates/default/homeserver.yaml | 0 .../templates/default/log.config | 0 .../templates/sso/homeserver.yaml | 0 .../synapsedocker/templates/sso/log.config | 0 playwright/tests/login.spec.ts | 59 +++++++++ .../tests/startup.spec.ts | 9 +- yarn.lock | 13 ++ 34 files changed, 164 insertions(+), 572 deletions(-) delete mode 100644 cypress.config.ts delete mode 100644 cypress/e2e/login.cy.ts delete mode 100644 cypress/plugins/index.ts delete mode 100644 cypress/plugins/log.ts delete mode 100644 cypress/plugins/performance.ts delete mode 100644 cypress/plugins/webserver.ts delete mode 100644 cypress/support/dex.ts delete mode 100644 cypress/support/synapse.ts delete mode 100644 cypress/tsconfig.json create mode 100644 playwright.config.ts rename cypress/e2e/startup.cy.ts => playwright/global-setup.ts (66%) rename {cypress => playwright}/plugins/dex/index.ts (74%) rename {cypress => playwright}/plugins/dex/template/config.yaml (100%) rename {cypress => playwright}/plugins/dex/template/dev.db (100%) rename {cypress => playwright}/plugins/docker/index.ts (88%) rename {cypress => playwright}/plugins/synapsedocker/index.ts (74%) rename {cypress => playwright}/plugins/synapsedocker/templates/COPYME/README.md (100%) rename {cypress => playwright}/plugins/synapsedocker/templates/COPYME/homeserver.yaml (100%) rename {cypress => playwright}/plugins/synapsedocker/templates/COPYME/log.config (100%) rename {cypress => playwright}/plugins/synapsedocker/templates/consent/README.md (100%) rename {cypress => playwright}/plugins/synapsedocker/templates/consent/homeserver.yaml (100%) rename {cypress => playwright}/plugins/synapsedocker/templates/consent/log.config (100%) rename {cypress => playwright}/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html (100%) rename {cypress => playwright}/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html (100%) rename {cypress => playwright}/plugins/synapsedocker/templates/default/README.md (100%) rename {cypress => playwright}/plugins/synapsedocker/templates/default/homeserver.yaml (100%) rename {cypress => playwright}/plugins/synapsedocker/templates/default/log.config (100%) rename {cypress => playwright}/plugins/synapsedocker/templates/sso/homeserver.yaml (100%) rename {cypress => playwright}/plugins/synapsedocker/templates/sso/log.config (100%) create mode 100644 playwright/tests/login.spec.ts rename cypress/support/e2e.ts => playwright/tests/startup.spec.ts (73%) diff --git a/.gitignore b/.gitignore index 20f09f19..ef4f67ca 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,4 @@ lib *.tar.gz .eslintcache .tmp -cypress/videos -cypress/synapselogs +playwright/synapselogs diff --git a/cypress.config.ts b/cypress.config.ts deleted file mode 100644 index 02f39392..00000000 --- a/cypress.config.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { defineConfig } from "cypress"; - -export default defineConfig({ - e2e: { - setupNodeEvents(on, config) { - require("./cypress/plugins/index.ts").default(on, config); - return config; - }, - baseUrl: "http://127.0.0.1:3000", - }, - env: { - SYNAPSE_IP_ADDRESS: "172.18.0.5", - SYNAPSE_PORT: "8008", - DEX_IP_ADDRESS: "172.18.0.4", - DEX_PORT: "5556", - }, -}); diff --git a/cypress/e2e/login.cy.ts b/cypress/e2e/login.cy.ts deleted file mode 100644 index 969c1884..00000000 --- a/cypress/e2e/login.cy.ts +++ /dev/null @@ -1,87 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -import type { DexInstance } from "../plugins/dex"; -import type { SynapseInstance } from "../plugins/synapsedocker"; - -describe("Login", () => { - let synapse: SynapseInstance; - let dex: DexInstance; - - beforeEach(() => { - cy.startDex().then((data) => { - dex = data; - cy.startSynapse("sso").then((data) => { - synapse = data; - }); - }); - }); - - afterEach(() => { - cy.stopSynapse(synapse); - cy.stopDex(dex); - }) - - it("Login using username/password", () => { - const username = "foobaraccount"; - const password = "password123"; - cy.registerUser(synapse, username, password); - cy.visit("/"); - cy.get("#homeserver").clear().type(synapse.baseUrl); - cy.get("#username").clear().type(username); - cy.get("#password").clear().type(password); - cy.contains("Log In").click(); - cy.get(".SessionView"); - }); - - it("Login using SSO", () => { - /** - * Add the homeserver to the localStorage manually; clicking on the start sso button would normally do this but we can't - * use two different origins in a single cypress test! - */ - cy.visit("/"); - cy.window().then(win => win.localStorage.setItem("hydrogen_setting_v1_sso_ongoing_login_homeserver", synapse.baseUrl)); - // Perform the SSO login manually using requests - const synapseAddress = synapse.baseUrl; - const dexAddress = dex.baseUrl; - // const dexAddress = `${Cypress.env("DEX_IP_ADDRESS")}:${Cypress.env("DEX_PORT")}`; - const redirectAddress = Cypress.config().baseUrl; - const ssoLoginUrl = `${synapseAddress}/_matrix/client/r0/login/sso/redirect?redirectUrl=${encodeURIComponent(redirectAddress)}`; - cy.request(ssoLoginUrl).then(response => { - // Request the Dex page - const dexPageHtml = response.body; - const loginWithExampleLink = Cypress.$(dexPageHtml).find(`a:contains("Log in with Example")`).attr("href"); - cy.log("Login with example link", loginWithExampleLink); - - // Proceed to next page - cy.request(`${dexAddress}${loginWithExampleLink}`).then(response => { - const secondDexPageHtml = response.body; - // This req token is used to approve this login in Dex - const req = Cypress.$(secondDexPageHtml).find(`input[name=req]`).attr("value"); - cy.log("req for sso login", req); - - // Next request will redirect us back to Synapse page with "Continue" link - cy.request("POST", `${dexAddress}/dex/approval?req=${req}&approval=approve`).then(response => { - const synapseHtml = response.body; - const hydrogenLinkWithToken = Cypress.$(synapseHtml).find(`a:contains("Continue")`).attr("href"); - cy.log("SSO redirect link", hydrogenLinkWithToken); - cy.visit(hydrogenLinkWithToken); - cy.get(".SessionView"); - }); - }); - }); - }) -}); - diff --git a/cypress/plugins/index.ts b/cypress/plugins/index.ts deleted file mode 100644 index 27c8b9a3..00000000 --- a/cypress/plugins/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -/// - -import PluginEvents = Cypress.PluginEvents; -import PluginConfigOptions = Cypress.PluginConfigOptions; -import { performance } from "./performance"; -import { synapseDocker } from "./synapsedocker"; -import { dexDocker } from "./dex"; -import { webserver } from "./webserver"; -import { docker } from "./docker"; -import { log } from "./log"; - -/** - * @type {Cypress.PluginConfig} - */ -export default function(on: PluginEvents, config: PluginConfigOptions) { - docker(on, config); - performance(on, config); - synapseDocker(on, config); - dexDocker(on, config); - webserver(on, config); - log(on, config); -} diff --git a/cypress/plugins/log.ts b/cypress/plugins/log.ts deleted file mode 100644 index 4b16c9b8..00000000 --- a/cypress/plugins/log.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -/// - -import PluginEvents = Cypress.PluginEvents; -import PluginConfigOptions = Cypress.PluginConfigOptions; - -export function log(on: PluginEvents, config: PluginConfigOptions) { - on("task", { - log(message: string) { - console.log(message); - - return null; - }, - table(message: string) { - console.table(message); - - return null; - }, - }); -} diff --git a/cypress/plugins/performance.ts b/cypress/plugins/performance.ts deleted file mode 100644 index c6bd3e4c..00000000 --- a/cypress/plugins/performance.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -/// - -import * as path from "path"; -import * as fse from "fs-extra"; - -import PluginEvents = Cypress.PluginEvents; -import PluginConfigOptions = Cypress.PluginConfigOptions; - -// This holds all the performance measurements throughout the run -let bufferedMeasurements: PerformanceEntry[] = []; - -function addMeasurements(measurements: PerformanceEntry[]): void { - bufferedMeasurements = bufferedMeasurements.concat(measurements); - return null; -} - -async function writeMeasurementsFile() { - try { - const measurementsPath = path.join("cypress", "performance", "measurements.json"); - await fse.outputJSON(measurementsPath, bufferedMeasurements, { - spaces: 4, - }); - } finally { - bufferedMeasurements = []; - } -} - -export function performance(on: PluginEvents, config: PluginConfigOptions) { - on("task", { addMeasurements }); - on("after:run", writeMeasurementsFile); -} diff --git a/cypress/plugins/webserver.ts b/cypress/plugins/webserver.ts deleted file mode 100644 index 55a25a31..00000000 --- a/cypress/plugins/webserver.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -/// - -import * as http from "http"; -import { AddressInfo } from "net"; - -import PluginEvents = Cypress.PluginEvents; -import PluginConfigOptions = Cypress.PluginConfigOptions; - -const servers: http.Server[] = []; - -function serveHtmlFile(html: string): string { - const server = http.createServer((req, res) => { - res.writeHead(200, { - "Content-Type": "text/html", - }); - res.end(html); - }); - server.listen(); - servers.push(server); - - return `http://localhost:${(server.address() as AddressInfo).port}/`; -} - -function stopWebServers(): null { - for (const server of servers) { - server.close(); - } - servers.splice(0, servers.length); // clear - - return null; // tell cypress we did the task successfully (doesn't allow undefined) -} - -export function webserver(on: PluginEvents, config: PluginConfigOptions) { - on("task", { serveHtmlFile, stopWebServers }); - on("after:run", stopWebServers); -} diff --git a/cypress/support/dex.ts b/cypress/support/dex.ts deleted file mode 100644 index 599eee26..00000000 --- a/cypress/support/dex.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -/// - -import Chainable = Cypress.Chainable; -import AUTWindow = Cypress.AUTWindow; -import { DexInstance } from "../plugins/dex"; - -declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace Cypress { - interface Chainable { - /** - * Start the dex server - */ - startDex(): Chainable; - - /** - * Stop the dex server - * @param dex the dex instance returned by startSynapse - */ - stopDex(dex: DexInstance): Chainable; - } - } -} - -function startDex(): Chainable { - return cy.task("dexStart"); -} - -function stopDex(dex?: DexInstance): Chainable { - if (!dex) return; - cy.task("dexStop", dex.dexId); -} - -Cypress.Commands.add("startDex", startDex); -Cypress.Commands.add("stopDex", stopDex); diff --git a/cypress/support/synapse.ts b/cypress/support/synapse.ts deleted file mode 100644 index 5696e8c0..00000000 --- a/cypress/support/synapse.ts +++ /dev/null @@ -1,122 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -/// - -import * as crypto from 'crypto'; - -import Chainable = Cypress.Chainable; -import AUTWindow = Cypress.AUTWindow; -import { SynapseInstance } from "../plugins/synapsedocker"; - -declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace Cypress { - interface Chainable { - /** - * Start a synapse instance with a given config template. - * @param template path to template within cypress/plugins/synapsedocker/template/ directory. - */ - startSynapse(template: string): Chainable; - - /** - * Custom command wrapping task:synapseStop whilst preventing uncaught exceptions - * for if Synapse stopping races with the app's background sync loop. - * @param synapse the synapse instance returned by startSynapse - */ - stopSynapse(synapse: SynapseInstance): Chainable; - - /** - * Register a user on the given Synapse using the shared registration secret. - * @param synapse the synapse instance returned by startSynapse - * @param username the username of the user to register - * @param password the password of the user to register - * @param displayName optional display name to set on the newly registered user - */ - registerUser( - synapse: SynapseInstance, - username: string, - password: string, - displayName?: string, - ): Chainable; - } - } -} - -function startSynapse(template: string): Chainable { - return cy.task("synapseStart", template); -} - -function stopSynapse(synapse?: SynapseInstance): Chainable { - if (!synapse) return; - // Navigate away from app to stop the background network requests which will race with Synapse shutting down - return cy.window({ log: false }).then((win) => { - win.location.href = 'about:blank'; - cy.task("synapseStop", synapse.synapseId); - }); -} - -interface Credentials { - accessToken: string; - userId: string; - deviceId: string; - homeServer: string; -} - -function registerUser( - synapse: SynapseInstance, - username: string, - password: string, - displayName?: string, -): Chainable { - const url = `${synapse.baseUrl}/_synapse/admin/v1/register`; - return cy.then(() => { - // get a nonce - return cy.request<{ nonce: string }>({ url }); - }).then(response => { - const { nonce } = response.body; - const mac = crypto.createHmac('sha1', synapse.registrationSecret).update( - `${nonce}\0${username}\0${password}\0notadmin`, - ).digest('hex'); - - return cy.request<{ - access_token: string; - user_id: string; - home_server: string; - device_id: string; - }>({ - url, - method: "POST", - body: { - nonce, - username, - password, - mac, - admin: false, - displayname: displayName, - }, - }); - }).then(response => ({ - homeServer: response.body.home_server, - accessToken: response.body.access_token, - userId: response.body.user_id, - deviceId: response.body.device_id, - })); -} - -Cypress.Commands.add("startSynapse", startSynapse); -Cypress.Commands.add("stopSynapse", stopSynapse); -Cypress.Commands.add("registerUser", registerUser); diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json deleted file mode 100644 index 6bd44918..00000000 --- a/cypress/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "compilerOptions": { - "downlevelIteration": true, - "target": "es5", - "lib": ["es5", "dom"], - "types": ["cypress", "node"] - }, - "include": ["**/*.ts"] -} diff --git a/package.json b/package.json index fbba3b2e..569354f0 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "build": "vite build && ./scripts/cleanup.sh", "build:sdk": "./scripts/sdk/build.sh", "watch:sdk": "./scripts/sdk/build.sh && yarn run vite build -c vite.sdk-lib-config.js --watch", - "test:app": "vite --port 3000 & yarn run cypress open" + "test:app": "vite --port 3000 & playwright test" }, "repository": { "type": "git", @@ -32,6 +32,7 @@ }, "homepage": "https://github.com/vector-im/hydrogen-web/#readme", "devDependencies": { + "@playwright/test": "^1.27.1", "@typescript-eslint/eslint-plugin": "^4.29.2", "@typescript-eslint/parser": "^4.29.2", "acorn": "^8.6.0", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 00000000..901e48d9 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,16 @@ +import type { PlaywrightTestConfig } from '@playwright/test'; + +const BASE_URL = process.env["BASE_URL"] ?? "http://127.0.0.1:3000"; + +const config: PlaywrightTestConfig = { + use: { + headless: false, + viewport: { width: 1280, height: 720 }, + ignoreHTTPSErrors: true, + video: 'on-first-retry', + baseURL: BASE_URL, + }, + testDir: "./playwright/tests", + globalSetup: require.resolve("./playwright/global-setup"), +}; +export default config; diff --git a/cypress/e2e/startup.cy.ts b/playwright/global-setup.ts similarity index 66% rename from cypress/e2e/startup.cy.ts rename to playwright/global-setup.ts index e7bf9c2c..5944e55c 100644 --- a/cypress/e2e/startup.cy.ts +++ b/playwright/global-setup.ts @@ -14,9 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -describe("App has no startup errors that prevent UI render", () => { - it("passes", () => { - cy.visit("/"); - cy.contains("Log In"); - }) -}) +const env = { + SYNAPSE_IP_ADDRESS: "172.18.0.5", + SYNAPSE_PORT: "8008", + DEX_IP_ADDRESS: "172.18.0.4", + DEX_PORT: "5556", +} + +export default function setupEnvironmentVariables() { + for (const [key, value] of Object.entries(env)) { + process.env[key] = value; + } +} diff --git a/cypress/plugins/dex/index.ts b/playwright/plugins/dex/index.ts similarity index 74% rename from cypress/plugins/dex/index.ts rename to playwright/plugins/dex/index.ts index b07a78e8..56605cf5 100644 --- a/cypress/plugins/dex/index.ts +++ b/playwright/plugins/dex/index.ts @@ -20,8 +20,6 @@ import * as path from "path"; import * as os from "os"; import * as fse from "fs-extra"; -import PluginEvents = Cypress.PluginEvents; -import PluginConfigOptions = Cypress.PluginConfigOptions; import {dockerRun, dockerStop } from "../docker"; // A cypress plugins to add command to start & stop dex instances @@ -38,7 +36,6 @@ export interface DexInstance extends DexConfig { } const dexConfigs = new Map(); -let env; async function produceConfigWithSynapseURLAdded(): Promise { const templateDir = path.join(__dirname, "template"); @@ -56,24 +53,26 @@ async function produceConfigWithSynapseURLAdded(): Promise { // now copy config.yaml, applying substitutions console.log(`Gen ${path.join(templateDir, "config.yaml")}`); let hsYaml = await fse.readFile(path.join(templateDir, "config.yaml"), "utf8"); - const synapseAddress = `${env.SYNAPSE_IP_ADDRESS}:${env.SYNAPSE_PORT}`; + const synapseHost = process.env.SYNAPSE_IP_ADDRESS; + const synapsePort = process.env.SYNAPSE_PORT; + const synapseAddress = `${synapseHost}:${synapsePort}`; hsYaml = hsYaml.replace(/{{SYNAPSE_ADDRESS}}/g, synapseAddress); - const host = env.DEX_IP_ADDRESS; - const port = env.DEX_PORT; - const dexAddress = `${host}:${port}`; + const dexHost = process.env.DEX_IP_ADDRESS!; + const dexPort = parseInt(process.env.DEX_PORT!, 10); + const dexAddress = `${dexHost}:${dexPort}`; hsYaml = hsYaml.replace(/{{DEX_ADDRESS}}/g, dexAddress); await fse.writeFile(path.join(tempDir, "config.yaml"), hsYaml); - const baseUrl = `http://${host}:${port}`; + const baseUrl = `http://${dexHost}:${dexPort}`; return { - host, - port, + host: dexHost, + port: dexPort, baseUrl, configDir: tempDir, }; } -async function dexStart(): Promise { +export async function dexStart(): Promise { const dexCfg = await produceConfigWithSynapseURLAdded(); console.log(`Starting dex with config dir ${dexCfg.configDir}...`); const dexId = await dockerRun({ @@ -99,34 +98,11 @@ async function dexStart(): Promise { return dex; } -async function dexStop(id: string): Promise { +export async function dexStop(id: string): Promise { const dexCfg = dexConfigs.get(id); if (!dexCfg) throw new Error("Unknown dex ID"); await dockerStop({ containerId: id, }); await fse.remove(dexCfg.configDir); dexConfigs.delete(id); console.log(`Stopped dex id ${id}.`); - // cypress deliberately fails if you return 'undefined', so - // return null to signal all is well, and we've handled the task. - return null; } - -/** - * @type {Cypress.PluginConfig} - */ -export function dexDocker(on: PluginEvents, config: PluginConfigOptions) { - env = config.env; - - on("task", { - dexStart, - dexStop, - }); - - on("after:spec", async (spec) => { - for (const dexId of dexConfigs.keys()) { - console.warn(`Cleaning up dex ID ${dexId} after ${spec.name}`); - await dexStop(dexId); - } - }); -} - diff --git a/cypress/plugins/dex/template/config.yaml b/playwright/plugins/dex/template/config.yaml similarity index 100% rename from cypress/plugins/dex/template/config.yaml rename to playwright/plugins/dex/template/config.yaml diff --git a/cypress/plugins/dex/template/dev.db b/playwright/plugins/dex/template/dev.db similarity index 100% rename from cypress/plugins/dex/template/dev.db rename to playwright/plugins/dex/template/dev.db diff --git a/cypress/plugins/docker/index.ts b/playwright/plugins/docker/index.ts similarity index 88% rename from cypress/plugins/docker/index.ts rename to playwright/plugins/docker/index.ts index a55f341e..b0080d6c 100644 --- a/cypress/plugins/docker/index.ts +++ b/playwright/plugins/docker/index.ts @@ -20,11 +20,6 @@ import * as os from "os"; import * as childProcess from "child_process"; import * as fse from "fs-extra"; -import PluginEvents = Cypress.PluginEvents; -import PluginConfigOptions = Cypress.PluginConfigOptions; - -// A cypress plugin to run docker commands - export function dockerRun(args: { image: string; containerName: string; @@ -48,8 +43,7 @@ export function dockerRun(args: { ...params, args.image, ... appParams - ], (err, stdout, stderr) => { - console.log("error", err, "stdout", stdout, "stderr", stderr); + ], (err, stdout) => { if (err) { reject(err); } @@ -155,18 +149,3 @@ export function dockerRm(args: { }); }); } - -/** - * @type {Cypress.PluginConfig} - */ -export function docker(on: PluginEvents, config: PluginConfigOptions) { - console.log("Code gets to here!"); - on("task", { - dockerRun, - dockerExec, - dockerLogs, - dockerStop, - dockerRm, - dockerCreateNetwork - }); -} diff --git a/cypress/plugins/synapsedocker/index.ts b/playwright/plugins/synapsedocker/index.ts similarity index 74% rename from cypress/plugins/synapsedocker/index.ts rename to playwright/plugins/synapsedocker/index.ts index 268f7320..1917aa85 100644 --- a/cypress/plugins/synapsedocker/index.ts +++ b/playwright/plugins/synapsedocker/index.ts @@ -21,9 +21,8 @@ import * as os from "os"; import * as crypto from "crypto"; import * as fse from "fs-extra"; -import PluginEvents = Cypress.PluginEvents; -import PluginConfigOptions = Cypress.PluginConfigOptions; import { dockerCreateNetwork, dockerExec, dockerLogs, dockerRun, dockerStop } from "../docker"; +import { request } from "@playwright/test"; // A cypress plugins to add command to start & stop synapses in @@ -43,7 +42,6 @@ export interface SynapseInstance extends SynapseConfig { } const synapses = new Map(); -let env; function randB64Bytes(numBytes: number): string { return crypto.randomBytes(numBytes).toString("base64").replace(/=*$/, ""); @@ -56,7 +54,7 @@ async function cfgDirFromTemplate(template: string): Promise { if (!stats?.isDirectory) { throw new Error(`No such template: ${template}`); } - const tempDir = await fse.mkdtemp(path.join(os.tmpdir(), 'react-sdk-synapsedocker-')); + const tempDir = await fse.mkdtemp(path.join(os.tmpdir(), 'synapsedocker-')); // copy the contents of the template dir, omitting homeserver.yaml as we'll template that console.log(`Copy ${templateDir} -> ${tempDir}`); @@ -66,9 +64,10 @@ async function cfgDirFromTemplate(template: string): Promise { const macaroonSecret = randB64Bytes(16); const formSecret = randB64Bytes(16); - const host = env["SYNAPSE_IP_ADDRESS"]; - const port = parseInt(env["SYNAPSE_PORT"], 10); - const baseUrl = `http://${host}:${port}`; + const synapseHost = process.env["SYNAPSE_IP_ADDRESS"]!!; + const synapsePort = parseInt(process.env["SYNAPSE_PORT"]!, 10); + const baseUrl = `http://${synapseHost}:${synapsePort}`; + // now copy homeserver.yaml, applying substitutions console.log(`Gen ${path.join(templateDir, "homeserver.yaml")}`); @@ -77,7 +76,10 @@ async function cfgDirFromTemplate(template: string): Promise { hsYaml = hsYaml.replace(/{{MACAROON_SECRET_KEY}}/g, macaroonSecret); hsYaml = hsYaml.replace(/{{FORM_SECRET}}/g, formSecret); hsYaml = hsYaml.replace(/{{PUBLIC_BASEURL}}/g, baseUrl); - const dexUrl = `http://${env["DEX_IP_ADDRESS"]}:${env["DEX_PORT"]}/dex`; + + const dexHost = process.env["DEX_IP_ADDRESS"]; + const dexPort = process.env["DEX_PORT"]; + const dexUrl = `http://${dexHost}:${dexPort}/dex`; hsYaml = hsYaml.replace(/{{OIDC_ISSUER}}/g, dexUrl); await fse.writeFile(path.join(tempDir, "homeserver.yaml"), hsYaml); @@ -89,8 +91,8 @@ async function cfgDirFromTemplate(template: string): Promise { await fse.writeFile(path.join(tempDir, "localhost.signing.key"), `ed25519 x ${signingKey}`); return { - port, - host, + port: synapsePort, + host: synapseHost, baseUrl, configDir: tempDir, registrationSecret, @@ -100,7 +102,7 @@ async function cfgDirFromTemplate(template: string): Promise { // Start a synapse instance: the template must be the name of // one of the templates in the cypress/plugins/synapsedocker/templates // directory -async function synapseStart(template: string): Promise { +export async function synapseStart(template: string): Promise { const synCfg = await cfgDirFromTemplate(template); console.log(`Starting synapse with config dir ${synCfg.configDir}...`); await dockerCreateNetwork({ networkName: "hydrogen" }); @@ -143,12 +145,12 @@ async function synapseStart(template: string): Promise { return synapse; } -async function synapseStop(id: string): Promise { +export async function synapseStop(id: string): Promise { const synCfg = synapses.get(id); if (!synCfg) throw new Error("Unknown synapse ID"); - const synapseLogsPath = path.join("cypress", "synapselogs", id); + const synapseLogsPath = path.join("playwright", "synapselogs", id); await fse.ensureDir(synapseLogsPath); await dockerLogs({ @@ -162,42 +164,40 @@ async function synapseStop(id: string): Promise { }); await fse.remove(synCfg.configDir); - synapses.delete(id); - console.log(`Stopped synapse id ${id}.`); - // cypress deliberately fails if you return 'undefined', so - // return null to signal all is well, and we've handled the task. - return null; } -/** - * @type {Cypress.PluginConfig} - */ -export function synapseDocker(on: PluginEvents, config: PluginConfigOptions) { - env = config.env; - - on("task", { - synapseStart, - synapseStop, - }); - on("after:spec", async (spec) => { - // Cleans up any remaining synapse instances after a spec run - // This is on the theory that we should avoid re-using synapse - // instances between spec runs: they should be cheap enough to - // start that we can have a separate one for each spec run or even - // test. If we accidentally re-use synapses, we could inadvertently - // make our tests depend on each other. - for (const synId of synapses.keys()) { - console.warn(`Cleaning up synapse ID ${synId} after ${spec.name}`); - await synapseStop(synId); +interface Credentials { + accessToken: string; + userId: string; + deviceId: string; + homeServer: string; +} + +export async function registerUser(synapse: SynapseInstance, username: string, password: string, displayName?: string,): Promise { + const url = `${synapse.baseUrl}/_synapse/admin/v1/register`; + const context = await request.newContext({ baseURL: url }); + const { nonce } = await (await context.get(url)).json(); + const mac = crypto.createHmac('sha1', synapse.registrationSecret).update( + `${nonce}\0${username}\0${password}\0notadmin`, + ).digest('hex'); + const response = await (await context.post(url, { + data: { + nonce, + username, + password, + mac, + admin: false, + displayname: displayName, } - }); - - on("before:run", async () => { - // tidy up old synapse log files before each run - await fse.emptyDir(path.join("cypress", "synapselogs")); - }); + })).json(); + return { + homeServer: response.home_server, + accessToken: response.access_token, + userId: response.user_id, + deviceId: response.device_id, + }; } diff --git a/cypress/plugins/synapsedocker/templates/COPYME/README.md b/playwright/plugins/synapsedocker/templates/COPYME/README.md similarity index 100% rename from cypress/plugins/synapsedocker/templates/COPYME/README.md rename to playwright/plugins/synapsedocker/templates/COPYME/README.md diff --git a/cypress/plugins/synapsedocker/templates/COPYME/homeserver.yaml b/playwright/plugins/synapsedocker/templates/COPYME/homeserver.yaml similarity index 100% rename from cypress/plugins/synapsedocker/templates/COPYME/homeserver.yaml rename to playwright/plugins/synapsedocker/templates/COPYME/homeserver.yaml diff --git a/cypress/plugins/synapsedocker/templates/COPYME/log.config b/playwright/plugins/synapsedocker/templates/COPYME/log.config similarity index 100% rename from cypress/plugins/synapsedocker/templates/COPYME/log.config rename to playwright/plugins/synapsedocker/templates/COPYME/log.config diff --git a/cypress/plugins/synapsedocker/templates/consent/README.md b/playwright/plugins/synapsedocker/templates/consent/README.md similarity index 100% rename from cypress/plugins/synapsedocker/templates/consent/README.md rename to playwright/plugins/synapsedocker/templates/consent/README.md diff --git a/cypress/plugins/synapsedocker/templates/consent/homeserver.yaml b/playwright/plugins/synapsedocker/templates/consent/homeserver.yaml similarity index 100% rename from cypress/plugins/synapsedocker/templates/consent/homeserver.yaml rename to playwright/plugins/synapsedocker/templates/consent/homeserver.yaml diff --git a/cypress/plugins/synapsedocker/templates/consent/log.config b/playwright/plugins/synapsedocker/templates/consent/log.config similarity index 100% rename from cypress/plugins/synapsedocker/templates/consent/log.config rename to playwright/plugins/synapsedocker/templates/consent/log.config diff --git a/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html b/playwright/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html similarity index 100% rename from cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html rename to playwright/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html diff --git a/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html b/playwright/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html similarity index 100% rename from cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html rename to playwright/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html diff --git a/cypress/plugins/synapsedocker/templates/default/README.md b/playwright/plugins/synapsedocker/templates/default/README.md similarity index 100% rename from cypress/plugins/synapsedocker/templates/default/README.md rename to playwright/plugins/synapsedocker/templates/default/README.md diff --git a/cypress/plugins/synapsedocker/templates/default/homeserver.yaml b/playwright/plugins/synapsedocker/templates/default/homeserver.yaml similarity index 100% rename from cypress/plugins/synapsedocker/templates/default/homeserver.yaml rename to playwright/plugins/synapsedocker/templates/default/homeserver.yaml diff --git a/cypress/plugins/synapsedocker/templates/default/log.config b/playwright/plugins/synapsedocker/templates/default/log.config similarity index 100% rename from cypress/plugins/synapsedocker/templates/default/log.config rename to playwright/plugins/synapsedocker/templates/default/log.config diff --git a/cypress/plugins/synapsedocker/templates/sso/homeserver.yaml b/playwright/plugins/synapsedocker/templates/sso/homeserver.yaml similarity index 100% rename from cypress/plugins/synapsedocker/templates/sso/homeserver.yaml rename to playwright/plugins/synapsedocker/templates/sso/homeserver.yaml diff --git a/cypress/plugins/synapsedocker/templates/sso/log.config b/playwright/plugins/synapsedocker/templates/sso/log.config similarity index 100% rename from cypress/plugins/synapsedocker/templates/sso/log.config rename to playwright/plugins/synapsedocker/templates/sso/log.config diff --git a/playwright/tests/login.spec.ts b/playwright/tests/login.spec.ts new file mode 100644 index 00000000..a7684eae --- /dev/null +++ b/playwright/tests/login.spec.ts @@ -0,0 +1,59 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +import { test } from '@playwright/test'; +import { synapseStart, synapseStop, registerUser } from "../plugins/synapsedocker"; +import { dexStart, dexStop } from "../plugins/dex"; +import type { DexInstance } from "../plugins/dex"; +import type { SynapseInstance } from "../plugins/synapsedocker"; + +test.describe("Login", () => { + let synapse: SynapseInstance; + let dex: DexInstance; + + test.beforeEach(async () => { + dex = await dexStart(); + synapse = await synapseStart("sso"); + }); + + test.afterEach(async () => { + await synapseStop(synapse.synapseId); + await dexStop(dex.dexId); + }); + + test("Login using username/password", async ({ page }) => { + const username = "foobaraccount"; + const password = "password123"; + await registerUser(synapse, username, password); + await page.goto("/"); + await page.locator("#homeserver").fill(""); + await page.locator("#homeserver").type(synapse.baseUrl); + await page.locator("#username").type(username); + await page.locator("#password").type(password); + await page.getByText('Log In', { exact: true }).click(); + await page.locator(".SessionView").waitFor(); + }); + + test("Login using SSO", async ({ page }) => { + await page.goto("/"); + await page.locator("#homeserver").fill(""); + await page.locator("#homeserver").type(synapse.baseUrl); + await page.locator(".StartSSOLoginView_button").click(); + await page.getByText("Log in with Example").click(); + await page.locator(".dex-btn-text", {hasText: "Grant Access"}).click(); + await page.locator(".primary-button", {hasText: "Continue"}).click(); + await page.locator(".SessionView").waitFor(); + }); +}); diff --git a/cypress/support/e2e.ts b/playwright/tests/startup.spec.ts similarity index 73% rename from cypress/support/e2e.ts rename to playwright/tests/startup.spec.ts index d186c5a0..0d38218a 100644 --- a/cypress/support/e2e.ts +++ b/playwright/tests/startup.spec.ts @@ -13,8 +13,9 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +import { test } from '@playwright/test'; -/// - -import "./synapse"; -import "./dex"; +test("App has no startup errors that prevent UI render", async ({ page }) => { + await page.goto('/'); + await page.getByText('Log In', { exact: true }).waitFor(); +}); diff --git a/yarn.lock b/yarn.lock index 994657f3..188a5fe1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -114,6 +114,14 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@playwright/test@^1.27.1": + version "1.27.1" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.27.1.tgz#9364d1e02021261211c8ff586d903faa79ce95c4" + integrity sha512-mrL2q0an/7tVqniQQF6RBL2saskjljXzqNcCOVMUjRIgE6Y38nCNaP+Dc2FBW06bcpD3tqIws/HT9qiMHbNU0A== + dependencies: + "@types/node" "*" + playwright-core "1.27.1" + "@trysound/sax@0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" @@ -2040,6 +2048,11 @@ pify@^2.2.0: resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== +playwright-core@1.27.1: + version "1.27.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.27.1.tgz#840ef662e55a3ed759d8b5d3d00a5f885a7184f4" + integrity sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q== + postcss-css-variables@^0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/postcss-css-variables/-/postcss-css-variables-0.18.0.tgz#d97b6da19e86245eb817006e11117382f997bb93" From 097d2296e01d6b1055f1d9a1a2c43c93addb0d02 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 25 Oct 2022 17:02:17 +0530 Subject: [PATCH 16/20] Make testing more reliable - Stop any running containers - Start dev server from playwright so that we don't keep spawning new node instances --- package.json | 2 +- playwright.config.ts | 24 +++++++++++++---------- playwright/plugins/dex/index.ts | 2 +- playwright/plugins/synapsedocker/index.ts | 2 +- scripts/test-app.sh | 19 ++++++++++++++++++ 5 files changed, 36 insertions(+), 13 deletions(-) create mode 100755 scripts/test-app.sh diff --git a/package.json b/package.json index 569354f0..002cc24a 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "build": "vite build && ./scripts/cleanup.sh", "build:sdk": "./scripts/sdk/build.sh", "watch:sdk": "./scripts/sdk/build.sh && yarn run vite build -c vite.sdk-lib-config.js --watch", - "test:app": "vite --port 3000 & playwright test" + "test:app": "./scripts/test-app.sh" }, "repository": { "type": "git", diff --git a/playwright.config.ts b/playwright.config.ts index 901e48d9..6fbb499b 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,16 +1,20 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; +import type { PlaywrightTestConfig } from "@playwright/test"; const BASE_URL = process.env["BASE_URL"] ?? "http://127.0.0.1:3000"; const config: PlaywrightTestConfig = { - use: { - headless: false, - viewport: { width: 1280, height: 720 }, - ignoreHTTPSErrors: true, - video: 'on-first-retry', - baseURL: BASE_URL, - }, - testDir: "./playwright/tests", - globalSetup: require.resolve("./playwright/global-setup"), + use: { + headless: false, + viewport: { width: 1280, height: 720 }, + ignoreHTTPSErrors: true, + video: "on-first-retry", + baseURL: BASE_URL, + }, + testDir: "./playwright/tests", + globalSetup: require.resolve("./playwright/global-setup"), + webServer: { + command: "yarn start", + url: `${BASE_URL}/#/login`, + }, }; export default config; diff --git a/playwright/plugins/dex/index.ts b/playwright/plugins/dex/index.ts index 56605cf5..f45257fc 100644 --- a/playwright/plugins/dex/index.ts +++ b/playwright/plugins/dex/index.ts @@ -77,7 +77,7 @@ export async function dexStart(): Promise { console.log(`Starting dex with config dir ${dexCfg.configDir}...`); const dexId = await dockerRun({ image: "bitnami/dex:latest", - containerName: "dex", + containerName: "hydrogen-dex", dockerParams: [ "--rm", "-v", `${dexCfg.configDir}:/data`, diff --git a/playwright/plugins/synapsedocker/index.ts b/playwright/plugins/synapsedocker/index.ts index 1917aa85..56ffa214 100644 --- a/playwright/plugins/synapsedocker/index.ts +++ b/playwright/plugins/synapsedocker/index.ts @@ -108,7 +108,7 @@ export async function synapseStart(template: string): Promise { await dockerCreateNetwork({ networkName: "hydrogen" }); const synapseId = await dockerRun({ image: "matrixdotorg/synapse:develop", - containerName: `react-sdk-cypress-synapse-${crypto.randomBytes(4).toString("hex")}`, + containerName: `hydrogen-synapse`, dockerParams: [ "--rm", "-v", `${synCfg.configDir}:/data`, diff --git a/scripts/test-app.sh b/scripts/test-app.sh new file mode 100755 index 00000000..cfbd37a3 --- /dev/null +++ b/scripts/test-app.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Make sure docker is available +if ! docker info > /dev/null 2>&1; then + echo "You need to intall docker before you can run the tests!" + exit 1 +fi + +# Stop running containers +if docker stop hydrogen-synapse > /dev/null 2>&1; then + echo "Existing 'hydrogen-synapse' container stopped ✔" +fi + +if docker stop hydrogen-dex > /dev/null 2>&1; then + echo "Existing 'hydrogen-dex' container stopped ✔" +fi + +# Run playwright +yarn playwright test From d810f22237c1d645f01e153c9f926b61406fb43e Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 25 Oct 2022 17:06:39 +0530 Subject: [PATCH 17/20] Remove cypress as dependency --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 002cc24a..20a16a4d 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "aes-js": "^3.1.2", "bs58": "^4.0.1", "core-js": "^3.6.5", - "cypress": "^10.6.0", "es6-promise": "https://github.com/bwindels/es6-promise.git#bwindels/expose-flush", "escodegen": "^2.0.0", "eslint": "^7.32.0", From a3a5d278a043b957ce04f134a3658e0622dcd211 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 25 Oct 2022 21:18:56 +0530 Subject: [PATCH 18/20] Limit workers to 1 for now --- playwright.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/playwright.config.ts b/playwright.config.ts index 6fbb499b..0a00a88f 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -16,5 +16,6 @@ const config: PlaywrightTestConfig = { command: "yarn start", url: `${BASE_URL}/#/login`, }, + workers: 1 }; export default config; From 53c3bf0ab382650f12690653bdaa63f715eba6d9 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 25 Oct 2022 21:20:20 +0530 Subject: [PATCH 19/20] Change quotes --- playwright/tests/startup.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/playwright/tests/startup.spec.ts b/playwright/tests/startup.spec.ts index 0d38218a..5bb7abf0 100644 --- a/playwright/tests/startup.spec.ts +++ b/playwright/tests/startup.spec.ts @@ -16,6 +16,6 @@ limitations under the License. import { test } from '@playwright/test'; test("App has no startup errors that prevent UI render", async ({ page }) => { - await page.goto('/'); - await page.getByText('Log In', { exact: true }).waitFor(); + await page.goto("/"); + await page.getByText("Log In", { exact: true }).waitFor(); }); From a3f70fd29be37f3c5d00174d2dbada5507c6315d Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 25 Oct 2022 21:29:28 +0530 Subject: [PATCH 20/20] Fix formatting --- playwright/plugins/synapsedocker/index.ts | 4 ++-- playwright/tests/login.spec.ts | 10 +++++----- playwright/tests/startup.spec.ts | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/playwright/plugins/synapsedocker/index.ts b/playwright/plugins/synapsedocker/index.ts index 56ffa214..390888cd 100644 --- a/playwright/plugins/synapsedocker/index.ts +++ b/playwright/plugins/synapsedocker/index.ts @@ -21,8 +21,8 @@ import * as os from "os"; import * as crypto from "crypto"; import * as fse from "fs-extra"; -import { dockerCreateNetwork, dockerExec, dockerLogs, dockerRun, dockerStop } from "../docker"; -import { request } from "@playwright/test"; +import {dockerCreateNetwork, dockerExec, dockerLogs, dockerRun, dockerStop} from "../docker"; +import {request} from "@playwright/test"; // A cypress plugins to add command to start & stop synapses in diff --git a/playwright/tests/login.spec.ts b/playwright/tests/login.spec.ts index a7684eae..a5f30476 100644 --- a/playwright/tests/login.spec.ts +++ b/playwright/tests/login.spec.ts @@ -13,11 +13,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import { test } from '@playwright/test'; -import { synapseStart, synapseStop, registerUser } from "../plugins/synapsedocker"; -import { dexStart, dexStop } from "../plugins/dex"; -import type { DexInstance } from "../plugins/dex"; -import type { SynapseInstance } from "../plugins/synapsedocker"; +import {test} from '@playwright/test'; +import {synapseStart, synapseStop, registerUser} from "../plugins/synapsedocker"; +import {dexStart, dexStop} from "../plugins/dex"; +import type {DexInstance} from "../plugins/dex"; +import type {SynapseInstance} from "../plugins/synapsedocker"; test.describe("Login", () => { let synapse: SynapseInstance; diff --git a/playwright/tests/startup.spec.ts b/playwright/tests/startup.spec.ts index 5bb7abf0..562859d7 100644 --- a/playwright/tests/startup.spec.ts +++ b/playwright/tests/startup.spec.ts @@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import { test } from '@playwright/test'; +import {test} from '@playwright/test'; test("App has no startup errors that prevent UI render", async ({ page }) => { await page.goto("/");