From c03b5e5c6879432eaa7dff0910ce1505ac840559 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:50:13 +1300 Subject: [PATCH 01/44] install cypress --- package.json | 1 + yarn.lock | 594 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 577 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 85bb5134..9f70a387 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "devDependencies": { "@nuxt/devtools": "latest", "@zadigetvoltaire/nuxt-gtm": "^0.0.13", + "cypress": "^13.6.6", "nuxt": "^3.8.2", "nuxt-svgo": "^3.5.6", "sass": "^1.66.1" diff --git a/yarn.lock b/yarn.lock index 0660e77a..4fedcb87 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2609,6 +2609,11 @@ dependencies: mime "^3.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== + "@contentful/rich-text-types@^16.0.2": version "16.3.4" resolved "https://registry.yarnpkg.com/@contentful/rich-text-types/-/rich-text-types-16.3.4.tgz#c5fc9c834dde03d4c4ee189900d304ce1888a74b" @@ -2619,6 +2624,30 @@ resolved "https://registry.yarnpkg.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz#b6c75a56a1947cc916ea058772d666a2c8932f31" integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA== +"@cypress/request@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@cypress/request/-/request-3.0.1.tgz#72d7d5425236a2413bd3d8bb66d02d9dc3168960" + integrity sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ== + 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.10.4" + safe-buffer "^5.1.2" + tough-cookie "^4.1.3" + tunnel-agent "^0.6.0" + uuid "^8.3.2" + "@cypress/vite-dev-server@^5.0.7": version "5.0.7" resolved "https://registry.yarnpkg.com/@cypress/vite-dev-server/-/vite-dev-server-5.0.7.tgz#edac70bfe53fb5a10c50efedd8141254335690e0" @@ -2629,6 +2658,14 @@ node-html-parser "5.3.3" semver "^7.5.3" +"@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" + "@deck.gl/core@^8.9.33": version "8.9.35" resolved "https://registry.yarnpkg.com/@deck.gl/core/-/core-8.9.35.tgz#50b660a7e22b6001a4f838120a3b034517553d8a" @@ -4365,6 +4402,16 @@ resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975" integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q== +"@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.8" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.8.tgz#518609aefb797da19bf222feb199e8f653ff7627" + integrity sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg== + "@types/supercluster@^7.1.3": version "7.1.3" resolved "https://registry.yarnpkg.com/@types/supercluster/-/supercluster-7.1.3.tgz#1a1bc2401b09174d9c9e44124931ec7874a72b27" @@ -5043,7 +5090,7 @@ ansi-align@^2.0.0: dependencies: string-width "^2.0.0" -ansi-colors@^4.1.3: +ansi-colors@^4.1.1, ansi-colors@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== @@ -5125,6 +5172,11 @@ anymatch@^3.1.3, anymatch@~3.1.2: resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== +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== + archiver-utils@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-4.0.1.tgz#66ad15256e69589a77f706c90c6dbcc1b2775d2a" @@ -5316,6 +5368,18 @@ asn1.js@^5.2.0: minimalistic-assert "^1.0.0" safer-buffer "^2.1.0" +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== + assert@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd" @@ -5358,6 +5422,11 @@ ast-walker-scope@^0.5.0: "@babel/parser" "^7.22.7" ast-kit "^0.9.4" +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-each@^1.0.1: version "1.0.6" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.6.tgz#52f1d9403818c179b7561e11a5d1b77eb2160e77" @@ -5378,7 +5447,7 @@ async-validator@^4.2.5: resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-4.2.5.tgz#c96ea3332a521699d0afaaceed510a54656c6339" integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg== -async@^3.2.4: +async@^3.2.0, async@^3.2.4: version "3.2.5" resolved "https://registry.yarnpkg.com/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66" integrity sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg== @@ -5395,6 +5464,11 @@ asynckit@^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== + atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -5441,6 +5515,16 @@ aws-amplify@^5.3.10: "@aws-amplify/storage" "5.9.9" tslib "^2.0.0" +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.12.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" + integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== + axios@^0.21.2: version "0.21.4" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" @@ -5495,6 +5579,13 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" +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" + bezier-js@^6.1.0: version "6.1.4" resolved "https://registry.yarnpkg.com/bezier-js/-/bezier-js-6.1.4.tgz#c7828f6c8900562b69d5040afb881bcbdad82001" @@ -5584,7 +5675,12 @@ bl@^4.0.3: inherits "^2.0.4" readable-stream "^3.4.0" -bluebird@^3.5.5: +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.5.5, 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== @@ -5948,6 +6044,11 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +cachedir@^2.3.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.4.0.tgz#7fef9cf7367233d7c88068fe6e34ed0d355a610d" + integrity sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ== + call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" @@ -6036,6 +6137,11 @@ capture-stack-trace@^1.0.0: resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.2.tgz#1c43f6b059d4249e7f3f8724f15f048b927d3a8a" integrity sha512-X/WM2UQs6VMHUtjUDnZTRI+i1crWteJySFzr9UpGoQa4WQffXVTTXuekjl7TjZRlcF2XfjgITT0HxZ9RnxeT0w== +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + caw@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/caw/-/caw-2.0.1.tgz#6c3ca071fc194720883c2dc5da9b074bfc7e9e95" @@ -6066,7 +6172,7 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1, chalk@^2.4 escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.1.1: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -6096,6 +6202,11 @@ chartjs-plugin-datalabels@^2.2.0: resolved "https://registry.yarnpkg.com/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz#369578e131d743c2e34b5fbe2d3f9335f6639b8f" integrity sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw== +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== + check-types@^8.0.3: version "8.0.3" resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552" @@ -6162,6 +6273,11 @@ ci-info@^1.5.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== +ci-info@^3.2.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + ci-info@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.0.0.tgz#65466f8b280fc019b9f50a5388115d17a63a44f2" @@ -6219,11 +6335,35 @@ cli-cursor@^2.0.0, cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +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-spinners@^1.0.1: version "1.3.1" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" integrity sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg== +cli-table3@~0.6.1: + version "0.6.3" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" + integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== + 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" + cli-width@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" @@ -6383,12 +6523,12 @@ colord@^2.9.1, colord@^2.9.3: resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== -colorette@^2.0.20: +colorette@^2.0.16, colorette@^2.0.20: version "2.0.20" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== -combined-stream@^1.0.8: +combined-stream@^1.0.6, combined-stream@^1.0.8, 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== @@ -6405,6 +6545,11 @@ commander@9.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-9.2.0.tgz#6e21014b2ed90d8b7c9647230d8b7a94a4a419a9" integrity sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w== +commander@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" + integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== + commander@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" @@ -6415,6 +6560,11 @@ commander@^8.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== +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== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -6583,6 +6733,11 @@ core-js@^3.22.5, core-js@^3.26.1, core-js@^3.6.5, core-js@^3.7.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.35.1.tgz#9c28f8b7ccee482796f8590cc8d15739eaaf980c" integrity sha512-IgdsbxNyMskrTFxa9lWHyMwAJU5gXOPP+1yO+K59d50VLVAIDAbs7gIv705KzALModfK3ZrSZTPNpC0PQgIZuw== +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== + core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -6899,6 +7054,54 @@ custom-event-polyfill@^1.0.7: resolved "https://registry.yarnpkg.com/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz#9bc993ddda937c1a30ccd335614c6c58c4f87aee" integrity sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w== +cypress@^13.6.6: + version "13.6.6" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-13.6.6.tgz#5133f231ed1c6e57dc8dcbf60aade220bcd6884b" + integrity sha512-S+2S9S94611hXimH9a3EAYt81QM913ZVA03pUmGDfLTFa5gyp85NJ8dJGSlEAEmyRsYkioS1TtnWtbv/Fzt11A== + dependencies: + "@cypress/request" "^3.0.0" + "@cypress/xvfb" "^1.2.4" + "@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.7.1" + 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 "^6.2.1" + common-tags "^1.8.0" + dayjs "^1.10.4" + debug "^4.3.4" + enquirer "^2.3.6" + eventemitter2 "6.4.7" + 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.1" + 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.8" + ospath "^1.2.2" + pretty-bytes "^5.6.0" + process "^0.11.10" + proxy-from-env "1.0.0" + request-progress "^3.0.0" + semver "^7.5.3" + supports-color "^8.1.1" + tmp "~0.2.1" + untildify "^4.0.0" + yauzl "^2.10.0" + d3-array@1, d3-array@^1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f" @@ -7026,6 +7229,13 @@ d@1, d@^1.0.1: es5-ext "^0.10.50" type "^1.0.1" +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" + data-uri-to-buffer@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" @@ -7046,7 +7256,7 @@ date-fns@^2.3.0, date-fns@^2.30.0: dependencies: "@babel/runtime" "^7.21.0" -dayjs@^1.11.3: +dayjs@^1.10.4, dayjs@^1.11.3: version "1.11.10" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0" integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ== @@ -7070,7 +7280,7 @@ debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: dependencies: ms "2.1.2" -debug@^3.2.6, debug@^3.2.7: +debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -7468,6 +7678,14 @@ earcut@^2.1.5, earcut@^2.2.2, earcut@^2.2.4: resolved "https://registry.yarnpkg.com/earcut/-/earcut-2.2.4.tgz#6d02fd4d68160c114825d06890a92ecaae60343a" integrity sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ== +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" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -7608,6 +7826,14 @@ enhanced-resolve@^5.14.1: graceful-fs "^4.2.4" tapable "^2.2.0" +enquirer@^2.3.6: + version "2.4.1" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== + dependencies: + ansi-colors "^4.1.1" + strip-ansi "^6.0.1" + entities@2.2.0, entities@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" @@ -8124,6 +8350,11 @@ event-target-shim@^5.0.0: resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== +eventemitter2@6.4.7: + version "6.4.7" + resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.7.tgz#a7f6c4d7abf28a14c1ef3442f21cb306a054271d" + integrity sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg== + events@^3.0.0, events@^3.1.0, events@^3.2.0, events@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" @@ -8137,6 +8368,21 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +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" + execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" @@ -8195,6 +8441,13 @@ execa@^8.0.1: signal-exit "^4.1.0" strip-final-newline "^3.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" + expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -8272,6 +8525,11 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.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== + external-editor@^2.0.4: version "2.2.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" @@ -8305,7 +8563,7 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -extract-zip@^2.0.0: +extract-zip@2.0.1, extract-zip@^2.0.0: 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== @@ -8316,6 +8574,16 @@ extract-zip@^2.0.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== + falafel@^2.1.0: version "2.2.5" resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.2.5.tgz#3ccb4970a09b094e9e54fead2deee64b4a589d56" @@ -8439,6 +8707,13 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" +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" @@ -8639,6 +8914,11 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" +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@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -8657,6 +8937,15 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +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" + formdata-polyfill@^4.0.10: version "4.0.10" resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" @@ -8740,6 +9029,16 @@ fs-extra@^7.0.1: jsonfile "^4.0.0" universalify "^0.1.0" +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-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -8888,7 +9187,7 @@ get-stream@^3.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ== -get-stream@^5.1.0: +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== @@ -8918,6 +9217,20 @@ get-value@^2.0.2, get-value@^2.0.3, get-value@^2.0.6: resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== +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" + giget@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/giget/-/giget-1.2.1.tgz#4f42779aae57a5f664a1c4d50401b008e9810f4c" @@ -9087,6 +9400,13 @@ global-dirs@^0.1.0: dependencies: ini "^1.3.4" +global-dirs@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485" + integrity sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA== + dependencies: + ini "2.0.0" + global-prefix@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" @@ -9606,6 +9926,15 @@ http-shutdown@^1.2.2: resolved "https://registry.yarnpkg.com/http-shutdown/-/http-shutdown-1.2.2.tgz#41bc78fc767637c4c95179bc492f312c0ae64c5f" integrity sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw== +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" + https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" @@ -9640,6 +9969,11 @@ httpxy@^0.1.5: resolved "https://registry.yarnpkg.com/httpxy/-/httpxy-0.1.5.tgz#fd2401206e0b5d919aeda25e967ece0f1a6c8569" integrity sha512-hqLDO+rfststuyEUTWObQK6zHEEmZ/kaIP2/zclGGZn6X8h/ESTWg+WKecQ/e5k4nPswjzZD+q2VqZIbr15CoQ== +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== + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -9752,6 +10086,11 @@ inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, i 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== + ini@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.1.tgz#d95b3d843b1e906e56d6747d5447904ff50ce7a1" @@ -9920,6 +10259,13 @@ is-ci@^1.0.10: dependencies: ci-info "^1.5.0" +is-ci@^3.0.1: + 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.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1, is-core-module@^2.8.1: version "2.13.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" @@ -10055,6 +10401,14 @@ is-installed-globally@^1.0.0: global-directory "^4.0.1" is-path-inside "^4.0.0" +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-lambda@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" @@ -10134,7 +10488,7 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" -is-path-inside@^3.0.3: +is-path-inside@^3.0.2, is-path-inside@^3.0.3: 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== @@ -10273,6 +10627,16 @@ is-typed-array@^1.1.3: dependencies: which-typed-array "^1.1.14" +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== + is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" @@ -10388,6 +10752,11 @@ isomorphic-unfetch@^3.0.0: node-fetch "^2.6.1" unfetch "^4.2.0" +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== + isurl@^1.0.0-alpha5: version "1.0.0" resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" @@ -10458,6 +10827,11 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + jsdom@^23.0.0: version "23.2.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-23.2.0.tgz#08083220146d41c467efa1c6969f02b525ba6c1d" @@ -10510,6 +10884,11 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +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" @@ -10520,7 +10899,7 @@ json-stringify-pretty-compact@^3.0.0: resolved "https://registry.yarnpkg.com/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz#f71ef9d82ef16483a407869556588e91b681d9ab" integrity sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA== -json-stringify-safe@^5.0.1: +json-stringify-safe@^5.0.1, 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== @@ -10585,6 +10964,16 @@ jsonschema@^1.4.0: resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.1.tgz#cc4c3f0077fb4542982973d8a083b6b34f482dab" integrity sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ== +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" + jstransformer-ejs@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/jstransformer-ejs/-/jstransformer-ejs-0.0.3.tgz#04d9201469274fcf260f1e7efd732d487fa234b6" @@ -10714,6 +11103,11 @@ launch-editor@^2.6.1: picocolors "^1.0.0" shell-quote "^1.8.1" +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== + lazystream@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638" @@ -10766,6 +11160,20 @@ listhen@^1.5.5: untun "^0.1.3" uqr "^0.1.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" + load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -10907,6 +11315,11 @@ 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.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" @@ -10932,6 +11345,14 @@ log-symbols@^2.1.0: dependencies: chalk "^2.0.1" +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@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" @@ -10941,6 +11362,16 @@ log-update@^2.3.0: cli-cursor "^2.0.0" wrap-ansi "^3.0.1" +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" + loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -11257,7 +11688,7 @@ mime-types@2.1.18: dependencies: mime-db "~1.33.0" -mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: 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== @@ -11947,7 +12378,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npm-run-path@^4.0.1: +npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== @@ -12216,7 +12647,7 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" -onetime@^5.1.2: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -12310,6 +12741,11 @@ os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== +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-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -12713,7 +13149,7 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pify@^2.0.0, pify@^2.3.0: +pify@^2.0.0, pify@^2.2.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== @@ -13149,6 +13585,11 @@ prescribe@>=1.1.2: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== +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== + pretty-bytes@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-6.1.1.tgz#38cd6bb46f47afbf667c202cfc754bffd2016a3b" @@ -13253,6 +13694,11 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +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== + proxy-from-env@^1.0.0, proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -13321,6 +13767,13 @@ puppeteer-core@^5.5.0: unbzip2-stream "^1.3.3" ws "^7.2.3" +qs@6.10.4: + version "6.10.4" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.4.tgz#6a3003755add91c0ec9eacdc5f878b034e73f9e7" + integrity sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g== + dependencies: + side-channel "^1.0.4" + qs@6.11.0: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" @@ -13778,6 +14231,13 @@ repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== +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-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -13846,6 +14306,14 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +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" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -13861,6 +14329,11 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== +rfdc@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f" + integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg== + right-now@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/right-now/-/right-now-1.0.0.tgz#6e89609deebd7dcdaf8daecc9aea39cf585a0918" @@ -13964,6 +14437,13 @@ rx-lite@*, rx-lite@^4.0.8: resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" integrity sha512-Cun9QucwK6MIrp3mry/Y7hqD1oFqTYLQ4pGxaHTjIdaFDWRGGLikqp6u8LcWJnzpoALg9hap+JGk8sFIUuEGNA== +rxjs@^7.5.1: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + safe-array-concat@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.0.tgz#8d0cae9cb806d6d1c06e08ab13d847293ebe0692" @@ -14000,7 +14480,7 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", 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== @@ -14339,6 +14819,24 @@ slash@^5.1.0: resolved "https://registry.yarnpkg.com/slash/-/slash-5.1.0.tgz#be3adddcdf09ac38eebe8dcdc7b1a57a75b095ce" integrity sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg== +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" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" @@ -14539,6 +15037,21 @@ splitpanes@^3.1.5: resolved "https://registry.yarnpkg.com/splitpanes/-/splitpanes-3.1.5.tgz#de81da25681c252d131747a9cb48a17156e2b210" integrity sha512-r3Mq2ITFQ5a2VXLOy4/Sb2Ptp7OfEO8YIbhVJqJXoFc9hc5nTXXkCvtVDjIGbvC0vdE7tse+xTM9BMjsszP6bw== +sshpk@^1.14.1: + version "1.18.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" + integrity sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ== + 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" + ssri@^10.0.0: version "10.0.5" resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.5.tgz#e49efcd6e36385196cb515d3a2ad6c3f0265ef8c" @@ -14890,6 +15403,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-color@^9.4.0: version "9.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.4.0.tgz#17bfcf686288f531db3dea3215510621ccb55954" @@ -15055,6 +15575,11 @@ three@^0.130.1: resolved "https://registry.yarnpkg.com/three/-/three-0.130.1.tgz#797588b2877ace31603bbbc864eb2e3022f0b3b4" integrity sha512-OSPPKcGvFSiGkG3jFrwwC76PBV/ZSrGxpBbg28bW8s9GU8r/y2spNGtEXHEb/CVqo0Ctf5Lx2rVaxQZB6OasaA== +throttleit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.1.tgz#304ec51631c3b770c65c6c6f76938b384000f4d5" + integrity sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ== + through2@^0.6.3: version "0.6.5" resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" @@ -15117,6 +15642,11 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +tmp@~0.2.1: + version "0.2.3" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" + integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== + to-buffer@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" @@ -15249,7 +15779,7 @@ tslib@^1.11.1, tslib@^1.8.0, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.3.1, tslib@^2.5.0: +tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.5.0: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== @@ -15275,6 +15805,11 @@ tunnel-agent@^0.6.0: 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" @@ -15696,6 +16231,11 @@ unstorage@^1.10.1: ofetch "^1.3.3" ufo "^1.3.1" +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== + untun@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/untun/-/untun-0.1.3.tgz#5d10dee37a3a5737ff03d158be877dae0a0e58a6" @@ -15892,6 +16432,15 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +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" + version-guard@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/version-guard/-/version-guard-1.1.1.tgz#7a6e87a1babff1b43d6a7b0fd239731e278262fa" @@ -16376,6 +16925,15 @@ wrap-ansi@^3.0.1: string-width "^2.1.1" strip-ansi "^4.0.0" +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@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From e00a65cd489a50391065d1594d103fcf75c267f9 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:51:15 +1300 Subject: [PATCH 02/44] add e2e testing config --- cypress.config.js | 26 ++++++++++++++++++++++++++ tests/cypress/fixtures/example.json | 5 +++++ tests/cypress/support/commands.js | 25 +++++++++++++++++++++++++ tests/cypress/support/e2e.js | 20 ++++++++++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 cypress.config.js create mode 100644 tests/cypress/fixtures/example.json create mode 100644 tests/cypress/support/commands.js create mode 100644 tests/cypress/support/e2e.js diff --git a/cypress.config.js b/cypress.config.js new file mode 100644 index 00000000..d2dddbcb --- /dev/null +++ b/cypress.config.js @@ -0,0 +1,26 @@ +import { defineConfig } from "cypress"; + +export default defineConfig({ + defaultCommandTimeout: 5000, + experimentalMemoryManagement: true, + numTestsKeptInMemory: 0, + e2e: { + baseUrl: process.env.ROOT_URL ? process.env.ROOT_URL : 'http://localhost:3000', + experimentalStudio: true, + projectId: process.env.CYPRESS_PROJECT_ID, + specPattern: "tests/cypress/e2e/**/*.cy.{js,jsx,ts,tsx}", + supportFile: "tests/cypress/support/e2e.js", + viewportWidth: 1600, + viewportHeight: 900, + //Prevent huge amount of time on reloading page + testIsolation: true, + // pageLoadTimeout: 1024*1024*1024, + setupNodeEvents(on, config) { + // implement node event listeners here + }, + }, + fixturesFolder: "tests/cypress/fixtures", + screenshotsFolder: "tests/cypress/screenshots", + videosFolder: "tests/cypress/videos", + downloadsFolder: "tests/cypress/downloads", +}); diff --git a/tests/cypress/fixtures/example.json b/tests/cypress/fixtures/example.json new file mode 100644 index 00000000..02e42543 --- /dev/null +++ b/tests/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js new file mode 100644 index 00000000..66ea16ef --- /dev/null +++ b/tests/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) \ No newline at end of file diff --git a/tests/cypress/support/e2e.js b/tests/cypress/support/e2e.js new file mode 100644 index 00000000..0e7290a1 --- /dev/null +++ b/tests/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/e2e.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') \ No newline at end of file From 67584a7cc22ba252ae7c9f528ad18ca98fb14fff Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:57:09 +1300 Subject: [PATCH 03/44] migrate testings from nuxt2 portal --- .gitignore | 3 + tests/MarkdownTest/MarkdownTest.spec.js | 23 ++ tests/MarkdownTest/MarkdownTest.vue | 27 ++ tests/cypress/e2e/datasets.cy.js | 383 ++++++++++++++++++++++++ tests/cypress/e2e/finddata.cy.js | 301 +++++++++++++++++++ tests/cypress/e2e/homepage.cy.js | 133 ++++++++ tests/cypress/e2e/mapviewer.cy.js | 175 +++++++++++ tests/cypress/e2e/userstories.cy.js | 166 ++++++++++ tests/cypress/support/commands.js | 54 +++- 9 files changed, 1264 insertions(+), 1 deletion(-) create mode 100644 tests/MarkdownTest/MarkdownTest.spec.js create mode 100644 tests/MarkdownTest/MarkdownTest.vue create mode 100644 tests/cypress/e2e/datasets.cy.js create mode 100644 tests/cypress/e2e/finddata.cy.js create mode 100644 tests/cypress/e2e/homepage.cy.js create mode 100644 tests/cypress/e2e/mapviewer.cy.js create mode 100644 tests/cypress/e2e/userstories.cy.js diff --git a/.gitignore b/.gitignore index 40d1c726..b8fbfa76 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,6 @@ logs .env .env.* !.env.example + +tests/cypress/videos +tests/cypress/downloads \ No newline at end of file diff --git a/tests/MarkdownTest/MarkdownTest.spec.js b/tests/MarkdownTest/MarkdownTest.spec.js new file mode 100644 index 00000000..c9286557 --- /dev/null +++ b/tests/MarkdownTest/MarkdownTest.spec.js @@ -0,0 +1,23 @@ +import { mount } from '@vue/test-utils' +import MarkdownTest from './MarkdownTest' + +describe('MarkdownTest', () => { + const wrapper = mount(MarkdownTest) + + it('Renders the correct markup', () => { + expect(wrapper.find('#externalWrap a').exists()).toBe(true) + expect(wrapper.find('#externalWrap h1').exists()).toBe(true) + }) + + it('Adds target="blank" to links', () => { + expect(wrapper.find('#externalWrap a').element.getAttribute('target')).toBe( + '_blank' + ) + }) + + it('Renders an anchor tag properly', () => { + expect(wrapper.find('#anchorWrap a').element.getAttribute('target')).toBe( + null + ) + }) +}) diff --git a/tests/MarkdownTest/MarkdownTest.vue b/tests/MarkdownTest/MarkdownTest.vue new file mode 100644 index 00000000..7655382d --- /dev/null +++ b/tests/MarkdownTest/MarkdownTest.vue @@ -0,0 +1,27 @@ + + + + + diff --git a/tests/cypress/e2e/datasets.cy.js b/tests/cypress/e2e/datasets.cy.js new file mode 100644 index 00000000..7b14aff4 --- /dev/null +++ b/tests/cypress/e2e/datasets.cy.js @@ -0,0 +1,383 @@ +const datasetIds = [127]; +// const datasetIds = [127, 282, 290, 34, 76]; + + +datasetIds.forEach(datasetId => { + + describe(`Dataset ${datasetId}`, { testIsolation: false }, function () { + before(function () { + cy.intercept('**/dataset_info/using_doi?**').as('dataset_info') + cy.intercept('**/knowledge/query/**').as('flatmap') + cy.visit(`/datasets/${datasetId}?type=dataset`) + }); + + it("Gallery Tab", function () { + // Should switch to 'Gallery' + cy.contains('#datasetDetailsTabsContainer .style1', ' Gallery ').click(); + cy.get('.nuxt-link-exact-active').should('contain', ' Gallery '); + + cy.wait(5000) + + cy.get('.content > .full-size', { timeout: 30000 }).then(($content) => { + const gallery = $content.find('.gallery-container'); + if (gallery && gallery.length) { + // Check for pagination + cy.wrap(gallery).find('.sparc-design-system-pagination').as('pagination'); + cy.get('@pagination').find('li.number').should('have.length.least', 1); + + // Check for gallery card + cy.wrap(gallery).find('.el-card').as('card').should('have.length.least', 1) + cy.get('@card').first().within(($card) => { + cy.wrap($card).get('.cursor-pointer > img').should('be.visible').and('have.prop', 'naturalWidth').should('be.greaterThan', 0) + cy.wrap($card).contains('span', ' View ') + }); + + // Only check for dataset when it has valid flatmap data + cy.wait('@dataset_info').then((intercept) => { + if (intercept.response.body.result[0].organs) { + cy.wait('@flatmap').then((intercept) => { + if (intercept.response.body.values.length > 0) { + cy.findGalleryCard('flatmap', 'prev'); + cy.get('.el-card > .el-card__body').should('contain', 'flatmap'); + } + }) + } + }) + } else { + cy.wrap($content).contains(' This dataset does not contain gallery items '); + } + }); + }); + it("Landing page", function () { + cy.intercept('**/query?**').as('query') + + // Should display image with correct dataset src + cy.get('.dataset-image').should('have.attr', 'src').and('include', `https://assets.discover.pennsieve.io/dataset-assets/${datasetId}`) + + // Check for tooltip when hover over author + cy.get('.dataset-owners > :nth-child(2) > .contributor-item').then(($orcid) => { + if ($orcid.hasClass('has-orcid')) { + cy.wrap($orcid).trigger('mouseenter', { eventConstructor: 'MouseEvent' }) + //only one visible popover + cy.get('.orcid-popover:visible').should('have.length', 1) + } + }) + + // Should reload the page + cy.get('.dataset-information-box > :nth-child(2) > a').click() + cy.origin('https://sparc.science', () => { + cy.url().should('contain', 'version') + cy.go('back') + }) + // cy.get('.dataset-information-box > :nth-child(2) > a').should('have.attr', 'href').and('include', 'doi.org').then((href) => { + // cy.request(href).then((resp) => { + // expect(resp.status).to.eq(200); + // expect(resp.body).to.include(`datasets/${datasetId}/version`); + // }) + // }); + + // Should search for contributor in find data page + cy.get(':nth-child(2) > .contributor-list > li > .el-tooltip > .tooltip-item > a').then(($name) => { + cy.wrap($name).click() + + cy.wait('@query', { timeout: 20000 }) + + cy.get('.table-wrap.el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + + // Check for result + cy.get(':nth-child(1) > p > .el-dropdown > .filter-dropdown').should('be.visible').click() + cy.get('.el-dropdown-menu > .el-dropdown-menu__item:visible').contains('View All').click() + + let datasetShowUp = false + cy.get('.img-dataset > img').each(($img) => { + cy.wrap($img).invoke('attr', 'src').then((src) => { + datasetShowUp = datasetShowUp || src.includes(datasetId) + }) + }).then(() => { + if (!datasetShowUp) { + throw new Error("Can not find the dataset for current contributor") + } + }) + + // Check for URL and search input + cy.url({ decode: true }).should('contain', `search=${$name.text()}`) + cy.get('.el-input__inner').should('have.value', $name.text()); + cy.go('back') + }); + + // Check 'View other version' directs to Versions tab + cy.get('.dataset-information-box > div').contains('View other versions').click(); + cy.get('.nuxt-link-exact-active').should('contain', ' Versions '); + cy.get('[style=""] > .heading2.mb-8').should('contain', 'Versions for this Dataset').and('be.visible') + + //Check 'Get Dataset' directs to files tab + cy.contains('.button-container span', 'Get Dataset').click() + cy.get('.nuxt-link-exact-active').should('contain', ' Files '); + cy.get('[style=""] > .heading2.mb-8').should('have.text', 'Download Dataset').and('be.visible') + + //Check 'Cite Dataset' directs to Cite tab + cy.contains('.button-container span', 'Cite Dataset').click() + cy.get('.nuxt-link-exact-active').should('contain', ' Cite '); + cy.get('.citation-details > .heading2').should('have.text', '\n Dataset Citation\n ').and('be.visible') + }); + it("Abstract Tab", function () { + // Should switch to 'Abstract' + cy.contains('#datasetDetailsTabsContainer .style1', ' Abstract ').click(); + cy.get('.nuxt-link-exact-active').should('contain', ' Abstract '); + + //The following regular expression should capture space and letters + cy.get('.dataset-description-info > .col-xs-12.description-container > p').contains(/Study Purpose: (.+)/).should('exist') + cy.get('.dataset-description-info > .col-xs-12.description-container > p').contains(/Data (Collection|Collected):(.+)/).should('exist') + cy.get('.dataset-description-info > .col-xs-12.description-container > p').contains(/(Primary )?Conclusion(s)?: (.+)/).should('exist') + + // Check for Experimental Design + cy.get('.dataset-description-info > .mb-8').contains('Experimental Design:').should('exist') + cy.get('.dataset-description-info').contains('Protocol Links:').should('exist') + cy.get('.dataset-description-info').within(($el) => { + if ($el.text().includes('https://doi.org/')) { + cy.get('.link2').should('exist') + cy.get('.link2').should('have.length.above', 0) + cy.get('.link2').should('have.attr', 'href').and('include', 'https://doi.org/') + } + }) + cy.get('.dataset-description-info > .experimental-design-container').contains(/Experimental Approach: (.+)/).should('exist') + + // Check for Subject Information + cy.get('.dataset-description-info > .mb-8').contains('Subject Information:').should('exist') + cy.get('.dataset-description-info > .experimental-design-container').contains(/Anatomical structure: (.+)/).should('exist') + cy.get('.dataset-description-info > .experimental-design-container').contains(/Species: (.+)/).should('exist') + cy.get('.dataset-description-info > .experimental-design-container').contains(/Sex: (.+)/).should('exist') + cy.get('.dataset-description-info > .experimental-design-container').contains(/Number of samples: (.+)/).should('exist') + + // Check for Keywords + cy.get('.dataset-description-info').contains(/Keywords: (.+)/).should('exist') + + // Check for downloading + cy.contains('.dataset-description-info a', 'Download Metadata file').should('have.attr', 'href').and('include', 'metadata').then((href) => { + cy.request(href).then((resp) => { + expect(resp.status).to.eq(200) + }) + }) + }); + it("About Tab", function () { + // Should switch to 'About' + cy.contains('#datasetDetailsTabsContainer .style1', ' About ').click(); + cy.get('.nuxt-link-exact-active').should('contain', ' About '); + + // Check for content + cy.get('.dataset-about-info > .mb-16').contains(/Title: (.+)/).should('exist') + cy.get('.dataset-about-info > .mb-16').contains(/First Published: (.+)/).should('exist') + cy.get('.dataset-about-info > .mb-16').contains(/Last Published: (.+)/).should('exist') + cy.get('.dataset-about-info > .about-section-container').contains(/Contact Author: (.+)/).within(($el) => { + // Check for email link exist + cy.wrap($el).get(':nth-child(2) > :nth-child(2) > a').should('have.attr', 'href').and('include', 'mailto:'); + }) + cy.get('.dataset-about-info > .mb-16').contains(/Award[(]s[)]: (.+)/).should('exist') + cy.get('.dataset-about-info > .mb-16').contains(/Funding Program[(]s[)]: (.+)/).should('exist') + cy.get('.dataset-about-info > .mb-16').contains(/Associated project[(]s[)]: (.+)/).should('exist') + cy.get('.dataset-about-info > .mb-16').contains(/Institution[(]s[)]: (.+)/).should('exist') + cy.get('.dataset-about-info > .mb-16').contains(/Version (.+) Revision (.+): (.+)/).should('exist') + cy.get('.dataset-about-info > .mb-16').contains(/Dataset DOI: (.+)/).should('exist') + + /** + * Contact Author may not be the contributor + * If should be, uncomment following code + */ + // //match author to contributors + // cy.get('.about-section-container > :nth-child(2) > :nth-child(1)').invoke('text').then((value) => { + // const author = new RegExp(value.replace(/\s+/, ' '), 'i') + // cy.get('.similar-datasets-container').contains(author); + // }) + + // Ignore tests if project not exist + cy.get('.similar-datasets-container').then(($content) => { + if ($content.text().includes('project(s):')) { + //Match award link to associated project + cy.get(':nth-child(11) > :nth-child(2) > a').invoke('attr', 'href').then((value) => { + cy.get(':nth-child(8) > :nth-child(2) > a').should('have.attr', 'href', value); + }); + + cy.get('.dataset-about-info').contains(/Institution[(]s[)]: (.+)/).children().not('.label4').invoke('text').then((value) => { + cy.get('.mt-8 > a').click() + cy.url({ timeout: 30000 }).should('contain', 'projects') + + // Check for the institution + const institution = value.match(/[ a-zA-Z]+/)[0].trim() + cy.get('.body1 > :nth-child(6)').should('contain', institution); + cy.go('back') + }) + } + }) + }); + it("Cite Tab", function () { + // Should switch to 'Cite' + cy.contains('#datasetDetailsTabsContainer .style1', ' Cite ').click(); + cy.get('.nuxt-link-exact-active').should('contain', ' Cite '); + + // Check for title + cy.get('.bx--col-md-6 > .heading2').invoke('text').then((value) => { + cy.get('.info-citation > .citation-text', { timeout: 30000 }).should('contain', value.trim()) + }) + + cy.get('.dataset-information-box > :nth-child(2) > a > u').invoke('text').then((value) => { + // Check for citation doi + cy.get('.info-citation > .citation-text', { timeout: 30000 }).should('contain', value.toUpperCase()) + + // Check for source link + const expectedLink = 'https://citation.crosscite.org/?doi=' + value; + cy.get('.citation-details > p > a').should('have.attr', 'href', expectedLink); + }) + }); + it("Files Tab", function () { + //First check if there is a Files tab + cy.get('#datasetDetailsTabsContainer .style1').then(($tab) => { + if ($tab.text().includes(' Files ')) { + // Should switch to 'Files' if exist + cy.contains('#datasetDetailsTabsContainer .style1', ' Files ').click(); + cy.get('.nuxt-link-exact-active').should('contain', ' Files '); + + // Check for content + cy.get('[style=""] > .heading2.mb-8').should('have.text', 'Download Dataset'); + cy.get('.left-column > :nth-child(1) > div > .label4').should('have.text', 'Option 1 - Direct download: '); + cy.get('.aws-download-column > :nth-child(1) > .label4').should('have.text', 'Option 2 - AWS download: '); + + // Check for download full dataset button + cy.get('.left-column .el-button').contains('Download full dataset').should('be.visible'); + cy.contains('Dataset size').parent().then(($size) => { + const size = parseFloat($size.text().match(/[0-9]+(.[0-9]+)?/i)[0]) + if ($size.text().includes("GB") && size > 5) { + cy.get('.el-tooltip > .el-button').should('not.be.enabled') + } else { + cy.get('.left-column > :nth-child(1) > a > .el-button').should('be.enabled') + } + }) + + // Check for help link + cy.get('.aws-download-column > :nth-child(1) > a').should('have.attr', 'href', 'https://docs.sparc.science/docs/accessing-public-datasets'); + cy.get('.aws-download-column > :nth-child(3) > a').should('have.attr', 'href', 'https://aws.amazon.com/s3/pricing/'); + + //Find the download file button + cy.contains('.content .body1 .el-table__fixed-body-wrapper .el-table__row', ' dataset_description.xlsx ').should('have.length', 1).as('datasetDescription'); + + //there should be 4 icons, one for each action + cy.get('@datasetDescription').find('.svg-icon').should('have.length', 4).as('icons') + + //Check get share links + cy.get('@icons').eq(3).click({ force: true }); + cy.get('.el-message').should('be.visible').and('have.text', 'File URL copied to clipboard.') + + //Check oSPARC link + cy.get('@icons').eq(2).click({ force: true }); + cy.get('.files-table-table .el-dialog .svg-icon').click({ force: true }); + + // Check for files breadcrumb + cy.get('.inline > .dataset-link').should('have.attr', 'href', 'https://docs.sparc.science/docs/accessing-public-datasets'); + cy.get('.breadcrumb-link').should('have.class', 'breadcrumb-link'); + cy.get('.breadcrumb-link').should('have.attr', 'href').and('contain', 'datasetDetailsTab=files&path=files'); + cy.get('.el-table__body-wrapper > .el-table__body > tbody > .el-table__row').then(($table) => { + if ($table.text().includes('Folder')) { + cy.get('.breadcrumb-link').should('have.length', 1) + cy.wrap($table).filter(':contains("Folder")').first().within(($link) => { + cy.wrap($link).get('.file-name-wrap > .el-tooltip > .file-name').click({ force: true }) + }) + cy.get('.breadcrumb-link').should('have.length', 2) + cy.get(':nth-child(1) > .breadcrumb-link').click() + cy.get('.breadcrumb-link').should('have.length', 1) + } + }) + } else { + this.skip(); + } + }); + }); + it("References Tab", function () { + //First check if reference tab is present + cy.get('#datasetDetailsTabsContainer .style1').then(($tab) => { + if ($tab.text().includes(' References ')) { + // Should switch to 'References' if exist + cy.contains('#datasetDetailsTabsContainer .style1', ' References ').click(); + cy.get('.nuxt-link-exact-active').should('contain', ' References '); + + // Check for content + cy.get('.dataset-references .heading2').contains('Associated Publications for this Dataset'); + cy.get('.dataset-references .citation-container').each(el => { + cy.wrap(el).find('div > a').should('have.attr', 'href').and('include', 'doi.org'); + cy.wrap(el).find('.copy-button').click(); + cy.get('.el-message').should('be.visible').and('contain', 'Successfully copied citation.') + }); + + // Check if redundant doi exist + let doiList = [] + cy.get('.dataset-references').then(($content) => { + if ( + $content.text().includes('Primary Publications for this Dataset') && + $content.text().includes('Preprints') + ) { + cy.get('.dataset-references .citation-container > div > a').each($doi => { + cy.wrap($doi).invoke('attr', 'href').then((link) => { + if (!doiList.includes(link)) { + doiList.push(link) + } else { + throw new Error("Redundant doi is found") + } + }) + }); + } + }) + } else { + this.skip(); + } + }); + }); + it("Versions Tab", function () { + //First check if version tab is present + cy.get('#datasetDetailsTabsContainer .style1').then(($tab) => { + if ($tab.text().includes(' Versions ')) { + // Should switch to 'Versions' if exist + cy.contains('#datasetDetailsTabsContainer .style1', ' Versions ').click(); + cy.get('.nuxt-link-exact-active').should('contain', ' Versions '); + + // Check for file actions + cy.get('.version-table > :nth-child(2) > :nth-child(4)').then(($cell) => { + if ($cell.text().includes('Not available')) { + cy.wrap($cell).should('contain', 'Not available') + } else { + // Check for changelog + cy.wrap($cell).find('.svg-icon').as('icons').should('have.length', 2) + cy.get('@icons').eq(0).click() + + // Check for changelog popover + cy.get('.optional-content-container').should('be.visible'); + cy.get('.main-content-container').should('be.visible'); + cy.get('.close-icon > path').click(); + + // Check for download + cy.intercept('**/zipit/discover').as('changelogDownload') + cy.get('@icons').eq(1).click({ force: true }) + cy.get('@changelogDownload').should(({ request, response }) => { + expect(request.method).to.equal('POST') + expect(request.body.data.datasetId).to.equal(`${datasetId}`) + expect(response.statusCode).to.equal(200) + }) + } + }) + + // DOI link should reload page with correct version + cy.get(':nth-child(2) > .el-col-push-1 > a').click() + cy.origin('https://sparc.science', () => { + cy.url().should('contain', 'version') + cy.go('back') + }) + // cy.get('.el-col-push-1 > a').each(($link) => { + // cy.wrap($link).should('have.attr', 'href').and('include', 'doi.org').then((href) => { + // cy.request(href).then((resp) => { + // expect(resp.status).to.eq(200); + // expect(resp.body).to.include(`datasets/${datasetId}/version`); + // }) + // }); + // }) + } + }); + }); + }); +}); \ No newline at end of file diff --git a/tests/cypress/e2e/finddata.cy.js b/tests/cypress/e2e/finddata.cy.js new file mode 100644 index 00000000..3fac1064 --- /dev/null +++ b/tests/cypress/e2e/finddata.cy.js @@ -0,0 +1,301 @@ +// const categories = ['dataset'] +const categories = ['dataset', 'model', 'simulation', 'projects'] + +const limit = 20 + +const keywords = ['Spine', 'neck'] + +/** + * 1. + * If multiple facets are selected which includes one or more "ANATOMICAL STRUCTURE" parent facet, + * place it/them to the end of the array, + * this is to make sure the "ANATOMICAL STRUCTURE" child facet can be closed during "close tag" process. + * 2. + * If multiple facets are selected, + * all facets need to be matched, + * otherwise that test will be skipped. + */ +const facets = [['Human'], ['Heart', 'Adult']] + +categories.forEach((category) => { + + describe(`Find Data in ${category}`, { testIsolation: false }, function () { + before(function () { + cy.visit(`/data?type=${category}`) + }) + + it('Dataset card', function () { + if (category === 'projects') { + cy.get(':nth-child(1) > .el-table_1_column_1 > .cell > .image-container > .img-project').should('have.attr', 'src').and('contain', '//images.ctfassets.net/'); + cy.get(':nth-child(1) > .el-table_1_column_2 > .cell > .property-table > :nth-child(1) > .property-name-column').should('contain', 'Focus'); + cy.get(':nth-child(1) > .el-table_1_column_2 > .cell > .property-table > :nth-child(2) > .property-name-column').should('contain', 'Principle Investigator'); + cy.get(':nth-child(1) > .el-table_1_column_2 > .cell > .property-table > :nth-child(3) > .property-name-column').should('contain', 'Institution'); + cy.get(':nth-child(1) > .el-table_1_column_2 > .cell > .property-table > :nth-child(4) > .property-name-column').should('contain', 'Funding Program'); + cy.get(':nth-child(1) > .el-table_1_column_2 > .cell > .property-table > :nth-child(5) > .property-name-column').should('contain', 'Award'); + } else { + cy.get(':nth-child(1) > .el-table_1_column_1 > .cell > :nth-child(1) > .img-dataset > img').should('have.attr', 'src').and('contain', 'https://assets.discover.pennsieve.io/dataset-assets/') + cy.get(':nth-child(1) > .el-table_1_column_2 > .cell > :nth-child(1) > .property-table > :nth-child(1) > .property-name-column').should('contain', 'Anatomical Structure'); + cy.get(':nth-child(1) > .el-table_1_column_2 > .cell > :nth-child(1) > .property-table > :nth-child(2) > .property-name-column').should('contain', 'Species'); + cy.get(':nth-child(1) > .el-table_1_column_2 > .cell > :nth-child(1) > .property-table > :nth-child(3) > .property-name-column').should('contain', 'Experimental Approach'); + cy.get(':nth-child(1) > .el-table_1_column_2 > .cell > :nth-child(1) > .property-table > :nth-child(4) > .property-name-column').should('contain', 'Publication Date'); + } + }) + it('All Page Features', function () { + cy.get('h5').should('contain', 'Search within category'); + cy.get('.heading2').should('contain', 'Refine results'); + cy.get('.tags-container > .flex').should('contain', 'Filters applied'); + cy.get('.el-col-md-16 > :nth-child(1) > p').should('contain', 'Results | Showing'); + cy.get('.label1').should('contain', 'Sort'); + + /** + * Sort dropdown function testing + * Test whether the sort function can be triggered and text can be shown + */ + cy.get('.label1 > .el-dropdown > .filter-dropdown > .el-dropdown-text-link').click() + + // Change the order to 'Z-A' + cy.get('.el-dropdown-menu > .el-dropdown-menu__item:visible').contains('Z-A').click() + + // CHeck for the order + cy.get('.label1 > .el-dropdown > .filter-dropdown > .el-dropdown-text-link').should('contain', 'Z-A') + + /** + * Tooltips showup testing + * Test whether content will be displayed + */ + // Check for tooltip content + cy.get('.purple-fill').trigger('mouseenter', { eventConstructor: 'MouseEvent' }) + cy.get('[role="tooltip"]').should('be.visible') + cy.get('[role="tooltip"]:visible > .el-popover__title').should('have.text', 'How do filters work?') + cy.get('.purple-fill').trigger('mouseleave', { eventConstructor: 'MouseEvent' }) + cy.get('[role="tooltip"]').should('not.be.visible') + + cy.get('.label-header > :nth-child(1) > .label-title').then(($label) => { + if ($label.text().includes('Availability')) { + cy.get('.el-tooltip').trigger('mouseenter', { eventConstructor: 'MouseEvent' }) + cy.get('[role="tooltip"]').should('be.visible') + + // Check for tooltip content + cy.get('[role="tooltip"]').should('contain', 'SPARC') + + cy.get('.el-tooltip').trigger('mouseleave', { eventConstructor: 'MouseEvent' }) + cy.get('[role="tooltip"]').should('not.be.visible') + } + }) + + /** + * Dataset show testing + * Test whether the number of displayed datasets can be changed + */ + // Change the limit + cy.get(':nth-child(1) > p > .el-dropdown > .filter-dropdown').click() + cy.get('.el-dropdown-menu > .el-dropdown-menu__item:visible').contains(limit).click() + + // Check for limit change in URL + cy.url().should('contain', `limit=${limit}`) + cy.get('.el-table__row', { timeout: 30000 }).should('have.length', limit) + }) + + keywords.forEach((keyword) => { + + it(`Keyword Search - ${keyword}`, function () { + cy.intercept('**/query?**').as('query') + + cy.get('.el-input__inner').should('have.attr', 'placeholder', 'Enter search criteria') + + // Type keyword + cy.get('.el-input__inner').clear() + cy.get('.el-input__inner').type(keyword) + + // Check for clear search icon + cy.get('.btn-clear-search > .svg-icon').should('be.visible') + + // Click search button + cy.get('.search-text').click() + + // Check for keyword in URL + cy.url().should('contain', keyword) + + cy.wait('@query', { timeout: 20000 }) + + cy.get('.table-wrap.el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + + // Check for result + cy.get(':nth-child(1) > p').then(($result) => { + if ($result.text().includes(' 0 Results | Showing')) { + // Empty text should exist if no result + cy.get('.el-table__empty-text').should('exist').and('have.text', 'No Results') + } else { + cy.get('.table-wrap').then(($content) => { + const keywordExist = $content.text().toLowerCase().includes(keyword.toLowerCase()) + if (keywordExist) { + // Check for keyword + cy.wrap($content).contains(new RegExp(keyword, 'i')).should('exist') + + // Check for highlighted keyword + cy.get('b').contains(new RegExp(keyword, 'i')).should('exist') + } else { + // *** Ignore when keyword cannot be found or + // *** Find some other solutions in the future + } + }) + } + }) + // Clear search input + cy.get('.btn-clear-search > .svg-icon').click() + + // *** There are situations that dataset cards do not show the (highlighted) keywords + // *** Just in case this happens for all the displayed dataset cards, extra tests may need to be added + }) + }) + + facets.forEach((facetList) => { + + it(`Faceted Browse Search - ${facetList}`, function () { + cy.intercept('**/query?**').as('query') + cy.intercept('**/entries?**').as('entries') + + // Check for filters applied box + cy.get('.no-facets').should('contain', 'No filters applied') + + cy.wait(5000) + + // Expand all filters/facets + cy.get('.expand-all-container > .el-link > .el-link--inner').click() + cy.get('.label-content-container').should('be.visible').and('have.length.above', 0) + + // Expand nested facet menu item if facet not found + cy.get('.el-tree-node__content > .custom-tree-node > .capitalize:visible').then(($label) => { + let facetIsObserved = true + facetList.forEach((facet) => { + facetIsObserved = facetIsObserved && $label.text().toLowerCase().includes(facet.toLowerCase()) + }) + if (!facetIsObserved && category !== 'projects') { + // If the same facet are found in multiple place, the first will be checked by default + // This action is used to expand all parent facets in ANATOMICAL STRUCTURE + // To avoid facet not found when using child facets as test facets + // *** Need to think of a solution to open the specific parent facet, instead of open all + cy.get('.el-icon-caret-right:visible').not('.is-leaf').click({ multiple: true }) + } + }) + + cy.get('.el-tree-node__content > .custom-tree-node > .capitalize:visible').then(($label) => { + let facetIsObserved = true + facetList.forEach((facet) => { + facetIsObserved = facetIsObserved && $label.text().toLowerCase().includes(facet.toLowerCase()) + }) + if (!facetIsObserved && category !== 'projects') { + // If the same facet are found in multiple place, the first will be checked by default + // This action is used to expand all parent facets in ANATOMICAL STRUCTURE + // To avoid facet not found when using child facets as test facets + // *** Need to think of a solution to open the specific parent facet, instead of open all + cy.get('.el-icon-caret-right:visible').not('.is-leaf').click({ multiple: true }) + } + if (facetIsObserved) { + facetList.forEach((facet) => { + // Check the matched facet checkbox + cy.wrap($label).contains(new RegExp(`^${facet}$`, 'i')).click() + + // Check for the number of facet tags in filters applied box + cy.get('.el-card__body > .capitalize:visible').contains(new RegExp(facet, 'i')).should('exist') + }) + + // Check for URL + if (category === 'projects') { + cy.url().should('contain', 'selectedProjectsAnatomicalFocusIds') + cy.wait('@entries', { timeout: 20000 }) + } else { + cy.url().should('contain', 'selectedFacetIds') + cy.wait('@query', { timeout: 20000 }) + } + + cy.get('.table-wrap.el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + + // Check for result correctness + cy.get(':nth-child(1) > p').then(($result) => { + if ($result.text().includes(' 0 Results | Showing')) { + // Empty text should exist if no result + cy.get('.el-table__empty-text').should('exist').and('have.text', 'No Results') + } else { + // Check for facets exist in dataset card + cy.get('.property-table').then(($content) => { + facetList.forEach((facet) => { + const facetExistInCard = $content.text().toLowerCase().includes(facet.toLowerCase()) + if (facetExistInCard) { + cy.wrap($content).contains(new RegExp(facet, 'i')).should('exist') + } else { + // *** Ignore when facets cannot be found or + // *** Find some other solutions in the future + } + }) + }) + } + }) + + for (let index = 0; index < 2; index++) { + if (index === 1) { + // Combine with search + cy.get('.el-input__inner').clear() + cy.get('.el-input__inner').type('dataset') + facetList.forEach((facet) => { + cy.wrap($label).contains(new RegExp(`^${facet}$`, 'i')).click() + }) + } + + // Uncheck + facetList.forEach((facet) => { + cy.wrap($label).contains(new RegExp(`^${facet}$`, 'i')).click() + }) + cy.get('.el-card__body > .capitalize').should('not.exist') + cy.get('.no-facets').should('contain', 'No filters applied') + cy.url().should('not.contain', 'selectedFacetIds') + + // Close all tags in order + facetList.forEach((facet) => { + cy.wrap($label).contains(new RegExp(`^${facet}$`, 'i')).click() + }) + facetList.forEach((facet) => { + // Close all facet tags in filters applied box + cy.get('.el-card__body > .capitalize:visible').contains(new RegExp(facet, 'i')).within(() => { + cy.get('.el-tag__close').click() + }) + }) + cy.get('.el-card__body > .capitalize').should('not.exist') + cy.get('.no-facets').should('contain', 'No filters applied') + cy.url().should('not.contain', 'selectedFacetIds') + + // Reset all + facetList.forEach((facet) => { + cy.wrap($label).contains(new RegExp(`^${facet}$`, 'i')).click() + }) + cy.get('.tags-container > .flex > .el-link > .el-link--inner').click() + cy.get('.el-card__body > .capitalize').should('not.exist') + cy.get('.no-facets').should('contain', 'No filters applied') + cy.url().should('not.contain', 'selectedFacetIds') + + // Close the child facet tag and then click reset all + facetList.forEach((facet) => { + cy.wrap($label).contains(new RegExp(`^${facet}$`, 'i')).click() + }) + cy.get('.el-card__body > .capitalize').then(($tag) => { + if ($tag.length > 1) { + cy.get('.el-tag__close').last().click() + cy.get('.tags-container > .flex > .el-link > .el-link--inner').click() + cy.get('.el-card__body > .capitalize').should('not.exist') + cy.get('.no-facets').should('contain', 'No filters applied') + cy.url().should('not.contain', 'selectedFacetIds') + } else { + facetList.forEach((facet) => { + cy.wrap($label).contains(new RegExp(`^${facet}$`, 'i')).click() + }) + } + }) + } + } else { + this.skip() + } + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/homepage.cy.js b/tests/cypress/e2e/homepage.cy.js new file mode 100644 index 00000000..74a8f207 --- /dev/null +++ b/tests/cypress/e2e/homepage.cy.js @@ -0,0 +1,133 @@ +describe('Homepage', { testIsolation: false }, function () { + before(function () { + cy.visit('') + }) + + it('Navigation Bar', function () { + // Check for navigation bar + cy.get('.mobile-navigation > :nth-child(1) > :nth-child(1) > a').should('contain', 'Data & Models').and('have.attr', 'href', '/data?type=dataset') + cy.get('.mobile-navigation > :nth-child(1) > :nth-child(2) > a').should('contain', 'Tools & Resources').and('have.attr', 'href', '/resources') + cy.get('.mobile-navigation > :nth-child(1) > :nth-child(3) > a').should('contain', 'Maps').and('have.attr', 'href', '/maps') + cy.get('.mobile-navigation > :nth-child(1) > :nth-child(4) > a').should('contain', 'News & Events').and('have.attr', 'href', '/news-and-events') + cy.get(':nth-child(1) > :nth-child(5) > a').should('contain', 'About').and('have.attr', 'href', '/about') + cy.get(':nth-child(1) > :nth-child(6) > a').should('contain', 'Submit to SPARC').and('have.attr', 'href', '/share-data') + }) + it('Page hero', function () { + // Check for banner + cy.get('h1').should('contain', 'SPARC') + cy.get('[class="page-hero-img"]').should('exist') + + // Check for button function + cy.get('.btn-link > .el-button').should('contain', 'Submit to SPARC') + cy.get('.btn-link > .el-button').click() + cy.url().should('contain', 'share-data') + cy.get('.mobile-navigation > :nth-child(1) > :nth-child(6) > a').should('have.class', 'active') + cy.go('back') + }) + it('Featured data', function () { + // Check for content title + cy.get('.featured-data > h2').should('have.text', 'Find Data by Category') + + cy.get('.data-wrap > a:visible').as('category') + + cy.get('@category').first().click() + cy.url().should('contain', 'selectedFacetIds') + cy.visit('') + + // Check for the number of categories + cy.get('@category').should('have.length', 6) + + // Show more categories + cy.get('.featured-data > .el-button').should('have.text', '\n View more\n ') + cy.get('.featured-data > .el-button > span').click() + + // Check for the number of categories after showing more + cy.get('@category').should('have.length.above', 6) + + // Show less categories + cy.get('.featured-data > .el-button > span').should('have.text', '\n View less\n ') + cy.get('.featured-data > .el-button > span').click() + + // Check for the number of categories after showing less + cy.get('@category').should('have.length', 6) + }) + it('Portal features', function () { + // Check for the number of features + cy.get('.feature-container').should('have.length', 4) + + // Check for feature card + cy.get(':nth-child(1) > .feature-container').within(() => { + cy.get('.icon').should('exist') + cy.get('.heading2').should('exist') + cy.get('.body1').should('exist') + cy.get('.button-link > .el-button > span').should('exist') + }) + + // Check for button function + cy.get(':nth-child(1) > .feature-container > .button-link > .el-button').click() + cy.url().should('contain', 'data?type=dataset') + cy.get('.mobile-navigation > :nth-child(1) > :nth-child(1) > a').should('have.class', 'active') + cy.go('back') + }) + it('Projects and datasets', function () { + // Check for content title + cy.get(':nth-child(6) > .section-container > .heading2').should('contain', 'Resources & Datasets') + + // Check for card description + cy.get('.row > :nth-child(1) > .mb-16').should('contain', 'you might be interested in:') + cy.get('.row > :nth-child(2) > .mb-16').should('have.text', 'Featured Datasets') + + // Check for card content + cy.get(':nth-child(1) > .card-container > .el-row').within(() => { + cy.get('.el-col-6 > .image-container').should('exist') + cy.get('.el-col-18 > .dataset-name').should('exist') + cy.get('.el-col-18 > .dataset-description').should('exist') + cy.get('.el-col-18 > .button-link > .el-button').should('exist') + }) + + // Check for card 'view all' link + cy.get('.row > :nth-child(1) > .view-all-link').should('contain', 'View All') + cy.get(':nth-child(2) > .view-all-link').should('contain', 'View All Datasets') + + // Check for button redirect to dataset + cy.get(':nth-child(2) > .card-container > .el-row > .el-col-18 > .dataset-name').then(($link)=>{ + const title = $link.text().replace('\n', '').trim() + cy.get(':nth-child(2) > .card-container > .el-row > .el-col-18 > .button-link > .el-button').click() + cy.contains(title).should('exist') + }) + cy.visit('') + }) + it('Homepage news', function () { + // Check for content title + cy.get('.featured-datasets > .heading2').should('contain', 'News & Upcoming Events') + + // Check for card image + cy.get('.sparc-card__image').should('exist') + + // Check for card title + cy.get('h3 > a').should('exist') + + // Check for card subtitle + cy.get('.markdown-text > p').should('exist') + cy.get(':nth-child(2) > .el-button').should('contain', 'Learn More') + + // Check for card 'view all' link + cy.get('.sparc-card__content-wrap__content > .view-all-link').should('exist') + }) + it('Stay connected', function () { + // Check for content title + cy.get('.subheader').should('have.text', 'Stay Connected') + + // Check for content + cy.get('.newsletter-wrap > .heading2').should('have.text', 'Sign up for the SPARC Newsletter') + cy.get('.office-hours-column > .heading2').should('have.text', 'Open Office Hours') + }) + it('Footer', function () { + cy.get('.footer__links > :nth-child(1) > :nth-child(1) > h3').should('have.text', 'Learn More') + cy.get(':nth-child(1) > :nth-child(2) > h3').should('have.text', 'Policies') + cy.get(':nth-child(2) > :nth-child(1) > h3').should('have.text', 'Help Us Improve') + cy.get(':nth-child(2) > :nth-child(2) > h3').should('have.text', 'Stay Up-to-Date') + cy.get('.footer__info--logo > .nuxt-link-exact-active > .logo').should('have.attr', 'src').and('contain', 'logo-sparc-wave-primary') + cy.get('.footer__info--blurb > p').should('contain', 'The NIH Common') + }) +}) diff --git a/tests/cypress/e2e/mapviewer.cy.js b/tests/cypress/e2e/mapviewer.cy.js new file mode 100644 index 00000000..47adf11b --- /dev/null +++ b/tests/cypress/e2e/mapviewer.cy.js @@ -0,0 +1,175 @@ +// Human Female, Human Male, Rat, Mouse, Pig, Cat +// const taxonModels = ['Rat'] +const taxonModels = ['Rat', 'Human Female'] +// x: The distance in pixels from the element's left +// y: The distance in pixels from the element's top +// central coordinate { 'x': 768, 'y': 373 } +const coordinate = { 'x': 800, 'y': 333 } +const pixelChange = 3 + +const threeDSyncView = 'Human Male' + +const searchInput = 'heart' + +// const datasetIds = [150] +const datasetIds = [150, 155] + +describe('Maps Viewer', { testIsolation: false }, function () { + before(function () { + cy.visit('/maps?type=ac') + }) + + taxonModels.forEach((model) => { + + it(`Provenance card for ${model}`, function () { + cy.intercept('**/flatmap/**').as('flatmap') + + // Loading mask should not exist after the new flatmap is loaded + cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + + if (model !== 'Rat') { + // Switch to the second flatmap + cy.get('#flatmap-select').click() + cy.get('.el-select-dropdown__item').should('be.visible') + cy.get('.el-select-dropdown__item:visible').contains(new RegExp(model, 'i')).click({ force: true }) + } + + cy.wait('@flatmap', { timeout: 20000 }) + + // Loading mask should not exist after the new flatmap is loaded + cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + + // Hide organs and outlines + cy.get('.settings-group > :nth-child(2):visible').click({ waitForAnimations: false }) + cy.get('[role="radiogroup"] > .el-radio:visible').not('.is-checked').click({ multiple: true }); + cy.get('.settings-group > :nth-child(2):visible').click({ waitForAnimations: false }) + + let coorX = coordinate.x + let coorY = coordinate.y + cy.get('[style="height: 100%;"] > [style="height: 100%; width: 100%; position: relative;"] > [style="height: 100%; width: 100%;"] > .maplibregl-touch-drag-pan > .maplibregl-canvas').as('canvas'); + // Open a provenance card + const clickNeuron = () => { + cy.get('@canvas').click(coorX, coorY) + + cy.wait(5000) + + cy.get('body').then(($body) => { + if ($body.find('.maplibregl-popup-close-button').length > 0) { + cy.wrap($body).find('.maplibregl-popup-content > .tooltip-container > .el-main', { timeout: 30000 }).within(() => { + + // Check for the popover provenance card content + cy.get('.title').should('exist') + cy.get('.subtitle').should('exist') + cy.get('.attribute-title').should('exist') + cy.get('.attribute-content').should('exist') + }) + // Close the provenance card + cy.get('.maplibregl-popup-close-button').click({ force: true }) + } else { + coorX -= pixelChange + clickNeuron() + } + }) + } + clickNeuron() + }) + }) + it(`From 2D ${threeDSyncView}, open 3D map for synchronised view and Search within display`, function () { + cy.intercept('**/flatmap/**').as('flatmap') + cy.intercept('**/get_body_scaffold_info/**').as('get_body_scaffold_info') + cy.intercept('**/s3-resource/**').as('s3-resource') + + // Loading mask should not exist after the default flatmap is loaded + cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + + // Switch to the human related flatmap + cy.get('#flatmap-select').click() + cy.get('.el-select-dropdown__item').contains(new RegExp(threeDSyncView, 'i')).click({ force: true }) + + cy.wait('@flatmap', { timeout: 20000 }) + + // Loading mask should not exist after the new flatmap is loaded + cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + + // Open the 3D view in a split viewer + cy.get('.settings-group > :nth-child(1):visible').contains(/Open new map/i).should('exist') + cy.get('.settings-group > :nth-child(1):visible').click() + cy.get('.open-map-popper:visible > :nth-child(4) > .el-button').contains(/Open Sync Map/i).should('exist') + cy.get('.open-map-popper:visible > :nth-child(4) > .el-button').click() + + cy.wait(['@get_body_scaffold_info', '@s3-resource'], { timeout: 20000 }) + + // Check for the number of displayed viewers + cy.get('.toolbar > .toolbar-flex-container', { timeout: 30000 }).should('have.length', 2) + + // Check for 3D view's content card detail + cy.get('.context-card > .card-left > .context-image', { timeout: 30000 }).should('exist') + cy.get('.context-card > .card-right', { timeout: 30000 }).within(() => { + cy.get('.title').contains(/3D human whole-body/i).should('exist') + cy.get(':nth-child(2) > p').contains(/Visualization/i).should('exist') + cy.get('.subtitle').contains(/Scaffold Views/i).should('exist') + cy.get('.view-image').should('exist') + cy.get('.view-description').contains(/Human whole-body/i).should('exist') + }) + + // Close the pathway sidebar + cy.get('[style="height: 100%;"] > [style="height: 100%; width: 100%; position: relative;"] > .pathway-location > .drawer-button > .el-icon-arrow-left').click() + + // Search keyword in displayed viewers + cy.get('.el-autocomplete > .el-input > .el-input__inner').type(searchInput) + cy.get('.search-container > .map-icon > use').click() + + // Check for keyword(highlighted part) in displayed viewers + cy.get('.maplibregl-popup-content').contains(new RegExp(searchInput, 'i')).should('exist') + + cy.visit('/maps?type=ac') + }) + + datasetIds.forEach((datasetId) => { + + it(`Context card in sidebar for scaffold dataset ${datasetId}`, function () { + cy.intercept('**/query?**').as('query') + cy.intercept('**/dataset_info/**').as('dataset_info') + cy.intercept('**/datasets/**').as('datasets') + + // Open the sidebar + cy.get('.open-tab > .el-icon-arrow-left').click() + + // Search dataset id + cy.get('.search-input > .el-input__inner').clear() + cy.get('.search-input > .el-input__inner').type(datasetId) + cy.get('.header > .el-button > span').click() + + cy.wait('@query', { timeout: 20000 }) + + cy.get('.dataset-results-feedback').then(($result) => { + const noResult = $result.text() === '0 results | Showing' + if (noResult) { + // Error message should exist if no result + cy.get('.error-feedback').should('exist') + cy.get('.error-feedback').contains(/No results found/i).should('exist') + } else { + cy.wait(['@dataset_info', '@datasets'], { timeout: 20000 }) + + // Check for search result and the tag 'Scaffold' + cy.get('.dataset-card-container > .dataset-card', { timeout: 30000 }).contains(datasetId).should('exist') + cy.get('.dataset-card-container > .dataset-card').filter(`:contains(${datasetId})`).within(() => { + cy.get('.badges-container > .container', { timeout: 30000 }).contains(/Scaffold/i).should('exist') + cy.get('.badges-container > .container').contains(/Scaffold/i).click() + }) + + // Check for button text + cy.get('.dataset-card-container > .dataset-card', { timeout: 30000 }).contains(/View Scaffold/i).should('exist').click() + + // Loading mask should not exist after the scaffold is loaded + cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + + // Check for context card + cy.get('.context-card').should('be.visible') + cy.get('.context-image:visible').should('have.attr', 'src').and('contain', `https://assets.discover.pennsieve.io/dataset-assets/${datasetId}`) + cy.get('[style="margin-right: 8px;"] > .title:visible').should('have.class', 'title') + } + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/userstories.cy.js b/tests/cypress/e2e/userstories.cy.js new file mode 100644 index 00000000..4b1e2f4b --- /dev/null +++ b/tests/cypress/e2e/userstories.cy.js @@ -0,0 +1,166 @@ +// To check the segmentation card +// should use datasets which have segmentation data +const segmentationDatasetIds = [226, 77] +const scaffoldDatasetCategories = ['heart', 'stomach'] +const scaffoldUseFlowSearchInput = 'scaffold' +const categories = ['stomach', 'lung'] + +describe('User stories', function () { + describe('Should find segmentation in the gallery', { testIsolation: false }, function () { + before('Loading Datasets', function () { + cy.intercept('**/query?**').as('query'); + cy.visit(''); + cy.wait('@query', { timeout: 20000 }); + + // Navigate to 'Data&Models' page + cy.get('.mobile-navigation > :nth-child(1) > :nth-child(1) > a').click(); + }) + + segmentationDatasetIds.forEach((id) => { + it(`Access dataset ${id}`, function () { + // Search for segmentation related dataset + cy.get('.el-input__inner').clear(); + cy.get('.search-text').click(); + cy.get('.el-table__row', { timeout: 30000 }).should('have.length', 10) + + cy.get('.el-input__inner').type(id); + cy.get('.search-text').click(); + + cy.get('.el-table__row', { timeout: 30000 }).should('have.length', 1).first().as('dataset'); + + // Enter the dataset + cy.get('@dataset').find('.cell > :nth-child(1) > a').last().click(); + + // Enter the 'Gallery' tab + cy.get(':nth-child(5) > .style1', { timeout: 30000 }).click(); + cy.get('.gallery-container > .description-info > p > strong', { timeout: 30000 }).should('have.text', 'Data collection:'); + + // Check for segmentation + cy.findGalleryCard('Segmentation', 'prev'); + cy.get('.el-card > .el-card__body > :nth-child(1) > .details > :nth-child(1) > b').should('contain', 'Segmentation'); + cy.get('.el-card > .el-card__body > :nth-child(1) > .details > .el-button > span').should('contain', ' View Segmentation'); + + cy.goBackToBrowser('dataset'); + }) + }) + }) + describe('Should open scaffold through the gallery', { testIsolation: false }, function () { + before('Loading Anatomical Models', function () { + cy.intercept('**/query?**').as('query'); + cy.visit(''); + cy.wait('@query', { timeout: 20000 }); + + // Navigate to 'Data&Models' page + cy.get('.mobile-navigation > :nth-child(1) > :nth-child(1) > a').click(); + + // Go to 'Anatomical Models' + cy.get(':nth-child(2) > .search-tabs__button').click(); + cy.get(':nth-child(2) > .search-tabs__button').should('have.class', 'active'); + }) + + scaffoldDatasetCategories.forEach((category) => { + it(`Access scaffold ${category}`, function () { + // Search for scaffold related dataset + cy.get('.el-input__inner').clear(); + cy.get('.search-text').click(); + cy.get('.el-table__row', { timeout: 30000 }).should('have.length', 10) + + cy.get('.el-input__inner').type(category); + cy.get('.search-text').click(); + + cy.get('.el-table__row', { timeout: 30000 }).first().as('dataset'); + + // Enter the dataset + cy.get('@dataset').find('.cell > :nth-child(1) > a', { timeout: 30000 }).last().click(); + + // Enter the 'Gallery' tab + cy.get(':nth-child(5) > .style1', { timeout: 30000 }).click(); + cy.get('.gallery-container > .description-info > p > strong', { timeout: 30000 }).should('have.text', 'Data collection:'); + + // Check for scaffold + cy.findGalleryCard('Scaffold', 'prev'); + cy.get('.el-card > .el-card__body > :nth-child(1) > .details > :nth-child(1) > b').contains('Scaffold').should('exist'); + cy.get('.el-card > .el-card__body > :nth-child(1) > .details > .el-button > span').contains('View Scaffold').should('exist').as('scaffold'); + + // cy.get('@scaffold').first().click() + // Alternative solution + cy.url().then(($url) => { + const datasetId = $url.substring($url.lastIndexOf("/") + 1, $url.indexOf("?")); + cy.get('.dataset-information-box > :nth-child(1)').then(($version) => { + cy.intercept('**/query?**').as('query'); + cy.intercept('**/dataset_info/**').as('dataset_info'); + cy.intercept('**/datasets/**').as('datasets'); + + const version = $version.text().match(/[0-9]+/); + cy.visit(`/maps?type=scaffold&dataset_id=${datasetId}&dataset_version=${version}`); + + cy.wait('@query', { timeout: 20000 }); + + // Search dataset id + cy.get('.search-input > .el-input__inner').clear(); + cy.get('.search-input > .el-input__inner').type(datasetId); + cy.get('.header > .el-button').click(); + + cy.wait(['@dataset_info', '@datasets'], { timeout: 20000 }); + + // Check for search result and the tag 'Scaffold' + cy.get('.dataset-card-container > .dataset-card:visible', { timeout: 30000 }).as('datasetCards'); + + cy.get('@datasetCards').filter(`:contains(${datasetId})`).within(() => { + cy.get('.badges-container > .container', { timeout: 30000 }).contains(/Scaffold/i).click(); + }); + + cy.get('@datasetCards').contains(/View Scaffold/i).click(); + + // Loading mask should not exist after the scaffold is loaded + cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist'); + + // Check for context card + cy.get('.context-card').should('be.visible'); + cy.get('.context-image').should('have.attr', 'src').and('contain', datasetId); + cy.get('[style="margin-right: 8px;"] > .title').should('have.class', 'title'); + + cy.get('.open-tab > .el-icon-arrow-left').click(); + + cy.get('@datasetCards').contains(/All/i).click(); + + // cy.get('@datasetCards').contains(/View Dataset/i).click(); + // Alternative solution + cy.visit(`/datasets/${datasetId}?type=dataset`); + }) + }) + cy.goBackToBrowser('model'); + }) + }) + }) + describe('Should find data by category', { testIsolation: false }, function () { + before('Visit homepage', function () { + cy.visit(''); + }) + categories.forEach((category) => { + it(`Filter datasets by ${category}`, function () { + cy.intercept('**/query?**').as('query'); + + // Expand all cateories + cy.get('.featured-data > .el-button > span').click(); + cy.get('.data-wrap').should('be.visible'); + + // Check for category exist + const regex = new RegExp(category, 'i') + cy.get('.data-wrap > a > p').contains(regex).as('facetsCategory'); + cy.get('@facetsCategory').should('be.visible'); + cy.get('@facetsCategory').click(); + + cy.wait('@query', { timeout: 20000 }); + cy.get('.cell > :nth-child(1) > .property-table > :nth-child(1) > :nth-child(2)', { timeout: 30000 }).first().contains(regex).should('exist'); + + // Check for detail page + cy.get('.el-table__row', { timeout: 30000 }).first().as('dataset'); + cy.get('@dataset').find('.cell > :nth-child(1) > a').last().click(); + cy.contains(regex).should('have.length.above', 0); + cy.goBackToBrowser('dataset'); + cy.go('back'); + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js index 66ea16ef..f8d6d5e9 100644 --- a/tests/cypress/support/commands.js +++ b/tests/cypress/support/commands.js @@ -22,4 +22,56 @@ // // // -- This will overwrite an existing command -- -// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) \ No newline at end of file +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) + +Cypress.on('uncaught:exception', (err, runnable) => { + // returning false here prevents Cypress from + // failing the test + if (err.message.includes('Avoided redundant navigation to current location')) + return false + if (err.message.includes('Maximum iterations reached.')) + return false + if (err.message.includes('ResizeObserver loop limit exceeded')) + return false + if (err.message.includes('config is not defined')) + return false + // // For legacy dataset + // if (err.message.includes('ObjectID does not exist')) + // return false + return true + }) + + Cypress.Commands.add('findGalleryCard', (text, dir) => { + let direction = '.btn-next' + const clickNextPageButton = () => { + cy.get('.el-card > .el-card__body').then(($card) => { + if (!$card.text().includes(text)) { + cy.get(direction).then(($button) => { + if ($button.is(":disabled")) { + return + } else { + cy.wrap($button).click() + clickNextPageButton() + } + }) + } + }) + } + if (dir === 'prev') { + cy.get('.el-pager > .number').last().click() + direction = '.btn-prev' + } + clickNextPageButton() + }) + + Cypress.Commands.add('goBackToBrowser', (category) => { + const goBack = () => { + cy.url().then(($url) => { + if (!$url.includes(`data?type=${category}`)) { + cy.go('back') + goBack() + } + }) + } + goBack() + }) \ No newline at end of file From 228cf12b981cd718170eb792ab3cd7a46daf9d85 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Mon, 4 Mar 2024 13:44:03 +1300 Subject: [PATCH 04/44] update homepage testings --- tests/cypress/e2e/homepage.cy.js | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/tests/cypress/e2e/homepage.cy.js b/tests/cypress/e2e/homepage.cy.js index 74a8f207..b2fe04d0 100644 --- a/tests/cypress/e2e/homepage.cy.js +++ b/tests/cypress/e2e/homepage.cy.js @@ -5,7 +5,7 @@ describe('Homepage', { testIsolation: false }, function () { it('Navigation Bar', function () { // Check for navigation bar - cy.get('.mobile-navigation > :nth-child(1) > :nth-child(1) > a').should('contain', 'Data & Models').and('have.attr', 'href', '/data?type=dataset') + cy.get('.mobile-navigation > :nth-child(1) > :nth-child(1) > a').should('contain', 'Data & Models').and('have.attr', 'href', '/data') cy.get('.mobile-navigation > :nth-child(1) > :nth-child(2) > a').should('contain', 'Tools & Resources').and('have.attr', 'href', '/resources') cy.get('.mobile-navigation > :nth-child(1) > :nth-child(3) > a').should('contain', 'Maps').and('have.attr', 'href', '/maps') cy.get('.mobile-navigation > :nth-child(1) > :nth-child(4) > a').should('contain', 'News & Events').and('have.attr', 'href', '/news-and-events') @@ -16,13 +16,6 @@ describe('Homepage', { testIsolation: false }, function () { // Check for banner cy.get('h1').should('contain', 'SPARC') cy.get('[class="page-hero-img"]').should('exist') - - // Check for button function - cy.get('.btn-link > .el-button').should('contain', 'Submit to SPARC') - cy.get('.btn-link > .el-button').click() - cy.url().should('contain', 'share-data') - cy.get('.mobile-navigation > :nth-child(1) > :nth-child(6) > a').should('have.class', 'active') - cy.go('back') }) it('Featured data', function () { // Check for content title @@ -30,22 +23,24 @@ describe('Homepage', { testIsolation: false }, function () { cy.get('.data-wrap > a:visible').as('category') + cy.get('@category').each(($cat) => { + cy.wrap($cat).should('have.attr', 'href').and('contain', 'selectedFacetIds') + }) cy.get('@category').first().click() - cy.url().should('contain', 'selectedFacetIds') cy.visit('') // Check for the number of categories cy.get('@category').should('have.length', 6) // Show more categories - cy.get('.featured-data > .el-button').should('have.text', '\n View more\n ') + cy.get('.featured-data > .el-button').should('have.text', 'View more') cy.get('.featured-data > .el-button > span').click() // Check for the number of categories after showing more cy.get('@category').should('have.length.above', 6) // Show less categories - cy.get('.featured-data > .el-button > span').should('have.text', '\n View less\n ') + cy.get('.featured-data > .el-button > span').should('have.text', 'View less') cy.get('.featured-data > .el-button > span').click() // Check for the number of categories after showing less @@ -127,7 +122,7 @@ describe('Homepage', { testIsolation: false }, function () { cy.get(':nth-child(1) > :nth-child(2) > h3').should('have.text', 'Policies') cy.get(':nth-child(2) > :nth-child(1) > h3').should('have.text', 'Help Us Improve') cy.get(':nth-child(2) > :nth-child(2) > h3').should('have.text', 'Stay Up-to-Date') - cy.get('.footer__info--logo > .nuxt-link-exact-active > .logo').should('have.attr', 'src').and('contain', 'logo-sparc-wave-primary') + cy.get('.footer__info--logo > .router-link-active > .logo').should('have.attr', 'alt').and('contain', 'Logo for SPARC') cy.get('.footer__info--blurb > p').should('contain', 'The NIH Common') }) }) From f1c4cf6688296816d1c2766495a8e4e495e9772d Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Mon, 11 Mar 2024 15:06:25 +1300 Subject: [PATCH 05/44] update mapviewer testings there is an bug in mapviewer, will need to re-check testing cases once new release is updated. --- tests/cypress/e2e/mapviewer.cy.js | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/tests/cypress/e2e/mapviewer.cy.js b/tests/cypress/e2e/mapviewer.cy.js index 47adf11b..97eb8951 100644 --- a/tests/cypress/e2e/mapviewer.cy.js +++ b/tests/cypress/e2e/mapviewer.cy.js @@ -49,13 +49,30 @@ describe('Maps Viewer', { testIsolation: false }, function () { cy.get('[style="height: 100%;"] > [style="height: 100%; width: 100%; position: relative;"] > [style="height: 100%; width: 100%;"] > .maplibregl-touch-drag-pan > .maplibregl-canvas').as('canvas'); // Open a provenance card const clickNeuron = () => { + /** + * ================================================================== + * Below is used to avoid the tooltip not display for the first click + * Can be removed if the popup logic updated + */ cy.get('@canvas').click(coorX, coorY) - + cy.wait(5000) + cy.get('body').then(($body) => { + if ($body.find('.maplibregl-popup-close-button').length > 0) { + // Close the provenance card + cy.get('.maplibregl-popup-close-button').click({ force: true }) + } + }) + /** + * ================================================================== + */ + + cy.get('@canvas').click(coorX, coorY) + cy.wait(5000) cy.get('body').then(($body) => { if ($body.find('.maplibregl-popup-close-button').length > 0) { - cy.wrap($body).find('.maplibregl-popup-content > .tooltip-container > .el-main', { timeout: 30000 }).within(() => { + cy.wrap($body).find('.maplibregl-popup-content > .tooltip-container > .main', { timeout: 30000 }).within(() => { // Check for the popover provenance card content cy.get('.title').should('exist') @@ -74,6 +91,7 @@ describe('Maps Viewer', { testIsolation: false }, function () { clickNeuron() }) }) + it(`From 2D ${threeDSyncView}, open 3D map for synchronised view and Search within display`, function () { cy.intercept('**/flatmap/**').as('flatmap') cy.intercept('**/get_body_scaffold_info/**').as('get_body_scaffold_info') @@ -133,11 +151,11 @@ describe('Maps Viewer', { testIsolation: false }, function () { cy.intercept('**/datasets/**').as('datasets') // Open the sidebar - cy.get('.open-tab > .el-icon-arrow-left').click() + cy.get('.open-tab > .el-icon').click() // Search dataset id - cy.get('.search-input > .el-input__inner').clear() - cy.get('.search-input > .el-input__inner').type(datasetId) + cy.get('.search-input > .el-input__wrapper').clear() + cy.get('.search-input > .el-input__wrapper').type(datasetId) cy.get('.header > .el-button > span').click() cy.wait('@query', { timeout: 20000 }) From eb08f76cab56357f9495c7b9d824076c0930c289 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Mon, 11 Mar 2024 15:10:53 +1300 Subject: [PATCH 06/44] update footer content test assert --- tests/cypress/e2e/homepage.cy.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/cypress/e2e/homepage.cy.js b/tests/cypress/e2e/homepage.cy.js index b2fe04d0..3b153163 100644 --- a/tests/cypress/e2e/homepage.cy.js +++ b/tests/cypress/e2e/homepage.cy.js @@ -12,11 +12,13 @@ describe('Homepage', { testIsolation: false }, function () { cy.get(':nth-child(1) > :nth-child(5) > a').should('contain', 'About').and('have.attr', 'href', '/about') cy.get(':nth-child(1) > :nth-child(6) > a').should('contain', 'Submit to SPARC').and('have.attr', 'href', '/share-data') }) + it('Page hero', function () { // Check for banner cy.get('h1').should('contain', 'SPARC') cy.get('[class="page-hero-img"]').should('exist') }) + it('Featured data', function () { // Check for content title cy.get('.featured-data > h2').should('have.text', 'Find Data by Category') @@ -46,6 +48,7 @@ describe('Homepage', { testIsolation: false }, function () { // Check for the number of categories after showing less cy.get('@category').should('have.length', 6) }) + it('Portal features', function () { // Check for the number of features cy.get('.feature-container').should('have.length', 4) @@ -64,6 +67,7 @@ describe('Homepage', { testIsolation: false }, function () { cy.get('.mobile-navigation > :nth-child(1) > :nth-child(1) > a').should('have.class', 'active') cy.go('back') }) + it('Projects and datasets', function () { // Check for content title cy.get(':nth-child(6) > .section-container > .heading2').should('contain', 'Resources & Datasets') @@ -92,6 +96,7 @@ describe('Homepage', { testIsolation: false }, function () { }) cy.visit('') }) + it('Homepage news', function () { // Check for content title cy.get('.featured-datasets > .heading2').should('contain', 'News & Upcoming Events') @@ -109,6 +114,7 @@ describe('Homepage', { testIsolation: false }, function () { // Check for card 'view all' link cy.get('.sparc-card__content-wrap__content > .view-all-link').should('exist') }) + it('Stay connected', function () { // Check for content title cy.get('.subheader').should('have.text', 'Stay Connected') @@ -117,12 +123,13 @@ describe('Homepage', { testIsolation: false }, function () { cy.get('.newsletter-wrap > .heading2').should('have.text', 'Sign up for the SPARC Newsletter') cy.get('.office-hours-column > .heading2').should('have.text', 'Open Office Hours') }) + it('Footer', function () { cy.get('.footer__links > :nth-child(1) > :nth-child(1) > h3').should('have.text', 'Learn More') cy.get(':nth-child(1) > :nth-child(2) > h3').should('have.text', 'Policies') cy.get(':nth-child(2) > :nth-child(1) > h3').should('have.text', 'Help Us Improve') cy.get(':nth-child(2) > :nth-child(2) > h3').should('have.text', 'Stay Up-to-Date') cy.get('.footer__info--logo > .router-link-active > .logo').should('have.attr', 'alt').and('contain', 'Logo for SPARC') - cy.get('.footer__info--blurb > p').should('contain', 'The NIH Common') + cy.get('.footer__info--blurb > p').should('contain', 'The open community platform for bridging the body and the brain through neuroscience and systems physiology data, computational and spatial modeling, and device design.') }) }) From 38db888c7a3fcfa50c118598e02c5f0c0d72f9db Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 19 Mar 2024 11:15:13 +1300 Subject: [PATCH 07/44] update user flow testings --- tests/cypress/e2e/userstories.cy.js | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/tests/cypress/e2e/userstories.cy.js b/tests/cypress/e2e/userstories.cy.js index 4b1e2f4b..dd2469ef 100644 --- a/tests/cypress/e2e/userstories.cy.js +++ b/tests/cypress/e2e/userstories.cy.js @@ -1,8 +1,7 @@ // To check the segmentation card // should use datasets which have segmentation data const segmentationDatasetIds = [226, 77] -const scaffoldDatasetCategories = ['heart', 'stomach'] -const scaffoldUseFlowSearchInput = 'scaffold' +const scaffoldDatasetCategories = ['stomach', 'heart'] const categories = ['stomach', 'lung'] describe('User stories', function () { @@ -17,6 +16,7 @@ describe('User stories', function () { }) segmentationDatasetIds.forEach((id) => { + it(`Access dataset ${id}`, function () { // Search for segmentation related dataset cy.get('.el-input__inner').clear(); @@ -40,10 +40,11 @@ describe('User stories', function () { cy.get('.el-card > .el-card__body > :nth-child(1) > .details > :nth-child(1) > b').should('contain', 'Segmentation'); cy.get('.el-card > .el-card__body > :nth-child(1) > .details > .el-button > span').should('contain', ' View Segmentation'); - cy.goBackToBrowser('dataset'); + cy.visit(`${Cypress.config().baseUrl}/data?type=dataset`); }) }) }) + describe('Should open scaffold through the gallery', { testIsolation: false }, function () { before('Loading Anatomical Models', function () { cy.intercept('**/query?**').as('query'); @@ -59,6 +60,7 @@ describe('User stories', function () { }) scaffoldDatasetCategories.forEach((category) => { + it(`Access scaffold ${category}`, function () { // Search for scaffold related dataset cy.get('.el-input__inner').clear(); @@ -97,8 +99,8 @@ describe('User stories', function () { cy.wait('@query', { timeout: 20000 }); // Search dataset id - cy.get('.search-input > .el-input__inner').clear(); - cy.get('.search-input > .el-input__inner').type(datasetId); + cy.get('.search-input > .el-input__wrapper').clear(); + cy.get('.search-input > .el-input__wrapper').type(datasetId); cy.get('.header > .el-button').click(); cy.wait(['@dataset_info', '@datasets'], { timeout: 20000 }); @@ -120,7 +122,7 @@ describe('User stories', function () { cy.get('.context-image').should('have.attr', 'src').and('contain', datasetId); cy.get('[style="margin-right: 8px;"] > .title').should('have.class', 'title'); - cy.get('.open-tab > .el-icon-arrow-left').click(); + cy.get('.open-tab > .el-icon').click(); cy.get('@datasetCards').contains(/All/i).click(); @@ -129,15 +131,18 @@ describe('User stories', function () { cy.visit(`/datasets/${datasetId}?type=dataset`); }) }) - cy.goBackToBrowser('model'); + cy.visit(`${Cypress.config().baseUrl}/data?type=model&search=${category}`); }) }) }) + describe('Should find data by category', { testIsolation: false }, function () { - before('Visit homepage', function () { + beforeEach('Visit homepage', function () { cy.visit(''); }) + categories.forEach((category) => { + it(`Filter datasets by ${category}`, function () { cy.intercept('**/query?**').as('query'); @@ -147,8 +152,9 @@ describe('User stories', function () { // Check for category exist const regex = new RegExp(category, 'i') - cy.get('.data-wrap > a > p').contains(regex).as('facetsCategory'); - cy.get('@facetsCategory').should('be.visible'); + // Wait for 'href' ready for click + cy.wait(5000) + cy.get('.data-wrap > .featured-data__item > .mb-0.mt-8').contains(regex).should('exist').as('facetsCategory'); cy.get('@facetsCategory').click(); cy.wait('@query', { timeout: 20000 }); @@ -158,8 +164,6 @@ describe('User stories', function () { cy.get('.el-table__row', { timeout: 30000 }).first().as('dataset'); cy.get('@dataset').find('.cell > :nth-child(1) > a').last().click(); cy.contains(regex).should('have.length.above', 0); - cy.goBackToBrowser('dataset'); - cy.go('back'); }) }) }) From 4b7bb39c97ee87cb15c80ed622f17e3d425740cc Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 19 Mar 2024 11:15:33 +1300 Subject: [PATCH 08/44] remove `goBackToBrowser` Commands --- tests/cypress/support/commands.js | 90 ++++++++++++++----------------- 1 file changed, 40 insertions(+), 50 deletions(-) diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js index f8d6d5e9..e0291280 100644 --- a/tests/cypress/support/commands.js +++ b/tests/cypress/support/commands.js @@ -25,53 +25,43 @@ // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) Cypress.on('uncaught:exception', (err, runnable) => { - // returning false here prevents Cypress from - // failing the test - if (err.message.includes('Avoided redundant navigation to current location')) - return false - if (err.message.includes('Maximum iterations reached.')) - return false - if (err.message.includes('ResizeObserver loop limit exceeded')) - return false - if (err.message.includes('config is not defined')) - return false - // // For legacy dataset - // if (err.message.includes('ObjectID does not exist')) - // return false - return true - }) - - Cypress.Commands.add('findGalleryCard', (text, dir) => { - let direction = '.btn-next' - const clickNextPageButton = () => { - cy.get('.el-card > .el-card__body').then(($card) => { - if (!$card.text().includes(text)) { - cy.get(direction).then(($button) => { - if ($button.is(":disabled")) { - return - } else { - cy.wrap($button).click() - clickNextPageButton() - } - }) - } - }) - } - if (dir === 'prev') { - cy.get('.el-pager > .number').last().click() - direction = '.btn-prev' - } - clickNextPageButton() - }) - - Cypress.Commands.add('goBackToBrowser', (category) => { - const goBack = () => { - cy.url().then(($url) => { - if (!$url.includes(`data?type=${category}`)) { - cy.go('back') - goBack() - } - }) - } - goBack() - }) \ No newline at end of file + // returning false here prevents Cypress from + // failing the test + if (err.message.includes('Avoided redundant navigation to current location')) + return false + if (err.message.includes('Maximum iterations reached.')) + return false + if (err.message.includes('ResizeObserver loop limit exceeded')) + return false + if (err.message.includes('config is not defined')) + return false + if (err.message.includes('ResizeObserver loop completed with undelivered notifications')) + return false + // // For legacy dataset + // if (err.message.includes('ObjectID does not exist')) + // return false + return true +}) + +Cypress.Commands.add('findGalleryCard', (text, dir) => { + let direction = '.btn-next' + const clickNextPageButton = () => { + cy.get('.el-card > .el-card__body').then(($card) => { + if (!$card.text().includes(text)) { + cy.get(direction).then(($button) => { + if ($button.is(":disabled")) { + return + } else { + cy.wrap($button).click() + clickNextPageButton() + } + }) + } + }) + } + if (dir === 'prev') { + cy.get('.el-pager > .number').last().click() + direction = '.btn-prev' + } + clickNextPageButton() +}) \ No newline at end of file From ac9e9fc697d5082f878b4690d840aa7fc9e7dca9 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 19 Mar 2024 13:05:55 +1300 Subject: [PATCH 09/44] update data browsering testings filter now have a BUG on updating url, so this test needs to be re-checked once related changes are made --- tests/cypress/e2e/finddata.cy.js | 91 ++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 41 deletions(-) diff --git a/tests/cypress/e2e/finddata.cy.js b/tests/cypress/e2e/finddata.cy.js index 3fac1064..47bfcbd0 100644 --- a/tests/cypress/e2e/finddata.cy.js +++ b/tests/cypress/e2e/finddata.cy.js @@ -1,5 +1,5 @@ -// const categories = ['dataset'] -const categories = ['dataset', 'model', 'simulation', 'projects'] +const categories = ['dataset'] +// const categories = ['dataset', 'model', 'simulation', 'projects'] const limit = 20 @@ -40,8 +40,9 @@ categories.forEach((category) => { cy.get(':nth-child(1) > .el-table_1_column_2 > .cell > :nth-child(1) > .property-table > :nth-child(4) > .property-name-column').should('contain', 'Publication Date'); } }) + it('All Page Features', function () { - cy.get('h5').should('contain', 'Search within category'); + cy.get('.body1').should('contain', 'Search within category'); cy.get('.heading2').should('contain', 'Refine results'); cy.get('.tags-container > .flex').should('contain', 'Filters applied'); cy.get('.el-col-md-16 > :nth-child(1) > p').should('contain', 'Results | Showing'); @@ -64,21 +65,21 @@ categories.forEach((category) => { * Test whether content will be displayed */ // Check for tooltip content - cy.get('.purple-fill').trigger('mouseenter', { eventConstructor: 'MouseEvent' }) + cy.get('.nuxt-icon.nuxt-icon--fill.help-icon.el-tooltip__trigger.el-tooltip__trigger').trigger('mouseenter', { eventConstructor: 'MouseEvent' }) cy.get('[role="tooltip"]').should('be.visible') cy.get('[role="tooltip"]:visible > .el-popover__title').should('have.text', 'How do filters work?') - cy.get('.purple-fill').trigger('mouseleave', { eventConstructor: 'MouseEvent' }) + cy.get('.nuxt-icon.nuxt-icon--fill.help-icon.el-tooltip__trigger.el-tooltip__trigger').trigger('mouseleave', { eventConstructor: 'MouseEvent' }) cy.get('[role="tooltip"]').should('not.be.visible') cy.get('.label-header > :nth-child(1) > .label-title').then(($label) => { if ($label.text().includes('Availability')) { - cy.get('.el-tooltip').trigger('mouseenter', { eventConstructor: 'MouseEvent' }) + cy.get('.ml-4.help-icon').trigger('mouseenter', { eventConstructor: 'MouseEvent' }) cy.get('[role="tooltip"]').should('be.visible') // Check for tooltip content cy.get('[role="tooltip"]').should('contain', 'SPARC') - cy.get('.el-tooltip').trigger('mouseleave', { eventConstructor: 'MouseEvent' }) + cy.get('.ml-4.help-icon').trigger('mouseleave', { eventConstructor: 'MouseEvent' }) cy.get('[role="tooltip"]').should('not.be.visible') } }) @@ -108,7 +109,7 @@ categories.forEach((category) => { cy.get('.el-input__inner').type(keyword) // Check for clear search icon - cy.get('.btn-clear-search > .svg-icon').should('be.visible') + cy.get('.nuxt-icon.nuxt-icon--fill.body1.close-icon').should('be.visible') // Click search button cy.get('.search-text').click() @@ -142,7 +143,7 @@ categories.forEach((category) => { } }) // Clear search input - cy.get('.btn-clear-search > .svg-icon').click() + cy.get('.nuxt-icon.nuxt-icon--fill.body1.close-icon').click() // *** There are situations that dataset cards do not show the (highlighted) keywords // *** Just in case this happens for all the displayed dataset cards, extra tests may need to be added @@ -161,7 +162,7 @@ categories.forEach((category) => { cy.wait(5000) // Expand all filters/facets - cy.get('.expand-all-container > .el-link > .el-link--inner').click() + cy.get('.expand-all-container > .el-link > .el-link__inner').click() cy.get('.label-content-container').should('be.visible').and('have.length.above', 0) // Expand nested facet menu item if facet not found @@ -175,7 +176,7 @@ categories.forEach((category) => { // This action is used to expand all parent facets in ANATOMICAL STRUCTURE // To avoid facet not found when using child facets as test facets // *** Need to think of a solution to open the specific parent facet, instead of open all - cy.get('.el-icon-caret-right:visible').not('.is-leaf').click({ multiple: true }) + cy.get('.el-icon.el-tree-node__expand-icon:visible').not('.is-leaf').click({ multiple: true }) } }) @@ -189,7 +190,7 @@ categories.forEach((category) => { // This action is used to expand all parent facets in ANATOMICAL STRUCTURE // To avoid facet not found when using child facets as test facets // *** Need to think of a solution to open the specific parent facet, instead of open all - cy.get('.el-icon-caret-right:visible').not('.is-leaf').click({ multiple: true }) + cy.get('.el-icon.el-tree-node__expand-icon:visible').not('.is-leaf').click({ multiple: true }) } if (facetIsObserved) { facetList.forEach((facet) => { @@ -256,40 +257,48 @@ categories.forEach((category) => { }) facetList.forEach((facet) => { // Close all facet tags in filters applied box - cy.get('.el-card__body > .capitalize:visible').contains(new RegExp(facet, 'i')).within(() => { - cy.get('.el-tag__close').click() - }) + cy.get('.el-card__body > .capitalize').contains(new RegExp(`^${facet}$`, 'i')).siblings().click() }) cy.get('.el-card__body > .capitalize').should('not.exist') cy.get('.no-facets').should('contain', 'No filters applied') cy.url().should('not.contain', 'selectedFacetIds') - // Reset all - facetList.forEach((facet) => { - cy.wrap($label).contains(new RegExp(`^${facet}$`, 'i')).click() - }) - cy.get('.tags-container > .flex > .el-link > .el-link--inner').click() - cy.get('.el-card__body > .capitalize').should('not.exist') - cy.get('.no-facets').should('contain', 'No filters applied') - cy.url().should('not.contain', 'selectedFacetIds') - - // Close the child facet tag and then click reset all - facetList.forEach((facet) => { - cy.wrap($label).contains(new RegExp(`^${facet}$`, 'i')).click() - }) - cy.get('.el-card__body > .capitalize').then(($tag) => { - if ($tag.length > 1) { - cy.get('.el-tag__close').last().click() - cy.get('.tags-container > .flex > .el-link > .el-link--inner').click() - cy.get('.el-card__body > .capitalize').should('not.exist') - cy.get('.no-facets').should('contain', 'No filters applied') - cy.url().should('not.contain', 'selectedFacetIds') - } else { - facetList.forEach((facet) => { - cy.wrap($label).contains(new RegExp(`^${facet}$`, 'i')).click() - }) - } - }) + /** + * ========================================================================= + * Tests temporarily commented out due to a issue on the FILTER component + * Uncomment once it is fixed or has other reasonable reasons + */ + + // // Reset all + // facetList.forEach((facet) => { + // cy.wrap($label).contains(new RegExp(`^${facet}$`, 'i')).click() + // }) + // cy.get('.tags-container > .flex > .el-link > .el-link__inner').click() + // cy.get('.el-card__body > .capitalize').should('not.exist') + // cy.get('.no-facets').should('contain', 'No filters applied') + // cy.url().should('not.contain', 'selectedFacetIds') + + // // Close the child facet tag and then click reset all + // facetList.forEach((facet) => { + // cy.wrap($label).contains(new RegExp(`^${facet}$`, 'i')).click() + // }) + // cy.get('.el-card__body > .capitalize').then(($tag) => { + // if ($tag.length > 1) { + // cy.get('.el-tag__close').last().click() + // cy.get('.tags-container > .flex > .el-link > .el-link__inner').click() + // cy.get('.el-card__body > .capitalize').should('not.exist') + // cy.get('.no-facets').should('contain', 'No filters applied') + // cy.url().should('not.contain', 'selectedFacetIds') + // } else { + // facetList.forEach((facet) => { + // cy.wrap($label).contains(new RegExp(`^${facet}$`, 'i')).click() + // }) + // } + // }) + + /** + * ========================================================================= + */ } } else { this.skip() From 3be956aa1b929bc1160a570193a8a45a5a1aae0c Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:34:31 +1300 Subject: [PATCH 10/44] update dataset testings --- tests/cypress/e2e/datasets.cy.js | 116 ++++++++++++++++++------------- 1 file changed, 68 insertions(+), 48 deletions(-) diff --git a/tests/cypress/e2e/datasets.cy.js b/tests/cypress/e2e/datasets.cy.js index 7b14aff4..bd60085c 100644 --- a/tests/cypress/e2e/datasets.cy.js +++ b/tests/cypress/e2e/datasets.cy.js @@ -13,8 +13,8 @@ datasetIds.forEach(datasetId => { it("Gallery Tab", function () { // Should switch to 'Gallery' - cy.contains('#datasetDetailsTabsContainer .style1', ' Gallery ').click(); - cy.get('.nuxt-link-exact-active').should('contain', ' Gallery '); + cy.contains('#datasetDetailsTabsContainer .style1', 'Gallery').click(); + cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Gallery'); cy.wait(5000) @@ -51,6 +51,7 @@ datasetIds.forEach(datasetId => { it("Landing page", function () { cy.intercept('**/query?**').as('query') + it("Landing page", function () { // Should display image with correct dataset src cy.get('.dataset-image').should('have.attr', 'src').and('include', `https://assets.discover.pennsieve.io/dataset-assets/${datasetId}`) @@ -77,7 +78,7 @@ datasetIds.forEach(datasetId => { // }); // Should search for contributor in find data page - cy.get(':nth-child(2) > .contributor-list > li > .el-tooltip > .tooltip-item > a').then(($name) => { + cy.get(':nth-child(2) > .contributor-list > li > .el-tooltip__trigger > .tooltip-item').then(($name) => { cy.wrap($name).click() cy.wait('@query', { timeout: 20000 }) @@ -100,35 +101,36 @@ datasetIds.forEach(datasetId => { }) // Check for URL and search input - cy.url({ decode: true }).should('contain', `search=${$name.text()}`) + cy.url({ decode: true }).should('contain', `search=${$name.text().replaceAll(' ', '+')}`) cy.get('.el-input__inner').should('have.value', $name.text()); cy.go('back') }); // Check 'View other version' directs to Versions tab cy.get('.dataset-information-box > div').contains('View other versions').click(); - cy.get('.nuxt-link-exact-active').should('contain', ' Versions '); + cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Versions'); cy.get('[style=""] > .heading2.mb-8').should('contain', 'Versions for this Dataset').and('be.visible') //Check 'Get Dataset' directs to files tab cy.contains('.button-container span', 'Get Dataset').click() - cy.get('.nuxt-link-exact-active').should('contain', ' Files '); - cy.get('[style=""] > .heading2.mb-8').should('have.text', 'Download Dataset').and('be.visible') + cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Files'); + cy.get('[style=""] > .heading2.mb-8').should('contain', 'Download Dataset').and('be.visible') //Check 'Cite Dataset' directs to Cite tab cy.contains('.button-container span', 'Cite Dataset').click() - cy.get('.nuxt-link-exact-active').should('contain', ' Cite '); - cy.get('.citation-details > .heading2').should('have.text', '\n Dataset Citation\n ').and('be.visible') + cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Cite'); + cy.get('.citation-details > .heading2').should('contain', 'Dataset Citation').and('be.visible') }); + it("Abstract Tab", function () { // Should switch to 'Abstract' - cy.contains('#datasetDetailsTabsContainer .style1', ' Abstract ').click(); - cy.get('.nuxt-link-exact-active').should('contain', ' Abstract '); + cy.contains('#datasetDetailsTabsContainer .style1', 'Abstract').click(); + cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Abstract'); //The following regular expression should capture space and letters - cy.get('.dataset-description-info > .col-xs-12.description-container > p').contains(/Study Purpose: (.+)/).should('exist') - cy.get('.dataset-description-info > .col-xs-12.description-container > p').contains(/Data (Collection|Collected):(.+)/).should('exist') - cy.get('.dataset-description-info > .col-xs-12.description-container > p').contains(/(Primary )?Conclusion(s)?: (.+)/).should('exist') + cy.get('.dataset-description-info > :nth-child(1)').contains(/Study Purpose: (.+)/).should('exist') + cy.get('.dataset-description-info > :nth-child(1)').contains(/Data (Collection|Collected):(.+)/).should('exist') + cy.get('.dataset-description-info > :nth-child(1)').contains(/(Primary )?Conclusion(s)?: (.+)/).should('exist') // Check for Experimental Design cy.get('.dataset-description-info > .mb-8').contains('Experimental Design:').should('exist') @@ -159,10 +161,11 @@ datasetIds.forEach(datasetId => { }) }) }); + it("About Tab", function () { // Should switch to 'About' - cy.contains('#datasetDetailsTabsContainer .style1', ' About ').click(); - cy.get('.nuxt-link-exact-active').should('contain', ' About '); + cy.contains('#datasetDetailsTabsContainer .style1', 'About').click(); + cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'About'); // Check for content cy.get('.dataset-about-info > .mb-16').contains(/Title: (.+)/).should('exist') @@ -182,13 +185,19 @@ datasetIds.forEach(datasetId => { /** * Contact Author may not be the contributor * If should be, uncomment following code + * ========================================= */ + // //match author to contributors // cy.get('.about-section-container > :nth-child(2) > :nth-child(1)').invoke('text').then((value) => { // const author = new RegExp(value.replace(/\s+/, ' '), 'i') // cy.get('.similar-datasets-container').contains(author); // }) + /** + * ========================================= + */ + // Ignore tests if project not exist cy.get('.similar-datasets-container').then(($content) => { if ($content.text().includes('project(s):')) { @@ -209,13 +218,14 @@ datasetIds.forEach(datasetId => { } }) }); + it("Cite Tab", function () { // Should switch to 'Cite' - cy.contains('#datasetDetailsTabsContainer .style1', ' Cite ').click(); - cy.get('.nuxt-link-exact-active').should('contain', ' Cite '); + cy.contains('#datasetDetailsTabsContainer .style1', 'Cite').click(); + cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Cite'); // Check for title - cy.get('.bx--col-md-6 > .heading2').invoke('text').then((value) => { + cy.get('.el-col-sm-16 > .heading2').invoke('text').then((value) => { cy.get('.info-citation > .citation-text', { timeout: 30000 }).should('contain', value.trim()) }) @@ -228,13 +238,14 @@ datasetIds.forEach(datasetId => { cy.get('.citation-details > p > a').should('have.attr', 'href', expectedLink); }) }); + it("Files Tab", function () { //First check if there is a Files tab cy.get('#datasetDetailsTabsContainer .style1').then(($tab) => { - if ($tab.text().includes(' Files ')) { + if ($tab.text().includes('Files')) { // Should switch to 'Files' if exist - cy.contains('#datasetDetailsTabsContainer .style1', ' Files ').click(); - cy.get('.nuxt-link-exact-active').should('contain', ' Files '); + cy.contains('#datasetDetailsTabsContainer .style1', 'Files').click(); + cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Files'); // Check for content cy.get('[style=""] > .heading2.mb-8').should('have.text', 'Download Dataset'); @@ -246,7 +257,7 @@ datasetIds.forEach(datasetId => { cy.contains('Dataset size').parent().then(($size) => { const size = parseFloat($size.text().match(/[0-9]+(.[0-9]+)?/i)[0]) if ($size.text().includes("GB") && size > 5) { - cy.get('.el-tooltip > .el-button').should('not.be.enabled') + cy.get('.el-tooltip__trigger > .el-button').should('not.be.enabled') } else { cy.get('.left-column > :nth-child(1) > a > .el-button').should('be.enabled') } @@ -257,53 +268,61 @@ datasetIds.forEach(datasetId => { cy.get('.aws-download-column > :nth-child(3) > a').should('have.attr', 'href', 'https://aws.amazon.com/s3/pricing/'); //Find the download file button - cy.contains('.content .body1 .el-table__fixed-body-wrapper .el-table__row', ' dataset_description.xlsx ').should('have.length', 1).as('datasetDescription'); + cy.contains('.el-table__row', 'dataset_description.xlsx').should('have.length', 1).as('datasetDescription'); //there should be 4 icons, one for each action - cy.get('@datasetDescription').find('.svg-icon').should('have.length', 4).as('icons') + cy.get('@datasetDescription').find('.nuxt-icon.nuxt-icon--fill.action-icon').should('have.length', 4).as('icons') //Check get share links cy.get('@icons').eq(3).click({ force: true }); - cy.get('.el-message').should('be.visible').and('have.text', 'File URL copied to clipboard.') + cy.get('.el-message').should('be.visible') //Check oSPARC link cy.get('@icons').eq(2).click({ force: true }); - cy.get('.files-table-table .el-dialog .svg-icon').click({ force: true }); + cy.get('.el-dialog__headerbtn').click(); // Check for files breadcrumb - cy.get('.inline > .dataset-link').should('have.attr', 'href', 'https://docs.sparc.science/docs/accessing-public-datasets'); + cy.get('.inline > .dataset-link').should('have.attr', 'href', 'https://docs.sparc.science/docs/navigating-a-sparc-dataset'); cy.get('.breadcrumb-link').should('have.class', 'breadcrumb-link'); cy.get('.breadcrumb-link').should('have.attr', 'href').and('contain', 'datasetDetailsTab=files&path=files'); - cy.get('.el-table__body-wrapper > .el-table__body > tbody > .el-table__row').then(($table) => { - if ($table.text().includes('Folder')) { - cy.get('.breadcrumb-link').should('have.length', 1) - cy.wrap($table).filter(':contains("Folder")').first().within(($link) => { - cy.wrap($link).get('.file-name-wrap > .el-tooltip > .file-name').click({ force: true }) - }) - cy.get('.breadcrumb-link').should('have.length', 2) - cy.get(':nth-child(1) > .breadcrumb-link').click() - cy.get('.breadcrumb-link').should('have.length', 1) - } + cy.get('.cell > .file-name-wrap > .el-tooltip__trigger').then(($folder) => { + cy.get('.breadcrumb-link').should('have.length', 1) + cy.wrap($folder).first().click() + cy.get('.breadcrumb-link').should('have.length', 2) + cy.get(':nth-child(1) > .breadcrumb-link').click() + cy.get('.breadcrumb-link').should('have.length', 1) }) } else { this.skip(); } }); }); + it("References Tab", function () { //First check if reference tab is present cy.get('#datasetDetailsTabsContainer .style1').then(($tab) => { - if ($tab.text().includes(' References ')) { + if ($tab.text().includes('References')) { // Should switch to 'References' if exist - cy.contains('#datasetDetailsTabsContainer .style1', ' References ').click(); - cy.get('.nuxt-link-exact-active').should('contain', ' References '); + cy.contains('#datasetDetailsTabsContainer .style1', 'References').click(); + cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'References'); // Check for content cy.get('.dataset-references .heading2').contains('Associated Publications for this Dataset'); - cy.get('.dataset-references .citation-container').each(el => { - cy.wrap(el).find('div > a').should('have.attr', 'href').and('include', 'doi.org'); - cy.wrap(el).find('.copy-button').click(); - cy.get('.el-message').should('be.visible').and('contain', 'Successfully copied citation.') + cy.get('.dataset-references .citation-container').each(($el) => { + cy.wrap($el).find('div > a').should('have.attr', 'href').and('include', 'doi.org'); + + /** + * ============================================================================ + * Temporarily disable the copy testing, 'document not focused issue' may occur + */ + + // cy.wrap($el).find('.copy-button').click(); + // cy.get('.el-message').should('be.visible').and('contain', 'Successfully copied citation.') + + /** + * ============================================================================ + */ + }); // Check if redundant doi exist @@ -318,7 +337,7 @@ datasetIds.forEach(datasetId => { if (!doiList.includes(link)) { doiList.push(link) } else { - throw new Error("Redundant doi is found") + throw new Error("Redundant doi references are found") } }) }); @@ -329,13 +348,14 @@ datasetIds.forEach(datasetId => { } }); }); + it("Versions Tab", function () { //First check if version tab is present cy.get('#datasetDetailsTabsContainer .style1').then(($tab) => { if ($tab.text().includes(' Versions ')) { // Should switch to 'Versions' if exist - cy.contains('#datasetDetailsTabsContainer .style1', ' Versions ').click(); - cy.get('.nuxt-link-exact-active').should('contain', ' Versions '); + cy.contains('#datasetDetailsTabsContainer .style1', 'Versions').click(); + cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Versions'); // Check for file actions cy.get('.version-table > :nth-child(2) > :nth-child(4)').then(($cell) => { From f4f24d66b845a2b3e6d0b199d2ea2feaff4660c7 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:35:14 +1300 Subject: [PATCH 11/44] update cy.wait() --- tests/cypress/e2e/datasets.cy.js | 10 ++++++++-- tests/cypress/e2e/finddata.cy.js | 4 ++++ tests/cypress/e2e/mapviewer.cy.js | 3 +++ tests/cypress/e2e/userstories.cy.js | 5 +++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/tests/cypress/e2e/datasets.cy.js b/tests/cypress/e2e/datasets.cy.js index bd60085c..5b6bb63b 100644 --- a/tests/cypress/e2e/datasets.cy.js +++ b/tests/cypress/e2e/datasets.cy.js @@ -33,9 +33,12 @@ datasetIds.forEach(datasetId => { }); // Only check for dataset when it has valid flatmap data - cy.wait('@dataset_info').then((intercept) => { + cy.wait('@dataset_info', { timeout: 20000 }).then((intercept) => { + if (intercept.response.body.result[0].organs) { - cy.wait('@flatmap').then((intercept) => { + + cy.wait('@flatmap', { timeout: 20000 }).then((intercept) => { + if (intercept.response.body.values.length > 0) { cy.findGalleryCard('flatmap', 'prev'); cy.get('.el-card > .el-card__body').should('contain', 'flatmap'); @@ -77,6 +80,9 @@ datasetIds.forEach(datasetId => { // }) // }); + // Wait for the link in the clicked name + cy.wait(5000) + // Should search for contributor in find data page cy.get(':nth-child(2) > .contributor-list > li > .el-tooltip__trigger > .tooltip-item').then(($name) => { cy.wrap($name).click() diff --git a/tests/cypress/e2e/finddata.cy.js b/tests/cypress/e2e/finddata.cy.js index 47bfcbd0..f185ae03 100644 --- a/tests/cypress/e2e/finddata.cy.js +++ b/tests/cypress/e2e/finddata.cy.js @@ -204,10 +204,14 @@ categories.forEach((category) => { // Check for URL if (category === 'projects') { cy.url().should('contain', 'selectedProjectsAnatomicalFocusIds') + cy.wait('@entries', { timeout: 20000 }) + } else { cy.url().should('contain', 'selectedFacetIds') + cy.wait('@query', { timeout: 20000 }) + } cy.get('.table-wrap.el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') diff --git a/tests/cypress/e2e/mapviewer.cy.js b/tests/cypress/e2e/mapviewer.cy.js index 97eb8951..abc24495 100644 --- a/tests/cypress/e2e/mapviewer.cy.js +++ b/tests/cypress/e2e/mapviewer.cy.js @@ -55,7 +55,9 @@ describe('Maps Viewer', { testIsolation: false }, function () { * Can be removed if the popup logic updated */ cy.get('@canvas').click(coorX, coorY) + cy.wait(5000) + cy.get('body').then(($body) => { if ($body.find('.maplibregl-popup-close-button').length > 0) { // Close the provenance card @@ -167,6 +169,7 @@ describe('Maps Viewer', { testIsolation: false }, function () { cy.get('.error-feedback').should('exist') cy.get('.error-feedback').contains(/No results found/i).should('exist') } else { + cy.wait(['@dataset_info', '@datasets'], { timeout: 20000 }) // Check for search result and the tag 'Scaffold' diff --git a/tests/cypress/e2e/userstories.cy.js b/tests/cypress/e2e/userstories.cy.js index dd2469ef..9f152ca4 100644 --- a/tests/cypress/e2e/userstories.cy.js +++ b/tests/cypress/e2e/userstories.cy.js @@ -9,6 +9,7 @@ describe('User stories', function () { before('Loading Datasets', function () { cy.intercept('**/query?**').as('query'); cy.visit(''); + cy.wait('@query', { timeout: 20000 }); // Navigate to 'Data&Models' page @@ -49,6 +50,7 @@ describe('User stories', function () { before('Loading Anatomical Models', function () { cy.intercept('**/query?**').as('query'); cy.visit(''); + cy.wait('@query', { timeout: 20000 }); // Navigate to 'Data&Models' page @@ -152,12 +154,15 @@ describe('User stories', function () { // Check for category exist const regex = new RegExp(category, 'i') + // Wait for 'href' ready for click cy.wait(5000) + cy.get('.data-wrap > .featured-data__item > .mb-0.mt-8').contains(regex).should('exist').as('facetsCategory'); cy.get('@facetsCategory').click(); cy.wait('@query', { timeout: 20000 }); + cy.get('.cell > :nth-child(1) > .property-table > :nth-child(1) > :nth-child(2)', { timeout: 30000 }).first().contains(regex).should('exist'); // Check for detail page From 2c8c05798d977ecb4d798c76a3ae74f3327856ef Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:55:30 +1300 Subject: [PATCH 12/44] move cy.intercept() to beforeEach --- tests/cypress/e2e/datasets.cy.js | 10 ++++++---- tests/cypress/e2e/finddata.cy.js | 10 +++++----- tests/cypress/e2e/mapviewer.cy.js | 18 +++++++++--------- tests/cypress/e2e/userstories.cy.js | 11 +++++------ 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/tests/cypress/e2e/datasets.cy.js b/tests/cypress/e2e/datasets.cy.js index 5b6bb63b..dede20c0 100644 --- a/tests/cypress/e2e/datasets.cy.js +++ b/tests/cypress/e2e/datasets.cy.js @@ -6,10 +6,14 @@ datasetIds.forEach(datasetId => { describe(`Dataset ${datasetId}`, { testIsolation: false }, function () { before(function () { - cy.intercept('**/dataset_info/using_doi?**').as('dataset_info') - cy.intercept('**/knowledge/query/**').as('flatmap') cy.visit(`/datasets/${datasetId}?type=dataset`) }); + + beforeEach(function () { + cy.intercept('**/dataset_info/using_doi?**').as('dataset_info') + cy.intercept('**/knowledge/query/**').as('flatmap') + cy.intercept('**/query?**').as('query') + }) it("Gallery Tab", function () { // Should switch to 'Gallery' @@ -51,8 +55,6 @@ datasetIds.forEach(datasetId => { } }); }); - it("Landing page", function () { - cy.intercept('**/query?**').as('query') it("Landing page", function () { // Should display image with correct dataset src diff --git a/tests/cypress/e2e/finddata.cy.js b/tests/cypress/e2e/finddata.cy.js index f185ae03..ecc2cdb8 100644 --- a/tests/cypress/e2e/finddata.cy.js +++ b/tests/cypress/e2e/finddata.cy.js @@ -24,6 +24,11 @@ categories.forEach((category) => { cy.visit(`/data?type=${category}`) }) + beforeEach(function () { + cy.intercept('**/query?**').as('query') + cy.intercept('**/entries?**').as('entries') + }) + it('Dataset card', function () { if (category === 'projects') { cy.get(':nth-child(1) > .el-table_1_column_1 > .cell > .image-container > .img-project').should('have.attr', 'src').and('contain', '//images.ctfassets.net/'); @@ -100,8 +105,6 @@ categories.forEach((category) => { keywords.forEach((keyword) => { it(`Keyword Search - ${keyword}`, function () { - cy.intercept('**/query?**').as('query') - cy.get('.el-input__inner').should('have.attr', 'placeholder', 'Enter search criteria') // Type keyword @@ -153,9 +156,6 @@ categories.forEach((category) => { facets.forEach((facetList) => { it(`Faceted Browse Search - ${facetList}`, function () { - cy.intercept('**/query?**').as('query') - cy.intercept('**/entries?**').as('entries') - // Check for filters applied box cy.get('.no-facets').should('contain', 'No filters applied') diff --git a/tests/cypress/e2e/mapviewer.cy.js b/tests/cypress/e2e/mapviewer.cy.js index abc24495..ef322037 100644 --- a/tests/cypress/e2e/mapviewer.cy.js +++ b/tests/cypress/e2e/mapviewer.cy.js @@ -19,11 +19,18 @@ describe('Maps Viewer', { testIsolation: false }, function () { cy.visit('/maps?type=ac') }) + beforeEach(function () { + cy.intercept('**/flatmap/**').as('flatmap') + cy.intercept('**/get_body_scaffold_info/**').as('get_body_scaffold_info') + cy.intercept('**/s3-resource/**').as('s3-resource') + cy.intercept('**/query?**').as('query') + cy.intercept('**/dataset_info/**').as('dataset_info') + cy.intercept('**/datasets/**').as('datasets') + }) + taxonModels.forEach((model) => { it(`Provenance card for ${model}`, function () { - cy.intercept('**/flatmap/**').as('flatmap') - // Loading mask should not exist after the new flatmap is loaded cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') @@ -95,10 +102,6 @@ describe('Maps Viewer', { testIsolation: false }, function () { }) it(`From 2D ${threeDSyncView}, open 3D map for synchronised view and Search within display`, function () { - cy.intercept('**/flatmap/**').as('flatmap') - cy.intercept('**/get_body_scaffold_info/**').as('get_body_scaffold_info') - cy.intercept('**/s3-resource/**').as('s3-resource') - // Loading mask should not exist after the default flatmap is loaded cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') @@ -148,9 +151,6 @@ describe('Maps Viewer', { testIsolation: false }, function () { datasetIds.forEach((datasetId) => { it(`Context card in sidebar for scaffold dataset ${datasetId}`, function () { - cy.intercept('**/query?**').as('query') - cy.intercept('**/dataset_info/**').as('dataset_info') - cy.intercept('**/datasets/**').as('datasets') // Open the sidebar cy.get('.open-tab > .el-icon').click() diff --git a/tests/cypress/e2e/userstories.cy.js b/tests/cypress/e2e/userstories.cy.js index 9f152ca4..2e775d62 100644 --- a/tests/cypress/e2e/userstories.cy.js +++ b/tests/cypress/e2e/userstories.cy.js @@ -140,24 +140,23 @@ describe('User stories', function () { describe('Should find data by category', { testIsolation: false }, function () { beforeEach('Visit homepage', function () { + cy.intercept('**/query?**').as('query'); cy.visit(''); + + // Wait for 'href' ready for click + cy.wait(5000) + }) categories.forEach((category) => { it(`Filter datasets by ${category}`, function () { - cy.intercept('**/query?**').as('query'); - // Expand all cateories cy.get('.featured-data > .el-button > span').click(); cy.get('.data-wrap').should('be.visible'); // Check for category exist const regex = new RegExp(category, 'i') - - // Wait for 'href' ready for click - cy.wait(5000) - cy.get('.data-wrap > .featured-data__item > .mb-0.mt-8').contains(regex).should('exist').as('facetsCategory'); cy.get('@facetsCategory').click(); From 847f09dd4c94f266f312368b40171070522c1f34 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Wed, 20 Mar 2024 16:23:28 +1300 Subject: [PATCH 13/44] move clickNeuron() to commands.js --- tests/cypress/e2e/mapviewer.cy.js | 46 +---------------------------- tests/cypress/support/commands.js | 48 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/tests/cypress/e2e/mapviewer.cy.js b/tests/cypress/e2e/mapviewer.cy.js index ef322037..7d1b2dc1 100644 --- a/tests/cypress/e2e/mapviewer.cy.js +++ b/tests/cypress/e2e/mapviewer.cy.js @@ -51,53 +51,9 @@ describe('Maps Viewer', { testIsolation: false }, function () { cy.get('[role="radiogroup"] > .el-radio:visible').not('.is-checked').click({ multiple: true }); cy.get('.settings-group > :nth-child(2):visible').click({ waitForAnimations: false }) - let coorX = coordinate.x - let coorY = coordinate.y cy.get('[style="height: 100%;"] > [style="height: 100%; width: 100%; position: relative;"] > [style="height: 100%; width: 100%;"] > .maplibregl-touch-drag-pan > .maplibregl-canvas').as('canvas'); // Open a provenance card - const clickNeuron = () => { - /** - * ================================================================== - * Below is used to avoid the tooltip not display for the first click - * Can be removed if the popup logic updated - */ - cy.get('@canvas').click(coorX, coorY) - - cy.wait(5000) - - cy.get('body').then(($body) => { - if ($body.find('.maplibregl-popup-close-button').length > 0) { - // Close the provenance card - cy.get('.maplibregl-popup-close-button').click({ force: true }) - } - }) - /** - * ================================================================== - */ - - cy.get('@canvas').click(coorX, coorY) - - cy.wait(5000) - - cy.get('body').then(($body) => { - if ($body.find('.maplibregl-popup-close-button').length > 0) { - cy.wrap($body).find('.maplibregl-popup-content > .tooltip-container > .main', { timeout: 30000 }).within(() => { - - // Check for the popover provenance card content - cy.get('.title').should('exist') - cy.get('.subtitle').should('exist') - cy.get('.attribute-title').should('exist') - cy.get('.attribute-content').should('exist') - }) - // Close the provenance card - cy.get('.maplibregl-popup-close-button').click({ force: true }) - } else { - coorX -= pixelChange - clickNeuron() - } - }) - } - clickNeuron() + cy.clickNeuron(coordinate, pixelChange) }) }) diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js index e0291280..077b4339 100644 --- a/tests/cypress/support/commands.js +++ b/tests/cypress/support/commands.js @@ -64,4 +64,52 @@ Cypress.Commands.add('findGalleryCard', (text, dir) => { direction = '.btn-prev' } clickNextPageButton() +}) + +Cypress.Commands.add('clickNeuron', (coordinate, pixel) => { + let coorX = coordinate.x + let coorY = coordinate.y + const clickNeuron = () => { + /** + * ================================================================== + * Below is used to avoid the tooltip not display for the first click + * Can be removed if the popup logic updated + */ + cy.get('@canvas').click(coorX, coorY) + + cy.wait(5000) + + cy.get('body').then(($body) => { + if ($body.find('.maplibregl-popup-close-button').length > 0) { + // Close the provenance card + cy.get('.maplibregl-popup-close-button').click({ force: true }) + } + }) + /** + * ================================================================== + */ + + cy.get('@canvas').click(coorX, coorY) + + cy.wait(5000) + + cy.get('body').then(($body) => { + if ($body.find('.maplibregl-popup-close-button').length > 0) { + cy.wrap($body).find('.maplibregl-popup-content > .tooltip-container > .main', { timeout: 30000 }).within(() => { + + // Check for the popover provenance card content + cy.get('.title').should('exist') + cy.get('.subtitle').should('exist') + cy.get('.attribute-title').should('exist') + cy.get('.attribute-content').should('exist') + }) + // Close the provenance card + cy.get('.maplibregl-popup-close-button').click({ force: true }) + } else { + coorX -= pixel + clickNeuron() + } + }) + } + clickNeuron() }) \ No newline at end of file From f67e8e1632b1d27160b0f7f9dc5fb515dd7bc6b0 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Mon, 15 Apr 2024 14:35:23 +1200 Subject: [PATCH 14/44] Using Cypress.env for variables --- cypress.config.js | 12 ++++ .../e2e/{finddata.cy.js => databrowser.cy.js} | 55 ++++++++++++++----- tests/cypress/e2e/datasets.cy.js | 13 +++-- .../e2e/{mapviewer.cy.js => mapsviewer.cy.js} | 19 ++++--- 4 files changed, 71 insertions(+), 28 deletions(-) rename tests/cypress/e2e/{finddata.cy.js => databrowser.cy.js} (90%) rename tests/cypress/e2e/{mapviewer.cy.js => mapsviewer.cy.js} (94%) diff --git a/cypress.config.js b/cypress.config.js index d2dddbcb..8e467de9 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -18,6 +18,18 @@ export default defineConfig({ setupNodeEvents(on, config) { // implement node event listeners here }, + env: { + // databrowser.js + BROWSE_CATEGORIES: 'dataset, model, simulation, projects', + PAGE_LIMIT: '20', + SEARCH_KEYWORDS: 'Spine, neck', + FILTER_FACETS: 'Human, Heart, Adult', + // datasets.js + DATASET_IDS: '127, 282, 290, 34, 76', + // mapsviewer.js + THREE_SYNC_VIEW: 'Human Male', + SCAFFOLD_DATASET_IDS: '150, 155', + } }, fixturesFolder: "tests/cypress/fixtures", screenshotsFolder: "tests/cypress/screenshots", diff --git a/tests/cypress/e2e/finddata.cy.js b/tests/cypress/e2e/databrowser.cy.js similarity index 90% rename from tests/cypress/e2e/finddata.cy.js rename to tests/cypress/e2e/databrowser.cy.js index ecc2cdb8..e7b1f589 100644 --- a/tests/cypress/e2e/finddata.cy.js +++ b/tests/cypress/e2e/databrowser.cy.js @@ -1,11 +1,21 @@ -const categories = ['dataset'] -// const categories = ['dataset', 'model', 'simulation', 'projects'] +/** + * List of categories + * Default will be ['dataset', 'model', 'simulation', 'projects'] + */ +const browseCategories = Cypress.env('BROWSE_CATEGORIES').split(',').map(item => item.trim()) -const limit = 20 +/** + * The number of datasets are displayed per page + */ +const pageLimit = Cypress.env('PAGE_LIMIT') -const keywords = ['Spine', 'neck'] +/** + * List of keywords + */ +const searchKeywords = Cypress.env('SEARCH_KEYWORDS').split(',').map(item => item.trim()) /** + * List of facets * 1. * If multiple facets are selected which includes one or more "ANATOMICAL STRUCTURE" parent facet, * place it/them to the end of the array, @@ -15,9 +25,13 @@ const keywords = ['Spine', 'neck'] * all facets need to be matched, * otherwise that test will be skipped. */ -const facets = [['Human'], ['Heart', 'Adult']] +let filterFacets +const facets = Cypress.env('FILTER_FACETS').split(',').map(item => item.trim()) +if (facets && facets.length > 1) { + filterFacets = [facets.slice(0, 1), facets.slice(1, facets.length)] +} -categories.forEach((category) => { +browseCategories.forEach((category) => { describe(`Find Data in ${category}`, { testIsolation: false }, function () { before(function () { @@ -30,6 +44,10 @@ categories.forEach((category) => { }) it('Dataset card', function () { + + cy.wait('@query', { timeout: 20000 }) + cy.wait('@entries', { timeout: 20000 }) + if (category === 'projects') { cy.get(':nth-child(1) > .el-table_1_column_1 > .cell > .image-container > .img-project').should('have.attr', 'src').and('contain', '//images.ctfassets.net/'); cy.get(':nth-child(1) > .el-table_1_column_2 > .cell > .property-table > :nth-child(1) > .property-name-column').should('contain', 'Focus'); @@ -95,14 +113,23 @@ categories.forEach((category) => { */ // Change the limit cy.get(':nth-child(1) > p > .el-dropdown > .filter-dropdown').click() - cy.get('.el-dropdown-menu > .el-dropdown-menu__item:visible').contains(limit).click() - - // Check for limit change in URL - cy.url().should('contain', `limit=${limit}`) - cy.get('.el-table__row', { timeout: 30000 }).should('have.length', limit) + cy.get('.el-dropdown-menu > .el-dropdown-menu__item:visible').contains(pageLimit).click() + + if (pageLimit === 'View All') { + cy.get('.el-col-md-16 > :nth-child(1) > p').then(($number) => { + const numberOfDatasets = parseInt($number.text().match(/[0-9]+(.[0-9]+)?/i)[0]) + // Check for limit change in URL + cy.url().should('contain', `limit=${numberOfDatasets}`) + cy.get('.el-table__row', { timeout: 30000 }).should('have.length', numberOfDatasets) + }) + } else { + // Check for limit change in URL + cy.url().should('contain', `limit=${pageLimit}`) + cy.get('.el-table__row', { timeout: 30000 }).should('have.length', pageLimit) + } }) - keywords.forEach((keyword) => { + searchKeywords.forEach((keyword) => { it(`Keyword Search - ${keyword}`, function () { cy.get('.el-input__inner').should('have.attr', 'placeholder', 'Enter search criteria') @@ -153,7 +180,7 @@ categories.forEach((category) => { }) }) - facets.forEach((facetList) => { + filterFacets.forEach((facetList) => { it(`Faceted Browse Search - ${facetList}`, function () { // Check for filters applied box @@ -211,7 +238,7 @@ categories.forEach((category) => { cy.url().should('contain', 'selectedFacetIds') cy.wait('@query', { timeout: 20000 }) - + } cy.get('.table-wrap.el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') diff --git a/tests/cypress/e2e/datasets.cy.js b/tests/cypress/e2e/datasets.cy.js index dede20c0..324afdd7 100644 --- a/tests/cypress/e2e/datasets.cy.js +++ b/tests/cypress/e2e/datasets.cy.js @@ -1,6 +1,7 @@ -const datasetIds = [127]; -// const datasetIds = [127, 282, 290, 34, 76]; - +/** + * List of dataset ids + */ +const datasetIds = Cypress.env('DATASET_IDS').split(',').map(item => item.trim()) datasetIds.forEach(datasetId => { @@ -8,7 +9,7 @@ datasetIds.forEach(datasetId => { before(function () { cy.visit(`/datasets/${datasetId}?type=dataset`) }); - + beforeEach(function () { cy.intercept('**/dataset_info/using_doi?**').as('dataset_info') cy.intercept('**/knowledge/query/**').as('flatmap') @@ -51,7 +52,7 @@ datasetIds.forEach(datasetId => { } }) } else { - cy.wrap($content).contains(' This dataset does not contain gallery items '); + cy.wrap($content).contains(/Loading gallery...|There was an error loading the gallery items|This dataset does not contain gallery items/); } }); }); @@ -84,7 +85,7 @@ datasetIds.forEach(datasetId => { // Wait for the link in the clicked name cy.wait(5000) - + // Should search for contributor in find data page cy.get(':nth-child(2) > .contributor-list > li > .el-tooltip__trigger > .tooltip-item').then(($name) => { cy.wrap($name).click() diff --git a/tests/cypress/e2e/mapviewer.cy.js b/tests/cypress/e2e/mapsviewer.cy.js similarity index 94% rename from tests/cypress/e2e/mapviewer.cy.js rename to tests/cypress/e2e/mapsviewer.cy.js index 7d1b2dc1..a8626dde 100644 --- a/tests/cypress/e2e/mapviewer.cy.js +++ b/tests/cypress/e2e/mapsviewer.cy.js @@ -7,12 +7,15 @@ const taxonModels = ['Rat', 'Human Female'] const coordinate = { 'x': 800, 'y': 333 } const pixelChange = 3 -const threeDSyncView = 'Human Male' +/** + * Name of species for the 3D sync map + * 'Human Female', 'Human Male', 'Rat' + */ +const threeDSyncView = Cypress.env('THREE_SYNC_VIEW') -const searchInput = 'heart' +const searchInMap = 'heart' -// const datasetIds = [150] -const datasetIds = [150, 155] +const scaffoldDatasetIds = Cypress.env('SCAFFOLD_DATASET_IDS').split(',').map(item => item.trim()) describe('Maps Viewer', { testIsolation: false }, function () { before(function () { @@ -95,16 +98,16 @@ describe('Maps Viewer', { testIsolation: false }, function () { cy.get('[style="height: 100%;"] > [style="height: 100%; width: 100%; position: relative;"] > .pathway-location > .drawer-button > .el-icon-arrow-left').click() // Search keyword in displayed viewers - cy.get('.el-autocomplete > .el-input > .el-input__inner').type(searchInput) + cy.get('.el-autocomplete > .el-input > .el-input__inner').type(searchInMap) cy.get('.search-container > .map-icon > use').click() // Check for keyword(highlighted part) in displayed viewers - cy.get('.maplibregl-popup-content').contains(new RegExp(searchInput, 'i')).should('exist') + cy.get('.maplibregl-popup-content').contains(new RegExp(searchInMap, 'i')).should('exist') cy.visit('/maps?type=ac') }) - datasetIds.forEach((datasetId) => { + scaffoldDatasetIds.forEach((datasetId) => { it(`Context card in sidebar for scaffold dataset ${datasetId}`, function () { @@ -125,7 +128,7 @@ describe('Maps Viewer', { testIsolation: false }, function () { cy.get('.error-feedback').should('exist') cy.get('.error-feedback').contains(/No results found/i).should('exist') } else { - + cy.wait(['@dataset_info', '@datasets'], { timeout: 20000 }) // Check for search result and the tag 'Scaffold' From f41807f97bb9e7547b31d752b5256b2fe0172dee Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 16 Apr 2024 10:39:51 +1200 Subject: [PATCH 15/44] replace cy.contains with cy.get and add timeout --- tests/cypress/e2e/datasets.cy.js | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/cypress/e2e/datasets.cy.js b/tests/cypress/e2e/datasets.cy.js index 324afdd7..9772016b 100644 --- a/tests/cypress/e2e/datasets.cy.js +++ b/tests/cypress/e2e/datasets.cy.js @@ -18,7 +18,7 @@ datasetIds.forEach(datasetId => { it("Gallery Tab", function () { // Should switch to 'Gallery' - cy.contains('#datasetDetailsTabsContainer .style1', 'Gallery').click(); + cy.get('#datasetDetailsTabsContainer > .style1', { timeout: 30000 }).contains('Gallery').click(); cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Gallery'); cy.wait(5000) @@ -133,7 +133,7 @@ datasetIds.forEach(datasetId => { it("Abstract Tab", function () { // Should switch to 'Abstract' - cy.contains('#datasetDetailsTabsContainer .style1', 'Abstract').click(); + cy.get('#datasetDetailsTabsContainer > .style1', { timeout: 30000 }).contains('Abstract').click(); cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Abstract'); //The following regular expression should capture space and letters @@ -173,7 +173,7 @@ datasetIds.forEach(datasetId => { it("About Tab", function () { // Should switch to 'About' - cy.contains('#datasetDetailsTabsContainer .style1', 'About').click(); + cy.get('#datasetDetailsTabsContainer > .style1', { timeout: 30000 }).contains('About').click(); cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'About'); // Check for content @@ -230,7 +230,7 @@ datasetIds.forEach(datasetId => { it("Cite Tab", function () { // Should switch to 'Cite' - cy.contains('#datasetDetailsTabsContainer .style1', 'Cite').click(); + cy.get('#datasetDetailsTabsContainer > .style1', { timeout: 30000 }).contains('Cite').click(); cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Cite'); // Check for title @@ -250,10 +250,10 @@ datasetIds.forEach(datasetId => { it("Files Tab", function () { //First check if there is a Files tab - cy.get('#datasetDetailsTabsContainer .style1').then(($tab) => { - if ($tab.text().includes('Files')) { + cy.get('#datasetDetailsTabsContainer > .style1', { timeout: 30000 }).then(($tabs) => { + if ($tabs.text().includes('Files')) { // Should switch to 'Files' if exist - cy.contains('#datasetDetailsTabsContainer .style1', 'Files').click(); + cy.wrap($tabs).contains('Files').click(); cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Files'); // Check for content @@ -284,7 +284,7 @@ datasetIds.forEach(datasetId => { //Check get share links cy.get('@icons').eq(3).click({ force: true }); - cy.get('.el-message').should('be.visible') + cy.get('.el-message', { timeout: 30000 }).should('be.visible') //Check oSPARC link cy.get('@icons').eq(2).click({ force: true }); @@ -309,10 +309,10 @@ datasetIds.forEach(datasetId => { it("References Tab", function () { //First check if reference tab is present - cy.get('#datasetDetailsTabsContainer .style1').then(($tab) => { - if ($tab.text().includes('References')) { + cy.get('#datasetDetailsTabsContainer > .style1', { timeout: 30000 }).then(($tabs) => { + if ($tabs.text().includes('References')) { // Should switch to 'References' if exist - cy.contains('#datasetDetailsTabsContainer .style1', 'References').click(); + cy.wrap($tabs).contains('References').click(); cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'References'); // Check for content @@ -360,14 +360,14 @@ datasetIds.forEach(datasetId => { it("Versions Tab", function () { //First check if version tab is present - cy.get('#datasetDetailsTabsContainer .style1').then(($tab) => { - if ($tab.text().includes(' Versions ')) { + cy.get('#datasetDetailsTabsContainer > .style1', { timeout: 30000 }).then(($tabs) => { + if ($tabs.text().includes('Versions')) { // Should switch to 'Versions' if exist - cy.contains('#datasetDetailsTabsContainer .style1', 'Versions').click(); + cy.wrap($tabs).contains('Versions').click(); cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Versions'); // Check for file actions - cy.get('.version-table > :nth-child(2) > :nth-child(4)').then(($cell) => { + cy.get('.version-table > :nth-child(2) > :nth-child(4)', { timeout: 30000 }).then(($cell) => { if ($cell.text().includes('Not available')) { cy.wrap($cell).should('contain', 'Not available') } else { From 879741620998b2194483a6b29032c2b6575c1333 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 16 Apr 2024 10:41:02 +1200 Subject: [PATCH 16/44] update asserts --- tests/cypress/e2e/datasets.cy.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/cypress/e2e/datasets.cy.js b/tests/cypress/e2e/datasets.cy.js index 9772016b..35fe7f03 100644 --- a/tests/cypress/e2e/datasets.cy.js +++ b/tests/cypress/e2e/datasets.cy.js @@ -372,20 +372,20 @@ datasetIds.forEach(datasetId => { cy.wrap($cell).should('contain', 'Not available') } else { // Check for changelog - cy.wrap($cell).find('.svg-icon').as('icons').should('have.length', 2) + cy.wrap($cell).find('.circle').as('icons').should('have.length', 2) cy.get('@icons').eq(0).click() // Check for changelog popover cy.get('.optional-content-container').should('be.visible'); cy.get('.main-content-container').should('be.visible'); - cy.get('.close-icon > path').click(); + cy.get('.el-icon.el-dialog__close:visible').click(); // Check for download cy.intercept('**/zipit/discover').as('changelogDownload') cy.get('@icons').eq(1).click({ force: true }) cy.get('@changelogDownload').should(({ request, response }) => { expect(request.method).to.equal('POST') - expect(request.body.data.datasetId).to.equal(`${datasetId}`) + expect(request.body.data.datasetId).to.equal(datasetId) expect(response.statusCode).to.equal(200) }) } From 28e83178dac92fe589af1898033f78c46fac9fcf Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 16 Apr 2024 13:17:43 +1200 Subject: [PATCH 17/44] modify code for manual trigger testing --- cypress.config.js | 15 ++++++++------- tests/cypress/e2e/databrowser.cy.js | 17 +++++++++++------ tests/cypress/e2e/datasets.cy.js | 2 +- tests/cypress/e2e/mapsviewer.cy.js | 2 +- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/cypress.config.js b/cypress.config.js index 8e467de9..c1f9bd08 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -20,15 +20,16 @@ export default defineConfig({ }, env: { // databrowser.js - BROWSE_CATEGORIES: 'dataset, model, simulation, projects', - PAGE_LIMIT: '20', - SEARCH_KEYWORDS: 'Spine, neck', - FILTER_FACETS: 'Human, Heart, Adult', + BROWSE_CATEGORIES: process.env.BROWSE_CATEGORIES ? process.env.BROWSE_CATEGORIES : 'dataset, model, simulation, projects', + PAGE_LIMIT: process.env.PAGE_LIMIT ? process.env.PAGE_LIMIT : '20', + SEARCH_KEYWORDS: process.env.SEARCH_KEYWORDS ? process.env.SEARCH_KEYWORDS : 'Spine, neck', + FILTER_FACET: process.env.FILTER_FACET ? process.env.FILTER_FACET : 'Human', + MULTIPLE_FILTER_FACETS: process.env.MULTIPLE_FILTER_FACETS ? process.env.MULTIPLE_FILTER_FACETS : 'Heart, Adult', // datasets.js - DATASET_IDS: '127, 282, 290, 34, 76', + DATASET_IDS: process.env.DATASET_IDS ? process.env.DATASET_IDS : '127, 282, 290, 34, 76', // mapsviewer.js - THREE_SYNC_VIEW: 'Human Male', - SCAFFOLD_DATASET_IDS: '150, 155', + THREE_SYNC_VIEW: process.env.THREE_SYNC_VIEW ? process.env.THREE_SYNC_VIEW : 'Human Male', + SCAFFOLD_DATASET_IDS: process.env.SCAFFOLD_DATASET_IDS ? process.env.SCAFFOLD_DATASET_IDS : '150, 155', } }, fixturesFolder: "tests/cypress/fixtures", diff --git a/tests/cypress/e2e/databrowser.cy.js b/tests/cypress/e2e/databrowser.cy.js index e7b1f589..9adb4693 100644 --- a/tests/cypress/e2e/databrowser.cy.js +++ b/tests/cypress/e2e/databrowser.cy.js @@ -2,7 +2,7 @@ * List of categories * Default will be ['dataset', 'model', 'simulation', 'projects'] */ -const browseCategories = Cypress.env('BROWSE_CATEGORIES').split(',').map(item => item.trim()) +const browseCategories = Cypress.env('BROWSE_CATEGORIES').split(',').map(item => item.trim()).filter(item => item) /** * The number of datasets are displayed per page @@ -12,7 +12,7 @@ const pageLimit = Cypress.env('PAGE_LIMIT') /** * List of keywords */ -const searchKeywords = Cypress.env('SEARCH_KEYWORDS').split(',').map(item => item.trim()) +const searchKeywords = Cypress.env('SEARCH_KEYWORDS').split(',').map(item => item.trim()).filter(item => item) /** * List of facets @@ -25,10 +25,15 @@ const searchKeywords = Cypress.env('SEARCH_KEYWORDS').split(',').map(item => ite * all facets need to be matched, * otherwise that test will be skipped. */ -let filterFacets -const facets = Cypress.env('FILTER_FACETS').split(',').map(item => item.trim()) -if (facets && facets.length > 1) { - filterFacets = [facets.slice(0, 1), facets.slice(1, facets.length)] +let filterFacets = [] +const filterFacet = Cypress.env('FILTER_FACET').split(',').map(item => item.trim()).filter(item => item) +if (filterFacet && filterFacet.length === 1) { + filterFacets.push(filterFacet) +} + +const multipleFilterFacets = Cypress.env('MULTIPLE_FILTER_FACETS').split(',').map(item => item.trim()).filter(item => item) +if (multipleFilterFacets && multipleFilterFacets.length > 1) { + filterFacets.push(multipleFilterFacets) } browseCategories.forEach((category) => { diff --git a/tests/cypress/e2e/datasets.cy.js b/tests/cypress/e2e/datasets.cy.js index 35fe7f03..07e49004 100644 --- a/tests/cypress/e2e/datasets.cy.js +++ b/tests/cypress/e2e/datasets.cy.js @@ -1,7 +1,7 @@ /** * List of dataset ids */ -const datasetIds = Cypress.env('DATASET_IDS').split(',').map(item => item.trim()) +const datasetIds = Cypress.env('DATASET_IDS').split(',').map(item => item.trim()).filter(item => item) datasetIds.forEach(datasetId => { diff --git a/tests/cypress/e2e/mapsviewer.cy.js b/tests/cypress/e2e/mapsviewer.cy.js index a8626dde..5b6cc392 100644 --- a/tests/cypress/e2e/mapsviewer.cy.js +++ b/tests/cypress/e2e/mapsviewer.cy.js @@ -15,7 +15,7 @@ const threeDSyncView = Cypress.env('THREE_SYNC_VIEW') const searchInMap = 'heart' -const scaffoldDatasetIds = Cypress.env('SCAFFOLD_DATASET_IDS').split(',').map(item => item.trim()) +const scaffoldDatasetIds = Cypress.env('SCAFFOLD_DATASET_IDS').split(',').map(item => item.trim()).filter(item => item) describe('Maps Viewer', { testIsolation: false }, function () { before(function () { From 23e53dcc038c883c56436b9652c89f9bad544200 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 16 Apr 2024 13:18:20 +1200 Subject: [PATCH 18/44] update assert for map popup --- tests/cypress/support/commands.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js index 077b4339..b3423984 100644 --- a/tests/cypress/support/commands.js +++ b/tests/cypress/support/commands.js @@ -100,8 +100,9 @@ Cypress.Commands.add('clickNeuron', (coordinate, pixel) => { // Check for the popover provenance card content cy.get('.title').should('exist') cy.get('.subtitle').should('exist') - cy.get('.attribute-title').should('exist') - cy.get('.attribute-content').should('exist') + cy.get('.content-container').should('not.be.visible') + cy.get(':nth-child(3):visible').click() + cy.get('.content-container').should('be.visible') }) // Close the provenance card cy.get('.maplibregl-popup-close-button').click({ force: true }) From 9c41a44ef20d278f55ee9c0b103fd5d299593570 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 16 Apr 2024 13:18:43 +1200 Subject: [PATCH 19/44] update assert for homepage navigation bar --- tests/cypress/e2e/homepage.cy.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cypress/e2e/homepage.cy.js b/tests/cypress/e2e/homepage.cy.js index 3b153163..da1ad2d9 100644 --- a/tests/cypress/e2e/homepage.cy.js +++ b/tests/cypress/e2e/homepage.cy.js @@ -6,8 +6,8 @@ describe('Homepage', { testIsolation: false }, function () { it('Navigation Bar', function () { // Check for navigation bar cy.get('.mobile-navigation > :nth-child(1) > :nth-child(1) > a').should('contain', 'Data & Models').and('have.attr', 'href', '/data') - cy.get('.mobile-navigation > :nth-child(1) > :nth-child(2) > a').should('contain', 'Tools & Resources').and('have.attr', 'href', '/resources') - cy.get('.mobile-navigation > :nth-child(1) > :nth-child(3) > a').should('contain', 'Maps').and('have.attr', 'href', '/maps') + cy.get('.mobile-navigation > :nth-child(1) > :nth-child(2) > a').should('contain', 'SPARC Apps').and('have.attr', 'href', '/apps') + cy.get('.mobile-navigation > :nth-child(1) > :nth-child(3) > a').should('contain', 'Tools & Resources').and('have.attr', 'href', '/tools-and-resources/tools') cy.get('.mobile-navigation > :nth-child(1) > :nth-child(4) > a').should('contain', 'News & Events').and('have.attr', 'href', '/news-and-events') cy.get(':nth-child(1) > :nth-child(5) > a').should('contain', 'About').and('have.attr', 'href', '/about') cy.get(':nth-child(1) > :nth-child(6) > a').should('contain', 'Submit to SPARC').and('have.attr', 'href', '/share-data') From b1d85128a9b06306f2620575acccf6fee0a02fec Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 16 Apr 2024 13:19:07 +1200 Subject: [PATCH 20/44] add cypress test scripts --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 6f7f91d6..284c5c18 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,9 @@ "generate": "nuxt generate", "preview": "nuxt preview", "start": "node .output/server/index.mjs", - "postinstall": "nuxt prepare" + "postinstall": "nuxt prepare", + "test-cypress": "cypress run", + "test-run-e2e": "cypress run --record" }, "devDependencies": { "@nuxt/devtools": "latest", From 10ad7a2e78289a8568e8a1a9e17fa9b5067bb83b Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Fri, 26 Apr 2024 15:00:10 +1200 Subject: [PATCH 21/44] make some changes regarding to portal updates --- cypress.config.js | 1 + package.json | 2 +- tests/cypress/e2e/datasets.cy.js | 4 ++-- tests/cypress/e2e/homepage.cy.js | 2 +- tests/cypress/e2e/mapsviewer.cy.js | 8 ++++---- tests/cypress/e2e/userstories.cy.js | 12 ++++++------ tests/cypress/support/commands.js | 19 ------------------- 7 files changed, 15 insertions(+), 33 deletions(-) diff --git a/cypress.config.js b/cypress.config.js index c1f9bd08..55c56251 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -4,6 +4,7 @@ export default defineConfig({ defaultCommandTimeout: 5000, experimentalMemoryManagement: true, numTestsKeptInMemory: 0, + retries: 2, e2e: { baseUrl: process.env.ROOT_URL ? process.env.ROOT_URL : 'http://localhost:3000', experimentalStudio: true, diff --git a/package.json b/package.json index c6bed4a5..788e45cf 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "postinstall": "nuxt prepare", "sitemap": "node generate_sitemap.js", "test-cypress": "cypress run", - "test-run-e2e": "cypress run --record" + "test-cypress-record": "cypress run --record" }, "devDependencies": { "@nuxt/devtools": "latest", diff --git a/tests/cypress/e2e/datasets.cy.js b/tests/cypress/e2e/datasets.cy.js index 07e49004..efc641de 100644 --- a/tests/cypress/e2e/datasets.cy.js +++ b/tests/cypress/e2e/datasets.cy.js @@ -24,7 +24,7 @@ datasetIds.forEach(datasetId => { cy.wait(5000) cy.get('.content > .full-size', { timeout: 30000 }).then(($content) => { - const gallery = $content.find('.gallery-container'); + const gallery = $content.find('.gallery-container', { timeout: 30000 }); if (gallery && gallery.length) { // Check for pagination cy.wrap(gallery).find('.sparc-design-system-pagination').as('pagination'); @@ -52,7 +52,7 @@ datasetIds.forEach(datasetId => { } }) } else { - cy.wrap($content).contains(/Loading gallery...|There was an error loading the gallery items|This dataset does not contain gallery items/); + cy.wrap($content).contains(/There was an error loading the gallery items|This dataset does not contain gallery items/); } }); }); diff --git a/tests/cypress/e2e/homepage.cy.js b/tests/cypress/e2e/homepage.cy.js index da1ad2d9..6ca928fd 100644 --- a/tests/cypress/e2e/homepage.cy.js +++ b/tests/cypress/e2e/homepage.cy.js @@ -7,7 +7,7 @@ describe('Homepage', { testIsolation: false }, function () { // Check for navigation bar cy.get('.mobile-navigation > :nth-child(1) > :nth-child(1) > a').should('contain', 'Data & Models').and('have.attr', 'href', '/data') cy.get('.mobile-navigation > :nth-child(1) > :nth-child(2) > a').should('contain', 'SPARC Apps').and('have.attr', 'href', '/apps') - cy.get('.mobile-navigation > :nth-child(1) > :nth-child(3) > a').should('contain', 'Tools & Resources').and('have.attr', 'href', '/tools-and-resources/tools') + cy.get('.mobile-navigation > :nth-child(1) > :nth-child(3) > a').should('contain', 'Tools & Resources').and('have.attr', 'href', '/tools-and-resources') cy.get('.mobile-navigation > :nth-child(1) > :nth-child(4) > a').should('contain', 'News & Events').and('have.attr', 'href', '/news-and-events') cy.get(':nth-child(1) > :nth-child(5) > a').should('contain', 'About').and('have.attr', 'href', '/about') cy.get(':nth-child(1) > :nth-child(6) > a').should('contain', 'Submit to SPARC').and('have.attr', 'href', '/share-data') diff --git a/tests/cypress/e2e/mapsviewer.cy.js b/tests/cypress/e2e/mapsviewer.cy.js index 5b6cc392..505cb345 100644 --- a/tests/cypress/e2e/mapsviewer.cy.js +++ b/tests/cypress/e2e/mapsviewer.cy.js @@ -39,7 +39,7 @@ describe('Maps Viewer', { testIsolation: false }, function () { if (model !== 'Rat') { // Switch to the second flatmap - cy.get('#flatmap-select').click() + cy.get('.el-select.select-box.el-tooltip__trigger.el-tooltip__trigger').click() cy.get('.el-select-dropdown__item').should('be.visible') cy.get('.el-select-dropdown__item:visible').contains(new RegExp(model, 'i')).click({ force: true }) } @@ -65,7 +65,7 @@ describe('Maps Viewer', { testIsolation: false }, function () { cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') // Switch to the human related flatmap - cy.get('#flatmap-select').click() + cy.get('.el-select.select-box.el-tooltip__trigger.el-tooltip__trigger').click() cy.get('.el-select-dropdown__item').contains(new RegExp(threeDSyncView, 'i')).click({ force: true }) cy.wait('@flatmap', { timeout: 20000 }) @@ -95,10 +95,10 @@ describe('Maps Viewer', { testIsolation: false }, function () { }) // Close the pathway sidebar - cy.get('[style="height: 100%;"] > [style="height: 100%; width: 100%; position: relative;"] > .pathway-location > .drawer-button > .el-icon-arrow-left').click() + cy.get('[style="height: 100%;"] > [style="height: 100%; width: 100%; position: relative;"] > .pathway-location > .drawer-button > .el-icon').click() // Search keyword in displayed viewers - cy.get('.el-autocomplete > .el-input > .el-input__inner').type(searchInMap) + cy.get('.el-autocomplete > .el-input > .el-input__wrapper').type(searchInMap) cy.get('.search-container > .map-icon > use').click() // Check for keyword(highlighted part) in displayed viewers diff --git a/tests/cypress/e2e/userstories.cy.js b/tests/cypress/e2e/userstories.cy.js index 2e775d62..84aee6d2 100644 --- a/tests/cypress/e2e/userstories.cy.js +++ b/tests/cypress/e2e/userstories.cy.js @@ -20,11 +20,11 @@ describe('User stories', function () { it(`Access dataset ${id}`, function () { // Search for segmentation related dataset - cy.get('.el-input__inner').clear(); + cy.get('.el-input__wrapper > .el-input__inner').clear(); cy.get('.search-text').click(); cy.get('.el-table__row', { timeout: 30000 }).should('have.length', 10) - cy.get('.el-input__inner').type(id); + cy.get('.el-input__wrapper > .el-input__inner').type(id); cy.get('.search-text').click(); cy.get('.el-table__row', { timeout: 30000 }).should('have.length', 1).first().as('dataset'); @@ -65,11 +65,11 @@ describe('User stories', function () { it(`Access scaffold ${category}`, function () { // Search for scaffold related dataset - cy.get('.el-input__inner').clear(); + cy.get('.el-input__wrapper > .el-input__inner').clear(); cy.get('.search-text').click(); cy.get('.el-table__row', { timeout: 30000 }).should('have.length', 10) - cy.get('.el-input__inner').type(category); + cy.get('.el-input__wrapper > .el-input__inner').type(category); cy.get('.search-text').click(); cy.get('.el-table__row', { timeout: 30000 }).first().as('dataset'); @@ -101,8 +101,8 @@ describe('User stories', function () { cy.wait('@query', { timeout: 20000 }); // Search dataset id - cy.get('.search-input > .el-input__wrapper').clear(); - cy.get('.search-input > .el-input__wrapper').type(datasetId); + cy.get('.search-input > .el-input__wrapper > .el-input__inner').clear(); + cy.get('.search-input > .el-input__wrapper > .el-input__inner').type(datasetId); cy.get('.header > .el-button').click(); cy.wait(['@dataset_info', '@datasets'], { timeout: 20000 }); diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js index b3423984..0257e0c9 100644 --- a/tests/cypress/support/commands.js +++ b/tests/cypress/support/commands.js @@ -70,25 +70,6 @@ Cypress.Commands.add('clickNeuron', (coordinate, pixel) => { let coorX = coordinate.x let coorY = coordinate.y const clickNeuron = () => { - /** - * ================================================================== - * Below is used to avoid the tooltip not display for the first click - * Can be removed if the popup logic updated - */ - cy.get('@canvas').click(coorX, coorY) - - cy.wait(5000) - - cy.get('body').then(($body) => { - if ($body.find('.maplibregl-popup-close-button').length > 0) { - // Close the provenance card - cy.get('.maplibregl-popup-close-button').click({ force: true }) - } - }) - /** - * ================================================================== - */ - cy.get('@canvas').click(coorX, coorY) cy.wait(5000) From f682621374cac889bd27f8f4e3ca71950325355f Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:01:44 +1200 Subject: [PATCH 22/44] increase cy.wait time --- tests/cypress/e2e/datasets.cy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cypress/e2e/datasets.cy.js b/tests/cypress/e2e/datasets.cy.js index efc641de..38dae4d7 100644 --- a/tests/cypress/e2e/datasets.cy.js +++ b/tests/cypress/e2e/datasets.cy.js @@ -21,7 +21,7 @@ datasetIds.forEach(datasetId => { cy.get('#datasetDetailsTabsContainer > .style1', { timeout: 30000 }).contains('Gallery').click(); cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Gallery'); - cy.wait(5000) + cy.wait(10000) cy.get('.content > .full-size', { timeout: 30000 }).then(($content) => { const gallery = $content.find('.gallery-container', { timeout: 30000 }); From 306dbcba5b452b6b19d4c353a787b6094ea40af5 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:04:09 +1200 Subject: [PATCH 23/44] Create cypress_timeline.yml --- .github/workflows/cypress_timeline.yml | 220 +++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 .github/workflows/cypress_timeline.yml diff --git a/.github/workflows/cypress_timeline.yml b/.github/workflows/cypress_timeline.yml new file mode 100644 index 00000000..b95a7232 --- /dev/null +++ b/.github/workflows/cypress_timeline.yml @@ -0,0 +1,220 @@ +# This is a basic workflow to help you get started with Actions + +name: Cypress Timeline Tests + +on: + push: + branches: [master, main] + + pull_request_target: + types: [opened, synchronize, reopened] + branches: [master, main] + + schedule: + - cron: "0 0 * * 1" + + workflow_dispatch: + inputs: + PORTAL_TARGET: + type: "choice" + description: "Define portal target" + required: true + options: + - "Staging" + - "Production" + BROWSE_CATEGORIES: + description: "Define browse categories" + required: true + default: "dataset, model, simulation, projects" + PAGE_LIMIT: + type: "choice" + description: "Define the number of displayed datasets per page" + required: true + options: + - "10" + - "20" + - "50" + - "View All" + SEARCH_KEYWORDS: + description: "Define keywords for searching" + required: true + default: "Spine, neck" + FILTER_FACET: + description: "Define facet for filtering" + required: true + default: "Human" + MULTIPLE_FILTER_FACETS: + description: "Define multiple facets for filtering" + required: true + default: "Heart, Adult" + DATASET_IDS: + description: "Define dataset ids" + required: true + default: "127, 282, 290, 34, 76" + THREE_SYNC_VIEW: + type: "choice" + description: "Define species for sync map" + required: true + options: + - "Human Female" + - "Human Male" + - "Rat" + SCAFFOLD_DATASET_IDS: + description: "Define scaffold dataset ids" + required: true + default: "150, 155" + +env: + BROWSE_CATEGORIES: ${{ github.event.inputs.BROWSE_CATEGORIES }} + PAGE_LIMIT: ${{ github.event.inputs.PAGE_LIMIT }} + SEARCH_KEYWORDS: ${{ github.event.inputs.SEARCH_KEYWORDS }} + FILTER_FACET: ${{ github.event.inputs.FILTER_FACET }} + MULTIPLE_FILTER_FACETS: ${{ github.event.inputs.MULTIPLE_FILTER_FACETS }} + DATASET_IDS: ${{ github.event.inputs.DATASET_IDS }} + THREE_SYNC_VIEW: ${{ github.event.inputs.THREE_SYNC_VIEW }} + SCAFFOLD_DATASET_IDS: ${{ github.event.inputs.SCAFFOLD_DATASET_IDS }} + CYPRESS_PROJECT_ID: ${{ secrets.CYPRESS_PROJECT_ID }} + CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} + ALGOLIA_API_KEY: ${{ secrets.ALGOLIA_API_KEY }} + ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }} + ALGOLIA_INDEX: ${{ secrets.ALGOLIA_INDEX }} + AWS_USER_POOL_ID: ${{ secrets.AWS_USER_POOL_ID }} + AWS_USER_POOL_WEB_CLIENT_ID: ${{ secrets.AWS_USER_POOL_WEB_CLIENT_ID }} + BIOLUCIDA_PASSWORD: ${{ secrets.BIOLUCIDA_PASSWORD }} + BIOLUCIDA_USERNAME: ${{ secrets.BIOLUCIDA_USERNAME }} + BITLY_ACCESS_TOKEN: ${{ secrets.BITLY_ACCESS_TOKEN }} + BLACKFYNN_API_SECRET: ${{ secrets.BLACKFYNN_API_SECRET }} + BLACKFYNN_API_TOKEN: ${{ secrets.BLACKFYNN_API_TOKEN }} + BLACKFYNN_CONCEPTS_API_HOST: ${{ secrets.BLACKFYNN_CONCEPTS_API_HOST }} + CTF_API_HOST: ${{ secrets.CTF_API_HOST }} + CTF_CDA_ACCESS_TOKEN: ${{ secrets.CTF_CDA_ACCESS_TOKEN }} + CTF_SPACE_ID: ${{ secrets.CTF_SPACE_ID }} + DEPLOY_ENV: ${{ secrets.DEPLOY_ENV }} + DISABLE_REDIRECT_SSL: ${{ secrets.DISABLE_REDIRECT_SSL }} + FLATMAP_API_HOST: ${{ secrets.FLATMAP_API_HOST }} + LOGIN_API_URL: ${{ secrets.LOGIN_API_URL }} + NODE_ENV: ${{ secrets.NODE_ENV }} + NPM_CONFIG_PRODUCTION: ${{ secrets.NPM_CONFIG_PRODUCTION }} + OSPARC_HOST: ${{ secrets.OSPARC_HOST }} + PORTAL_API_HOST: ${{ secrets.PORTAL_API_HOST }} + RECAPTCHA_SECRET_KEY: ${{ secrets.RECAPTCHA_SECRET_KEY }} + RECAPTCHA_SITE_KEY: ${{ secrets.RECAPTCHA_SITE_KEY }} + SHOW_FUNDING_FACET: ${{ secrets.SHOW_FUNDING_FACET }} + SHOW_HIERARCHAL_FACETS: ${{ secrets.SHOW_HIERARCHAL_FACETS }} + SHOW_LOGIN_FEATURE: ${{ secrets.SHOW_LOGIN_FEATURE }} + SHOW_METRICS: ${{ secrets.SHOW_METRICS }} + SHOW_OSPARC_TAB: ${{ secrets.SHOW_OSPARC_TAB }} + SHOW_TIMESERIES_VIEWER: ${{ secrets.SHOW_TIMESERIES_VIEWER }} + SPARC_PORTAL_USER_ID: ${{ secrets.SPARC_PORTAL_USER_ID }} + SPARC_PORTAL_USER_SECRET: ${{ secrets.SPARC_PORTAL_USER_SECRET }} + +jobs: + pull-request-cypress-run: + if: github.event_name == 'pull_request_target' + runs-on: ubuntu-latest + + steps: + - uses: actions-cool/check-user-permission@main + id: checkUser + with: + require: "write" + username: ${{ github.event.pull_request.user.name }} + + - name: Checkout + if: steps.checkUser.outputs.require-result == 'true' + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 18.17.1 + + - name: Automated Run Testing when Pull Request + if: steps.checkUser.outputs.require-result == 'true' + uses: cypress-io/github-action@v6 + env: + ROOT_URL: ${{ secrets.ROOT_URL }} # http://localhost:3000 + with: + build: yarn build + start: yarn preview + wait-on: ${{ secrets.ROOT_URL }} + record: true + + - name: Skip tests + if: steps.checkUser.outputs.require-result == 'false' + uses: actions/github-script@v4 + with: + script: | + core.setFailed('Pull request is opened by an user without write permission, tests are skipped for security reason') + + schedule-cypress-run: + if: github.event_name == 'schedule' + runs-on: ubuntu-latest + + # Can be removed when nuxt3 portal is on production + env: + PROMOTION_TIMESTAMP: 1718107200 # Wed Jun 12 2024 00:00:00 GMT+1200 (New Zealand Standard Time) + + strategy: + fail-fast: false + matrix: + target: ["https://staging.sparc.science", "https://sparc.science"] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 18.17.1 + + # Can be removed when nuxt3 portal is on production + - name: Setup datetime + run: echo "CURRENT_TIMESTAMP=$(date +'%s')" >> $GITHUB_ENV + + - name: Schedule Run Testing on ${{ matrix.target }} + # Can be removed when nuxt3 portal is on production + if: ${{ (matrix.target == 'https://sparc.science' && fromJSON(env.CURRENT_TIMESTAMP) > fromJSON(env.PROMOTION_TIMESTAMP)) || matrix.target == 'https://staging.sparc.science' }} + uses: cypress-io/github-action@v6 + env: + ROOT_URL: ${{ matrix.target }} + with: + wait-on: ${{ matrix.target }} + record: true + parallel: true + + manual-cypress-run: + if: github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 18.17.1 + + - name: Manual Run Testing against Staging + if: ${{ github.event.inputs.PORTAL_TARGET == 'Staging' }} + env: + ROOT_URL: "https://staging.sparc.science" + uses: cypress-io/github-action@v6 + with: + wait-on: ${{ env.ROOT_URL }} + record: true + spec: tests/cypress/e2e/databrowser.cy.js,tests/cypress/e2e/datasets.cy.js,tests/cypress/e2e/mapsviewer.cy.js + + - name: Manual Run Testing against Production + if: ${{ github.event.inputs.PORTAL_TARGET == 'Production' }} + env: + ROOT_URL: "https://sparc.science" + uses: cypress-io/github-action@v6 + with: + wait-on: ${{ env.ROOT_URL }} + record: true + spec: tests/cypress/e2e/databrowser.cy.js,tests/cypress/e2e/datasets.cy.js,tests/cypress/e2e/mapsviewer.cy.js From ca3de3bc0610714f5907031961aef9d72b417546 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:31:54 +1200 Subject: [PATCH 24/44] disable action when push --- .github/workflows/cypress_timeline.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cypress_timeline.yml b/.github/workflows/cypress_timeline.yml index b95a7232..00cb6901 100644 --- a/.github/workflows/cypress_timeline.yml +++ b/.github/workflows/cypress_timeline.yml @@ -3,8 +3,8 @@ name: Cypress Timeline Tests on: - push: - branches: [master, main] + # push: + # branches: [master, main] pull_request_target: types: [opened, synchronize, reopened] From 53a4fcdd96c5fa2a13ba8d25ac0969cb653a04f6 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Mon, 29 Apr 2024 17:00:38 +1200 Subject: [PATCH 25/44] set REDIRECT_TARGET --- cypress.config.js | 1 + tests/cypress/e2e/datasets.cy.js | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cypress.config.js b/cypress.config.js index 55c56251..6f3b4793 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -31,6 +31,7 @@ export default defineConfig({ // mapsviewer.js THREE_SYNC_VIEW: process.env.THREE_SYNC_VIEW ? process.env.THREE_SYNC_VIEW : 'Human Male', SCAFFOLD_DATASET_IDS: process.env.SCAFFOLD_DATASET_IDS ? process.env.SCAFFOLD_DATASET_IDS : '150, 155', + REDIRECT_TARGET: process.env.ROOT_URL === 'http://localhost:3000' ? 'https://sparc.science' : process.env.ROOT_URL, } }, fixturesFolder: "tests/cypress/fixtures", diff --git a/tests/cypress/e2e/datasets.cy.js b/tests/cypress/e2e/datasets.cy.js index 38dae4d7..13ab2326 100644 --- a/tests/cypress/e2e/datasets.cy.js +++ b/tests/cypress/e2e/datasets.cy.js @@ -3,6 +3,8 @@ */ const datasetIds = Cypress.env('DATASET_IDS').split(',').map(item => item.trim()).filter(item => item) +const redirectTarget = Cypress.env('REDIRECT_TARGET') + datasetIds.forEach(datasetId => { describe(`Dataset ${datasetId}`, { testIsolation: false }, function () { @@ -72,7 +74,7 @@ datasetIds.forEach(datasetId => { // Should reload the page cy.get('.dataset-information-box > :nth-child(2) > a').click() - cy.origin('https://sparc.science', () => { + cy.origin(redirectTarget, () => { cy.url().should('contain', 'version') cy.go('back') }) @@ -393,7 +395,7 @@ datasetIds.forEach(datasetId => { // DOI link should reload page with correct version cy.get(':nth-child(2) > .el-col-push-1 > a').click() - cy.origin('https://sparc.science', () => { + cy.origin(redirectTarget, () => { cy.url().should('contain', 'version') cy.go('back') }) From 98a7eb31ec3723d57450ed62851497a1d1be58e3 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Mon, 29 Apr 2024 17:41:48 +1200 Subject: [PATCH 26/44] create cy.redirectDOILink() --- cypress.config.js | 2 +- tests/cypress/e2e/datasets.cy.js | 10 ++-------- tests/cypress/support/commands.js | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/cypress.config.js b/cypress.config.js index 6f3b4793..7b76c6a8 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -31,7 +31,7 @@ export default defineConfig({ // mapsviewer.js THREE_SYNC_VIEW: process.env.THREE_SYNC_VIEW ? process.env.THREE_SYNC_VIEW : 'Human Male', SCAFFOLD_DATASET_IDS: process.env.SCAFFOLD_DATASET_IDS ? process.env.SCAFFOLD_DATASET_IDS : '150, 155', - REDIRECT_TARGET: process.env.ROOT_URL === 'http://localhost:3000' ? 'https://sparc.science' : process.env.ROOT_URL, + REDIRECT_TARGET: process.env.ROOT_URL === 'http://localhost:3000' ? 'https://sparc.science' : null, } }, fixturesFolder: "tests/cypress/fixtures", diff --git a/tests/cypress/e2e/datasets.cy.js b/tests/cypress/e2e/datasets.cy.js index 13ab2326..0df90c83 100644 --- a/tests/cypress/e2e/datasets.cy.js +++ b/tests/cypress/e2e/datasets.cy.js @@ -74,10 +74,7 @@ datasetIds.forEach(datasetId => { // Should reload the page cy.get('.dataset-information-box > :nth-child(2) > a').click() - cy.origin(redirectTarget, () => { - cy.url().should('contain', 'version') - cy.go('back') - }) + cy.redirectDOILink(redirectTarget) // cy.get('.dataset-information-box > :nth-child(2) > a').should('have.attr', 'href').and('include', 'doi.org').then((href) => { // cy.request(href).then((resp) => { // expect(resp.status).to.eq(200); @@ -395,10 +392,7 @@ datasetIds.forEach(datasetId => { // DOI link should reload page with correct version cy.get(':nth-child(2) > .el-col-push-1 > a').click() - cy.origin(redirectTarget, () => { - cy.url().should('contain', 'version') - cy.go('back') - }) + cy.redirectDOILink(redirectTarget) // cy.get('.el-col-push-1 > a').each(($link) => { // cy.wrap($link).should('have.attr', 'href').and('include', 'doi.org').then((href) => { // cy.request(href).then((resp) => { diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js index 0257e0c9..769cece5 100644 --- a/tests/cypress/support/commands.js +++ b/tests/cypress/support/commands.js @@ -94,4 +94,20 @@ Cypress.Commands.add('clickNeuron', (coordinate, pixel) => { }) } clickNeuron() +}) + +Cypress.Commands.add('redirectDOILink', (target) => { + const clickLink = () => { + if (target) { + // When root url is localhost + cy.origin(target, () => { + cy.url().should('contain', 'version') + cy.go('back') + }) + } else { + cy.url().should('contain', 'version') + cy.go('back') + } + } + clickLink() }) \ No newline at end of file From 6b6fe3947c604f54b32809cccbaf2bdd8ec49370 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Mon, 29 Apr 2024 17:43:24 +1200 Subject: [PATCH 27/44] add production portal manual testing condition --- .github/workflows/cypress_timeline.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cypress_timeline.yml b/.github/workflows/cypress_timeline.yml index 00cb6901..2956f956 100644 --- a/.github/workflows/cypress_timeline.yml +++ b/.github/workflows/cypress_timeline.yml @@ -190,6 +190,10 @@ jobs: if: github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest + # Can be removed when nuxt3 portal is on production + env: + PROMOTION_TIMESTAMP: 1718107200 # Wed Jun 12 2024 00:00:00 GMT+1200 (New Zealand Standard Time) + steps: - name: Checkout uses: actions/checkout@v4 @@ -199,6 +203,10 @@ jobs: with: node-version: 18.17.1 + # Can be removed when nuxt3 portal is on production + - name: Setup datetime + run: echo "CURRENT_TIMESTAMP=$(date +'%s')" >> $GITHUB_ENV + - name: Manual Run Testing against Staging if: ${{ github.event.inputs.PORTAL_TARGET == 'Staging' }} env: @@ -210,7 +218,7 @@ jobs: spec: tests/cypress/e2e/databrowser.cy.js,tests/cypress/e2e/datasets.cy.js,tests/cypress/e2e/mapsviewer.cy.js - name: Manual Run Testing against Production - if: ${{ github.event.inputs.PORTAL_TARGET == 'Production' }} + if: ${{ github.event.inputs.PORTAL_TARGET == 'Production' && fromJSON(env.CURRENT_TIMESTAMP) > fromJSON(env.PROMOTION_TIMESTAMP) }} env: ROOT_URL: "https://sparc.science" uses: cypress-io/github-action@v6 From 07fe0b08edce16355dee79e5ceb02e21e218be7b Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 30 Apr 2024 09:58:11 +1200 Subject: [PATCH 28/44] update default datasets and update comment --- .github/workflows/cypress_timeline.yml | 14 +++++--------- cypress.config.js | 3 ++- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/.github/workflows/cypress_timeline.yml b/.github/workflows/cypress_timeline.yml index 2956f956..7dc14f44 100644 --- a/.github/workflows/cypress_timeline.yml +++ b/.github/workflows/cypress_timeline.yml @@ -11,6 +11,7 @@ on: branches: [master, main] schedule: + - cron: "*/5 * * * 1" # for test - cron: "0 0 * * 1" workflow_dispatch: @@ -107,6 +108,8 @@ env: SHOW_TIMESERIES_VIEWER: ${{ secrets.SHOW_TIMESERIES_VIEWER }} SPARC_PORTAL_USER_ID: ${{ secrets.SPARC_PORTAL_USER_ID }} SPARC_PORTAL_USER_SECRET: ${{ secrets.SPARC_PORTAL_USER_SECRET }} + # Should be removed when nuxt3 portal is on production + PROMOTION_TIMESTAMP: 1718107200 # Wed Jun 12 2024 00:00:00 GMT+1200 (New Zealand Standard Time) jobs: pull-request-cypress-run: @@ -153,10 +156,6 @@ jobs: if: github.event_name == 'schedule' runs-on: ubuntu-latest - # Can be removed when nuxt3 portal is on production - env: - PROMOTION_TIMESTAMP: 1718107200 # Wed Jun 12 2024 00:00:00 GMT+1200 (New Zealand Standard Time) - strategy: fail-fast: false matrix: @@ -176,7 +175,7 @@ jobs: run: echo "CURRENT_TIMESTAMP=$(date +'%s')" >> $GITHUB_ENV - name: Schedule Run Testing on ${{ matrix.target }} - # Can be removed when nuxt3 portal is on production + # Should be removed when nuxt3 portal is on production if: ${{ (matrix.target == 'https://sparc.science' && fromJSON(env.CURRENT_TIMESTAMP) > fromJSON(env.PROMOTION_TIMESTAMP)) || matrix.target == 'https://staging.sparc.science' }} uses: cypress-io/github-action@v6 env: @@ -190,10 +189,6 @@ jobs: if: github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest - # Can be removed when nuxt3 portal is on production - env: - PROMOTION_TIMESTAMP: 1718107200 # Wed Jun 12 2024 00:00:00 GMT+1200 (New Zealand Standard Time) - steps: - name: Checkout uses: actions/checkout@v4 @@ -218,6 +213,7 @@ jobs: spec: tests/cypress/e2e/databrowser.cy.js,tests/cypress/e2e/datasets.cy.js,tests/cypress/e2e/mapsviewer.cy.js - name: Manual Run Testing against Production + # Should be edit when nuxt3 portal is on production if: ${{ github.event.inputs.PORTAL_TARGET == 'Production' && fromJSON(env.CURRENT_TIMESTAMP) > fromJSON(env.PROMOTION_TIMESTAMP) }} env: ROOT_URL: "https://sparc.science" diff --git a/cypress.config.js b/cypress.config.js index 7b76c6a8..2f5d051e 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -27,10 +27,11 @@ export default defineConfig({ FILTER_FACET: process.env.FILTER_FACET ? process.env.FILTER_FACET : 'Human', MULTIPLE_FILTER_FACETS: process.env.MULTIPLE_FILTER_FACETS ? process.env.MULTIPLE_FILTER_FACETS : 'Heart, Adult', // datasets.js - DATASET_IDS: process.env.DATASET_IDS ? process.env.DATASET_IDS : '127, 282, 290, 34, 76', + DATASET_IDS: process.env.DATASET_IDS ? process.env.DATASET_IDS : '127, 205, 290, 34, 76', // mapsviewer.js THREE_SYNC_VIEW: process.env.THREE_SYNC_VIEW ? process.env.THREE_SYNC_VIEW : 'Human Male', SCAFFOLD_DATASET_IDS: process.env.SCAFFOLD_DATASET_IDS ? process.env.SCAFFOLD_DATASET_IDS : '150, 155', + // redirect REDIRECT_TARGET: process.env.ROOT_URL === 'http://localhost:3000' ? 'https://sparc.science' : null, } }, From bc8bf13a9de45c880ad23933dc835ae481f76b8c Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 30 Apr 2024 09:59:14 +1200 Subject: [PATCH 29/44] add two more inputs for manual testing --- .github/workflows/cypress_timeline.yml | 12 +++++++++++- cypress.config.js | 2 ++ tests/cypress/e2e/mapsviewer.cy.js | 10 ++++++---- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cypress_timeline.yml b/.github/workflows/cypress_timeline.yml index 7dc14f44..f4a435bd 100644 --- a/.github/workflows/cypress_timeline.yml +++ b/.github/workflows/cypress_timeline.yml @@ -51,7 +51,11 @@ on: DATASET_IDS: description: "Define dataset ids" required: true - default: "127, 282, 290, 34, 76" + default: "127, 205, 290, 34, 76" + TAXON_MODELS: + description: "Define taxon models" + required: true + default: "Rat, Human Female" THREE_SYNC_VIEW: type: "choice" description: "Define species for sync map" @@ -60,6 +64,10 @@ on: - "Human Female" - "Human Male" - "Rat" + SEARCH_IN_MAP: + description: "Define keyword" + required: true + default: "Heart" SCAFFOLD_DATASET_IDS: description: "Define scaffold dataset ids" required: true @@ -72,7 +80,9 @@ env: FILTER_FACET: ${{ github.event.inputs.FILTER_FACET }} MULTIPLE_FILTER_FACETS: ${{ github.event.inputs.MULTIPLE_FILTER_FACETS }} DATASET_IDS: ${{ github.event.inputs.DATASET_IDS }} + TAXON_MODELS: ${{ github.event.inputs.TAXON_MODELS }} THREE_SYNC_VIEW: ${{ github.event.inputs.THREE_SYNC_VIEW }} + SEARCH_IN_MAP: ${{ github.event.inputs.SEARCH_IN_MAP }} SCAFFOLD_DATASET_IDS: ${{ github.event.inputs.SCAFFOLD_DATASET_IDS }} CYPRESS_PROJECT_ID: ${{ secrets.CYPRESS_PROJECT_ID }} CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} diff --git a/cypress.config.js b/cypress.config.js index 2f5d051e..4e4f3c7a 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -29,7 +29,9 @@ export default defineConfig({ // datasets.js DATASET_IDS: process.env.DATASET_IDS ? process.env.DATASET_IDS : '127, 205, 290, 34, 76', // mapsviewer.js + TAXON_MODELS: process.env.TAXON_MODELS ? process.env.TAXON_MODELS : 'Rat, Human Female', THREE_SYNC_VIEW: process.env.THREE_SYNC_VIEW ? process.env.THREE_SYNC_VIEW : 'Human Male', + SEARCH_IN_MAP: process.env.SEARCH_IN_MAP ? process.env.SEARCH_IN_MAP : 'Heart', SCAFFOLD_DATASET_IDS: process.env.SCAFFOLD_DATASET_IDS ? process.env.SCAFFOLD_DATASET_IDS : '150, 155', // redirect REDIRECT_TARGET: process.env.ROOT_URL === 'http://localhost:3000' ? 'https://sparc.science' : null, diff --git a/tests/cypress/e2e/mapsviewer.cy.js b/tests/cypress/e2e/mapsviewer.cy.js index 505cb345..c4f632db 100644 --- a/tests/cypress/e2e/mapsviewer.cy.js +++ b/tests/cypress/e2e/mapsviewer.cy.js @@ -1,19 +1,21 @@ -// Human Female, Human Male, Rat, Mouse, Pig, Cat -// const taxonModels = ['Rat'] -const taxonModels = ['Rat', 'Human Female'] // x: The distance in pixels from the element's left // y: The distance in pixels from the element's top // central coordinate { 'x': 768, 'y': 373 } const coordinate = { 'x': 800, 'y': 333 } const pixelChange = 3 +/** + * Human Female, Human Male, Rat, Mouse, Pig, Cat + */ +const TAXON_MODELS = cypress.env('TAXON_MODELS').split(',').map(item => item.trim()).filter(item => item) + /** * Name of species for the 3D sync map * 'Human Female', 'Human Male', 'Rat' */ const threeDSyncView = Cypress.env('THREE_SYNC_VIEW') -const searchInMap = 'heart' +const searchInMap = Cypress.env('SEARCH_IN_MAP') const scaffoldDatasetIds = Cypress.env('SCAFFOLD_DATASET_IDS').split(',').map(item => item.trim()).filter(item => item) From df53eeacff31e9bb5fa1b902b90a72dbdbddb42b Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 30 Apr 2024 10:24:31 +1200 Subject: [PATCH 30/44] fix minor bugs --- tests/cypress/e2e/mapsviewer.cy.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/cypress/e2e/mapsviewer.cy.js b/tests/cypress/e2e/mapsviewer.cy.js index c4f632db..25251b73 100644 --- a/tests/cypress/e2e/mapsviewer.cy.js +++ b/tests/cypress/e2e/mapsviewer.cy.js @@ -7,7 +7,7 @@ const pixelChange = 3 /** * Human Female, Human Male, Rat, Mouse, Pig, Cat */ -const TAXON_MODELS = cypress.env('TAXON_MODELS').split(',').map(item => item.trim()).filter(item => item) +const taxonModels = Cypress.env('TAXON_MODELS').split(',').map(item => item.trim()).filter(item => item) /** * Name of species for the 3D sync map @@ -112,6 +112,8 @@ describe('Maps Viewer', { testIsolation: false }, function () { scaffoldDatasetIds.forEach((datasetId) => { it(`Context card in sidebar for scaffold dataset ${datasetId}`, function () { + // Loading mask should not exist after the default flatmap is loaded + cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') // Open the sidebar cy.get('.open-tab > .el-icon').click() From b937a7f5c4c432d46757b728ef567fd567e8b948 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 30 Apr 2024 10:29:46 +1200 Subject: [PATCH 31/44] remove unnecessary input --- .github/workflows/cypress_timeline.yml | 5 ----- cypress.config.js | 1 - tests/cypress/e2e/databrowser.cy.js | 6 +----- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/.github/workflows/cypress_timeline.yml b/.github/workflows/cypress_timeline.yml index f4a435bd..13cebfa9 100644 --- a/.github/workflows/cypress_timeline.yml +++ b/.github/workflows/cypress_timeline.yml @@ -23,10 +23,6 @@ on: options: - "Staging" - "Production" - BROWSE_CATEGORIES: - description: "Define browse categories" - required: true - default: "dataset, model, simulation, projects" PAGE_LIMIT: type: "choice" description: "Define the number of displayed datasets per page" @@ -74,7 +70,6 @@ on: default: "150, 155" env: - BROWSE_CATEGORIES: ${{ github.event.inputs.BROWSE_CATEGORIES }} PAGE_LIMIT: ${{ github.event.inputs.PAGE_LIMIT }} SEARCH_KEYWORDS: ${{ github.event.inputs.SEARCH_KEYWORDS }} FILTER_FACET: ${{ github.event.inputs.FILTER_FACET }} diff --git a/cypress.config.js b/cypress.config.js index 4e4f3c7a..3616d16d 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -21,7 +21,6 @@ export default defineConfig({ }, env: { // databrowser.js - BROWSE_CATEGORIES: process.env.BROWSE_CATEGORIES ? process.env.BROWSE_CATEGORIES : 'dataset, model, simulation, projects', PAGE_LIMIT: process.env.PAGE_LIMIT ? process.env.PAGE_LIMIT : '20', SEARCH_KEYWORDS: process.env.SEARCH_KEYWORDS ? process.env.SEARCH_KEYWORDS : 'Spine, neck', FILTER_FACET: process.env.FILTER_FACET ? process.env.FILTER_FACET : 'Human', diff --git a/tests/cypress/e2e/databrowser.cy.js b/tests/cypress/e2e/databrowser.cy.js index 9adb4693..f0fa7c88 100644 --- a/tests/cypress/e2e/databrowser.cy.js +++ b/tests/cypress/e2e/databrowser.cy.js @@ -1,8 +1,4 @@ -/** - * List of categories - * Default will be ['dataset', 'model', 'simulation', 'projects'] - */ -const browseCategories = Cypress.env('BROWSE_CATEGORIES').split(',').map(item => item.trim()).filter(item => item) +const browseCategories = ['dataset', 'model', 'simulation', 'projects'] /** * The number of datasets are displayed per page From d469df80371829dfc2868edb36e7137d2df9dcbd Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 30 Apr 2024 10:33:46 +1200 Subject: [PATCH 32/44] Update cypress_timeline.yml --- .github/workflows/cypress_timeline.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cypress_timeline.yml b/.github/workflows/cypress_timeline.yml index 13cebfa9..7c1274af 100644 --- a/.github/workflows/cypress_timeline.yml +++ b/.github/workflows/cypress_timeline.yml @@ -11,7 +11,7 @@ on: branches: [master, main] schedule: - - cron: "*/5 * * * 1" # for test + - cron: "*/15 * * * *" - cron: "0 0 * * 1" workflow_dispatch: @@ -35,7 +35,7 @@ on: SEARCH_KEYWORDS: description: "Define keywords for searching" required: true - default: "Spine, neck" + default: "Spine, Neck" FILTER_FACET: description: "Define facet for filtering" required: true From 884a74005a2b742195cc0a49d67b9535b1075a9f Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 30 Apr 2024 11:00:21 +1200 Subject: [PATCH 33/44] Update cypress_timeline.yml --- .github/workflows/cypress_timeline.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/cypress_timeline.yml b/.github/workflows/cypress_timeline.yml index 7c1274af..068df95b 100644 --- a/.github/workflows/cypress_timeline.yml +++ b/.github/workflows/cypress_timeline.yml @@ -11,7 +11,6 @@ on: branches: [master, main] schedule: - - cron: "*/15 * * * *" - cron: "0 0 * * 1" workflow_dispatch: From 16c8bf700bf9fb139f722c5dbbbec7be7443d58e Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 30 Apr 2024 11:29:30 +1200 Subject: [PATCH 34/44] add some extra timeout --- tests/cypress/e2e/mapsviewer.cy.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/cypress/e2e/mapsviewer.cy.js b/tests/cypress/e2e/mapsviewer.cy.js index 25251b73..71627d41 100644 --- a/tests/cypress/e2e/mapsviewer.cy.js +++ b/tests/cypress/e2e/mapsviewer.cy.js @@ -53,7 +53,7 @@ describe('Maps Viewer', { testIsolation: false }, function () { // Hide organs and outlines cy.get('.settings-group > :nth-child(2):visible').click({ waitForAnimations: false }) - cy.get('[role="radiogroup"] > .el-radio:visible').not('.is-checked').click({ multiple: true }); + cy.get('[role="radiogroup"] > .el-radio:visible').not('.is-checked').click({ waitForAnimations: false, multiple: true }); cy.get('.settings-group > :nth-child(2):visible').click({ waitForAnimations: false }) cy.get('[style="height: 100%;"] > [style="height: 100%; width: 100%; position: relative;"] > [style="height: 100%; width: 100%;"] > .maplibregl-touch-drag-pan > .maplibregl-canvas').as('canvas'); @@ -125,7 +125,9 @@ describe('Maps Viewer', { testIsolation: false }, function () { cy.wait('@query', { timeout: 20000 }) - cy.get('.dataset-results-feedback').then(($result) => { + cy.wait(5000) + + cy.get('.dataset-results-feedback', { timeout: 30000 }).then(($result) => { const noResult = $result.text() === '0 results | Showing' if (noResult) { // Error message should exist if no result @@ -135,6 +137,9 @@ describe('Maps Viewer', { testIsolation: false }, function () { cy.wait(['@dataset_info', '@datasets'], { timeout: 20000 }) + // Loading mask should not exist after the scaffold is loaded + cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + // Check for search result and the tag 'Scaffold' cy.get('.dataset-card-container > .dataset-card', { timeout: 30000 }).contains(datasetId).should('exist') cy.get('.dataset-card-container > .dataset-card').filter(`:contains(${datasetId})`).within(() => { @@ -142,6 +147,9 @@ describe('Maps Viewer', { testIsolation: false }, function () { cy.get('.badges-container > .container').contains(/Scaffold/i).click() }) + // Loading mask should not exist after the scaffold is loaded + cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + // Check for button text cy.get('.dataset-card-container > .dataset-card', { timeout: 30000 }).contains(/View Scaffold/i).should('exist').click() From f9cdf764802fc4868f77993bea655d434a5391f1 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 30 Apr 2024 12:06:36 +1200 Subject: [PATCH 35/44] create cy.waitForLoadingMask() --- tests/cypress/e2e/mapsviewer.cy.js | 29 ++++++++++------------------- tests/cypress/e2e/userstories.cy.js | 3 +-- tests/cypress/support/commands.js | 7 +++++++ 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/tests/cypress/e2e/mapsviewer.cy.js b/tests/cypress/e2e/mapsviewer.cy.js index 71627d41..2ceb3dd7 100644 --- a/tests/cypress/e2e/mapsviewer.cy.js +++ b/tests/cypress/e2e/mapsviewer.cy.js @@ -36,8 +36,8 @@ describe('Maps Viewer', { testIsolation: false }, function () { taxonModels.forEach((model) => { it(`Provenance card for ${model}`, function () { - // Loading mask should not exist after the new flatmap is loaded - cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + + cy.waitForLoadingMask() if (model !== 'Rat') { // Switch to the second flatmap @@ -48,8 +48,7 @@ describe('Maps Viewer', { testIsolation: false }, function () { cy.wait('@flatmap', { timeout: 20000 }) - // Loading mask should not exist after the new flatmap is loaded - cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + cy.waitForLoadingMask() // Hide organs and outlines cy.get('.settings-group > :nth-child(2):visible').click({ waitForAnimations: false }) @@ -63,8 +62,8 @@ describe('Maps Viewer', { testIsolation: false }, function () { }) it(`From 2D ${threeDSyncView}, open 3D map for synchronised view and Search within display`, function () { - // Loading mask should not exist after the default flatmap is loaded - cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + + cy.waitForLoadingMask() // Switch to the human related flatmap cy.get('.el-select.select-box.el-tooltip__trigger.el-tooltip__trigger').click() @@ -72,8 +71,7 @@ describe('Maps Viewer', { testIsolation: false }, function () { cy.wait('@flatmap', { timeout: 20000 }) - // Loading mask should not exist after the new flatmap is loaded - cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + cy.waitForLoadingMask() // Open the 3D view in a split viewer cy.get('.settings-group > :nth-child(1):visible').contains(/Open new map/i).should('exist') @@ -112,8 +110,8 @@ describe('Maps Viewer', { testIsolation: false }, function () { scaffoldDatasetIds.forEach((datasetId) => { it(`Context card in sidebar for scaffold dataset ${datasetId}`, function () { - // Loading mask should not exist after the default flatmap is loaded - cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + + cy.waitForLoadingMask() // Open the sidebar cy.get('.open-tab > .el-icon').click() @@ -125,7 +123,7 @@ describe('Maps Viewer', { testIsolation: false }, function () { cy.wait('@query', { timeout: 20000 }) - cy.wait(5000) + cy.waitForLoadingMask() cy.get('.dataset-results-feedback', { timeout: 30000 }).then(($result) => { const noResult = $result.text() === '0 results | Showing' @@ -137,24 +135,17 @@ describe('Maps Viewer', { testIsolation: false }, function () { cy.wait(['@dataset_info', '@datasets'], { timeout: 20000 }) - // Loading mask should not exist after the scaffold is loaded - cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') - // Check for search result and the tag 'Scaffold' cy.get('.dataset-card-container > .dataset-card', { timeout: 30000 }).contains(datasetId).should('exist') cy.get('.dataset-card-container > .dataset-card').filter(`:contains(${datasetId})`).within(() => { cy.get('.badges-container > .container', { timeout: 30000 }).contains(/Scaffold/i).should('exist') cy.get('.badges-container > .container').contains(/Scaffold/i).click() }) - - // Loading mask should not exist after the scaffold is loaded - cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') // Check for button text cy.get('.dataset-card-container > .dataset-card', { timeout: 30000 }).contains(/View Scaffold/i).should('exist').click() - // Loading mask should not exist after the scaffold is loaded - cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + cy.waitForLoadingMask() // Check for context card cy.get('.context-card').should('be.visible') diff --git a/tests/cypress/e2e/userstories.cy.js b/tests/cypress/e2e/userstories.cy.js index 84aee6d2..58a27657 100644 --- a/tests/cypress/e2e/userstories.cy.js +++ b/tests/cypress/e2e/userstories.cy.js @@ -116,8 +116,7 @@ describe('User stories', function () { cy.get('@datasetCards').contains(/View Scaffold/i).click(); - // Loading mask should not exist after the scaffold is loaded - cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist'); + cy.waitForLoadingMask() // Check for context card cy.get('.context-card').should('be.visible'); diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js index 769cece5..70f7f03d 100644 --- a/tests/cypress/support/commands.js +++ b/tests/cypress/support/commands.js @@ -110,4 +110,11 @@ Cypress.Commands.add('redirectDOILink', (target) => { } } clickLink() +}) + +Cypress.Commands.add('waitForLoadingMask', () => { + cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + + cy.wait(5000) + }) \ No newline at end of file From 5406bfe08ca6872fcb85dd2b0f130c9cd7874178 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 30 Apr 2024 12:38:26 +1200 Subject: [PATCH 36/44] fix test related to page limit --- tests/cypress/e2e/databrowser.cy.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/tests/cypress/e2e/databrowser.cy.js b/tests/cypress/e2e/databrowser.cy.js index f0fa7c88..6b9fd65d 100644 --- a/tests/cypress/e2e/databrowser.cy.js +++ b/tests/cypress/e2e/databrowser.cy.js @@ -119,14 +119,19 @@ browseCategories.forEach((category) => { if (pageLimit === 'View All') { cy.get('.el-col-md-16 > :nth-child(1) > p').then(($number) => { const numberOfDatasets = parseInt($number.text().match(/[0-9]+(.[0-9]+)?/i)[0]) - // Check for limit change in URL - cy.url().should('contain', `limit=${numberOfDatasets}`) - cy.get('.el-table__row', { timeout: 30000 }).should('have.length', numberOfDatasets) + if (pageLimit === 'View All') { + // Check for limit change in URL + cy.url().should('contain', `limit=${numberOfDatasets}`) + cy.get('.el-table__row', { timeout: 30000 }).should('have.length', numberOfDatasets) + } else { + cy.url().should('contain', `limit=${pageLimit}`) + if (numberOfDatasets < pageLimit) { + cy.get('.el-table__row', { timeout: 30000 }).should('have.length', numberOfDatasets) + } else { + cy.get('.el-table__row', { timeout: 30000 }).should('have.length', pageLimit) + } + } }) - } else { - // Check for limit change in URL - cy.url().should('contain', `limit=${pageLimit}`) - cy.get('.el-table__row', { timeout: 30000 }).should('have.length', pageLimit) } }) From 485cfb22b6b6a3e9bebb4d600dc243c7f88107d4 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 30 Apr 2024 12:42:33 +1200 Subject: [PATCH 37/44] move cy.waitForLoadingMask() --- tests/cypress/e2e/mapsviewer.cy.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/cypress/e2e/mapsviewer.cy.js b/tests/cypress/e2e/mapsviewer.cy.js index 2ceb3dd7..5645ff59 100644 --- a/tests/cypress/e2e/mapsviewer.cy.js +++ b/tests/cypress/e2e/mapsviewer.cy.js @@ -36,10 +36,10 @@ describe('Maps Viewer', { testIsolation: false }, function () { taxonModels.forEach((model) => { it(`Provenance card for ${model}`, function () { - - cy.waitForLoadingMask() - if (model !== 'Rat') { + + cy.waitForLoadingMask() + // Switch to the second flatmap cy.get('.el-select.select-box.el-tooltip__trigger.el-tooltip__trigger').click() cy.get('.el-select-dropdown__item').should('be.visible') From 8b668e7440fc53d1bb5001a0968827ee71112c93 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Wed, 1 May 2024 11:38:17 +1200 Subject: [PATCH 38/44] remove the restriction on production portal --- .github/workflows/cypress_timeline.yml | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/.github/workflows/cypress_timeline.yml b/.github/workflows/cypress_timeline.yml index 068df95b..acb7590a 100644 --- a/.github/workflows/cypress_timeline.yml +++ b/.github/workflows/cypress_timeline.yml @@ -112,8 +112,6 @@ env: SHOW_TIMESERIES_VIEWER: ${{ secrets.SHOW_TIMESERIES_VIEWER }} SPARC_PORTAL_USER_ID: ${{ secrets.SPARC_PORTAL_USER_ID }} SPARC_PORTAL_USER_SECRET: ${{ secrets.SPARC_PORTAL_USER_SECRET }} - # Should be removed when nuxt3 portal is on production - PROMOTION_TIMESTAMP: 1718107200 # Wed Jun 12 2024 00:00:00 GMT+1200 (New Zealand Standard Time) jobs: pull-request-cypress-run: @@ -174,13 +172,7 @@ jobs: with: node-version: 18.17.1 - # Can be removed when nuxt3 portal is on production - - name: Setup datetime - run: echo "CURRENT_TIMESTAMP=$(date +'%s')" >> $GITHUB_ENV - - name: Schedule Run Testing on ${{ matrix.target }} - # Should be removed when nuxt3 portal is on production - if: ${{ (matrix.target == 'https://sparc.science' && fromJSON(env.CURRENT_TIMESTAMP) > fromJSON(env.PROMOTION_TIMESTAMP)) || matrix.target == 'https://staging.sparc.science' }} uses: cypress-io/github-action@v6 env: ROOT_URL: ${{ matrix.target }} @@ -202,10 +194,6 @@ jobs: with: node-version: 18.17.1 - # Can be removed when nuxt3 portal is on production - - name: Setup datetime - run: echo "CURRENT_TIMESTAMP=$(date +'%s')" >> $GITHUB_ENV - - name: Manual Run Testing against Staging if: ${{ github.event.inputs.PORTAL_TARGET == 'Staging' }} env: @@ -217,8 +205,7 @@ jobs: spec: tests/cypress/e2e/databrowser.cy.js,tests/cypress/e2e/datasets.cy.js,tests/cypress/e2e/mapsviewer.cy.js - name: Manual Run Testing against Production - # Should be edit when nuxt3 portal is on production - if: ${{ github.event.inputs.PORTAL_TARGET == 'Production' && fromJSON(env.CURRENT_TIMESTAMP) > fromJSON(env.PROMOTION_TIMESTAMP) }} + if: ${{ github.event.inputs.PORTAL_TARGET == 'Production' }} env: ROOT_URL: "https://sparc.science" uses: cypress-io/github-action@v6 From e749f5c4311c94abd8a47569991cb815c4edfbac Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Fri, 3 May 2024 11:55:55 +1200 Subject: [PATCH 39/44] replace redirectDOILink by cy.request --- cypress.config.js | 2 - tests/cypress/e2e/datasets.cy.js | 146 ++++++++++++++---------------- tests/cypress/support/commands.js | 18 +--- 3 files changed, 70 insertions(+), 96 deletions(-) diff --git a/cypress.config.js b/cypress.config.js index 3616d16d..0438395b 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -32,8 +32,6 @@ export default defineConfig({ THREE_SYNC_VIEW: process.env.THREE_SYNC_VIEW ? process.env.THREE_SYNC_VIEW : 'Human Male', SEARCH_IN_MAP: process.env.SEARCH_IN_MAP ? process.env.SEARCH_IN_MAP : 'Heart', SCAFFOLD_DATASET_IDS: process.env.SCAFFOLD_DATASET_IDS ? process.env.SCAFFOLD_DATASET_IDS : '150, 155', - // redirect - REDIRECT_TARGET: process.env.ROOT_URL === 'http://localhost:3000' ? 'https://sparc.science' : null, } }, fixturesFolder: "tests/cypress/fixtures", diff --git a/tests/cypress/e2e/datasets.cy.js b/tests/cypress/e2e/datasets.cy.js index 0df90c83..bb469c1e 100644 --- a/tests/cypress/e2e/datasets.cy.js +++ b/tests/cypress/e2e/datasets.cy.js @@ -3,8 +3,6 @@ */ const datasetIds = Cypress.env('DATASET_IDS').split(',').map(item => item.trim()).filter(item => item) -const redirectTarget = Cypress.env('REDIRECT_TARGET') - datasetIds.forEach(datasetId => { describe(`Dataset ${datasetId}`, { testIsolation: false }, function () { @@ -18,50 +16,12 @@ datasetIds.forEach(datasetId => { cy.intercept('**/query?**').as('query') }) - it("Gallery Tab", function () { - // Should switch to 'Gallery' - cy.get('#datasetDetailsTabsContainer > .style1', { timeout: 30000 }).contains('Gallery').click(); - cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Gallery'); - - cy.wait(10000) - - cy.get('.content > .full-size', { timeout: 30000 }).then(($content) => { - const gallery = $content.find('.gallery-container', { timeout: 30000 }); - if (gallery && gallery.length) { - // Check for pagination - cy.wrap(gallery).find('.sparc-design-system-pagination').as('pagination'); - cy.get('@pagination').find('li.number').should('have.length.least', 1); - - // Check for gallery card - cy.wrap(gallery).find('.el-card').as('card').should('have.length.least', 1) - cy.get('@card').first().within(($card) => { - cy.wrap($card).get('.cursor-pointer > img').should('be.visible').and('have.prop', 'naturalWidth').should('be.greaterThan', 0) - cy.wrap($card).contains('span', ' View ') - }); - - // Only check for dataset when it has valid flatmap data - cy.wait('@dataset_info', { timeout: 20000 }).then((intercept) => { - - if (intercept.response.body.result[0].organs) { + it("Landing page", function () { - cy.wait('@flatmap', { timeout: 20000 }).then((intercept) => { + cy.waitForLoadingMask() - if (intercept.response.body.values.length > 0) { - cy.findGalleryCard('flatmap', 'prev'); - cy.get('.el-card > .el-card__body').should('contain', 'flatmap'); - } - }) - } - }) - } else { - cy.wrap($content).contains(/There was an error loading the gallery items|This dataset does not contain gallery items/); - } - }); - }); - - it("Landing page", function () { // Should display image with correct dataset src - cy.get('.dataset-image').should('have.attr', 'src').and('include', `https://assets.discover.pennsieve.io/dataset-assets/${datasetId}`) + cy.get('.dataset-image', { timeout: 30000 }).should('have.attr', 'src').and('include', `https://assets.discover.pennsieve.io/dataset-assets/${datasetId}`) // Check for tooltip when hover over author cy.get('.dataset-owners > :nth-child(2) > .contributor-item').then(($orcid) => { @@ -72,15 +32,16 @@ datasetIds.forEach(datasetId => { } }) - // Should reload the page - cy.get('.dataset-information-box > :nth-child(2) > a').click() - cy.redirectDOILink(redirectTarget) - // cy.get('.dataset-information-box > :nth-child(2) > a').should('have.attr', 'href').and('include', 'doi.org').then((href) => { - // cy.request(href).then((resp) => { - // expect(resp.status).to.eq(200); - // expect(resp.body).to.include(`datasets/${datasetId}/version`); - // }) - // }); + // DOI link should link to page with correct version + cy.get('.dataset-information-box > :nth-child(1)').invoke('text').then((value) => { + const version = value.match(/[0-9]+/i)[0] + cy.get('.dataset-information-box > :nth-child(2) > a').should('have.attr', 'href').and('include', 'doi.org').then((href) => { + cy.request(href).then((resp) => { + expect(resp.status).to.eq(200); + expect(resp.body).to.include(`datasets/${datasetId}/version/${version}`); + }) + }) + }); // Wait for the link in the clicked name cy.wait(5000) @@ -91,7 +52,7 @@ datasetIds.forEach(datasetId => { cy.wait('@query', { timeout: 20000 }) - cy.get('.table-wrap.el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') + cy.waitForLoadingMask() // Check for result cy.get(':nth-child(1) > p > .el-dropdown > .filter-dropdown').should('be.visible').click() @@ -130,6 +91,47 @@ datasetIds.forEach(datasetId => { cy.get('.citation-details > .heading2').should('contain', 'Dataset Citation').and('be.visible') }); + it("Gallery Tab", function () { + // Should switch to 'Gallery' + cy.get('#datasetDetailsTabsContainer > .style1', { timeout: 30000 }).contains('Gallery').click(); + cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Gallery'); + + cy.wait(10000) + + cy.get('.content > .full-size', { timeout: 30000 }).then(($content) => { + const gallery = $content.find('.gallery-container', { timeout: 30000 }); + if (gallery && gallery.length) { + // Check for pagination + cy.wrap(gallery).find('.sparc-design-system-pagination').as('pagination'); + cy.get('@pagination').find('li.number').should('have.length.least', 1); + + // Check for gallery card + cy.wrap(gallery).find('.el-card').as('card').should('have.length.least', 1) + cy.get('@card').first().within(($card) => { + cy.wrap($card).get('.cursor-pointer > img').should('be.visible').and('have.prop', 'naturalWidth').should('be.greaterThan', 0) + cy.wrap($card).contains('span', ' View ') + }); + + // Only check for dataset when it has valid flatmap data + cy.wait('@dataset_info', { timeout: 20000 }).then((intercept) => { + + if (intercept.response.body.result[0].organs) { + + cy.wait('@flatmap', { timeout: 20000 }).then((intercept) => { + + if (intercept.response.body.values.length > 0) { + cy.findGalleryCard('flatmap', 'prev'); + cy.get('.el-card > .el-card__body').should('contain', 'flatmap'); + } + }) + } + }) + } else { + cy.wrap($content).contains(/There was an error loading the gallery items|This dataset does not contain gallery items/); + } + }); + }); + it("Abstract Tab", function () { // Should switch to 'Abstract' cy.get('#datasetDetailsTabsContainer > .style1', { timeout: 30000 }).contains('Abstract').click(); @@ -318,19 +320,8 @@ datasetIds.forEach(datasetId => { cy.get('.dataset-references .heading2').contains('Associated Publications for this Dataset'); cy.get('.dataset-references .citation-container').each(($el) => { cy.wrap($el).find('div > a').should('have.attr', 'href').and('include', 'doi.org'); - - /** - * ============================================================================ - * Temporarily disable the copy testing, 'document not focused issue' may occur - */ - - // cy.wrap($el).find('.copy-button').click(); - // cy.get('.el-message').should('be.visible').and('contain', 'Successfully copied citation.') - - /** - * ============================================================================ - */ - + cy.wrap($el).find('.copy-button').click(); + cy.get('.el-message').should('be.visible').and('contain', 'Successfully copied citation.') }); // Check if redundant doi exist @@ -390,17 +381,18 @@ datasetIds.forEach(datasetId => { } }) - // DOI link should reload page with correct version - cy.get(':nth-child(2) > .el-col-push-1 > a').click() - cy.redirectDOILink(redirectTarget) - // cy.get('.el-col-push-1 > a').each(($link) => { - // cy.wrap($link).should('have.attr', 'href').and('include', 'doi.org').then((href) => { - // cy.request(href).then((resp) => { - // expect(resp.status).to.eq(200); - // expect(resp.body).to.include(`datasets/${datasetId}/version`); - // }) - // }); - // }) + // DOI link should link to page with correct version + cy.get('.version-table > .table-rows').each(($row) => { + cy.wrap($row).children('.el-col-pull-1').invoke('text').then((value) => { + const version = value.match(/[0-9]+/i)[0] + cy.wrap($row).children('.el-col-push-1').children('a').should('have.attr', 'href').and('include', 'doi.org').then((href) => { + cy.request(href).then((resp) => { + expect(resp.status).to.eq(200); + expect(resp.body).to.include(`datasets/${datasetId}/version/${version}`); + }) + }); + }) + }) } }); }); diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js index 70f7f03d..3bd78b8b 100644 --- a/tests/cypress/support/commands.js +++ b/tests/cypress/support/commands.js @@ -96,25 +96,9 @@ Cypress.Commands.add('clickNeuron', (coordinate, pixel) => { clickNeuron() }) -Cypress.Commands.add('redirectDOILink', (target) => { - const clickLink = () => { - if (target) { - // When root url is localhost - cy.origin(target, () => { - cy.url().should('contain', 'version') - cy.go('back') - }) - } else { - cy.url().should('contain', 'version') - cy.go('back') - } - } - clickLink() -}) - Cypress.Commands.add('waitForLoadingMask', () => { cy.get('.multi-container > .el-loading-parent--relative > .el-loading-mask', { timeout: 30000 }).should('not.exist') cy.wait(5000) - + }) \ No newline at end of file From 6e1b2da5826b5bc6ce971a25115a827167eb5397 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 7 May 2024 10:28:03 +1200 Subject: [PATCH 40/44] add wait --- tests/cypress/e2e/userstories.cy.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/cypress/e2e/userstories.cy.js b/tests/cypress/e2e/userstories.cy.js index 58a27657..4c53e4e2 100644 --- a/tests/cypress/e2e/userstories.cy.js +++ b/tests/cypress/e2e/userstories.cy.js @@ -100,6 +100,8 @@ describe('User stories', function () { cy.wait('@query', { timeout: 20000 }); + cy.waitForLoadingMask() + // Search dataset id cy.get('.search-input > .el-input__wrapper > .el-input__inner').clear(); cy.get('.search-input > .el-input__wrapper > .el-input__inner').type(datasetId); From b76d26925f1d1365d99e8a73a7386adc199e738b Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Tue, 7 May 2024 10:54:10 +1200 Subject: [PATCH 41/44] add wait to scaffold userstory testing --- tests/cypress/e2e/userstories.cy.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/cypress/e2e/userstories.cy.js b/tests/cypress/e2e/userstories.cy.js index 4c53e4e2..e35c8ec9 100644 --- a/tests/cypress/e2e/userstories.cy.js +++ b/tests/cypress/e2e/userstories.cy.js @@ -64,6 +64,9 @@ describe('User stories', function () { scaffoldDatasetCategories.forEach((category) => { it(`Access scaffold ${category}`, function () { + + cy.waitForLoadingMask() + // Search for scaffold related dataset cy.get('.el-input__wrapper > .el-input__inner').clear(); cy.get('.search-text').click(); From 668b3cfb50f34b7e0427ea7669df04d7f4074748 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Wed, 8 May 2024 13:44:52 +1200 Subject: [PATCH 42/44] change tests order --- tests/cypress/e2e/datasets.cy.js | 85 ++++++++++++++++---------------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/tests/cypress/e2e/datasets.cy.js b/tests/cypress/e2e/datasets.cy.js index bb469c1e..364e0fdb 100644 --- a/tests/cypress/e2e/datasets.cy.js +++ b/tests/cypress/e2e/datasets.cy.js @@ -16,10 +16,52 @@ datasetIds.forEach(datasetId => { cy.intercept('**/query?**').as('query') }) - it("Landing page", function () { + + it("Gallery Tab", function () { cy.waitForLoadingMask() + // Should switch to 'Gallery' + cy.get('#datasetDetailsTabsContainer > .style1', { timeout: 30000 }).contains('Gallery').click(); + cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Gallery'); + + cy.wait(10000) + + cy.get('.content > .full-size', { timeout: 30000 }).then(($content) => { + const gallery = $content.find('.gallery-container', { timeout: 30000 }); + if (gallery && gallery.length) { + // Check for pagination + cy.wrap(gallery).find('.sparc-design-system-pagination').as('pagination'); + cy.get('@pagination').find('li.number').should('have.length.least', 1); + + // Check for gallery card + cy.wrap(gallery).find('.el-card').as('card').should('have.length.least', 1) + cy.get('@card').first().within(($card) => { + cy.wrap($card).get('.cursor-pointer > img').should('be.visible').and('have.prop', 'naturalWidth').should('be.greaterThan', 0) + cy.wrap($card).contains('span', ' View ') + }); + + // Only check for dataset when it has valid flatmap data + cy.wait('@dataset_info', { timeout: 20000 }).then((intercept) => { + + if (intercept.response.body.result[0].organs) { + + cy.wait('@flatmap', { timeout: 20000 }).then((intercept) => { + + if (intercept.response.body.values.length > 0) { + cy.findGalleryCard('flatmap', 'prev'); + cy.get('.el-card > .el-card__body').should('contain', 'flatmap'); + } + }) + } + }) + } else { + cy.wrap($content).contains(/There was an error loading the gallery items|This dataset does not contain gallery items/); + } + }); + }); + + it("Landing page", function () { // Should display image with correct dataset src cy.get('.dataset-image', { timeout: 30000 }).should('have.attr', 'src').and('include', `https://assets.discover.pennsieve.io/dataset-assets/${datasetId}`) @@ -91,47 +133,6 @@ datasetIds.forEach(datasetId => { cy.get('.citation-details > .heading2').should('contain', 'Dataset Citation').and('be.visible') }); - it("Gallery Tab", function () { - // Should switch to 'Gallery' - cy.get('#datasetDetailsTabsContainer > .style1', { timeout: 30000 }).contains('Gallery').click(); - cy.get('.active.style1.tab2.tab-link.p-16').should('contain', 'Gallery'); - - cy.wait(10000) - - cy.get('.content > .full-size', { timeout: 30000 }).then(($content) => { - const gallery = $content.find('.gallery-container', { timeout: 30000 }); - if (gallery && gallery.length) { - // Check for pagination - cy.wrap(gallery).find('.sparc-design-system-pagination').as('pagination'); - cy.get('@pagination').find('li.number').should('have.length.least', 1); - - // Check for gallery card - cy.wrap(gallery).find('.el-card').as('card').should('have.length.least', 1) - cy.get('@card').first().within(($card) => { - cy.wrap($card).get('.cursor-pointer > img').should('be.visible').and('have.prop', 'naturalWidth').should('be.greaterThan', 0) - cy.wrap($card).contains('span', ' View ') - }); - - // Only check for dataset when it has valid flatmap data - cy.wait('@dataset_info', { timeout: 20000 }).then((intercept) => { - - if (intercept.response.body.result[0].organs) { - - cy.wait('@flatmap', { timeout: 20000 }).then((intercept) => { - - if (intercept.response.body.values.length > 0) { - cy.findGalleryCard('flatmap', 'prev'); - cy.get('.el-card > .el-card__body').should('contain', 'flatmap'); - } - }) - } - }) - } else { - cy.wrap($content).contains(/There was an error loading the gallery items|This dataset does not contain gallery items/); - } - }); - }); - it("Abstract Tab", function () { // Should switch to 'Abstract' cy.get('#datasetDetailsTabsContainer > .style1', { timeout: 30000 }).contains('Abstract').click(); From 9c5f39aaa501e1813fc0599b9e5bba0291004b02 Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Fri, 10 May 2024 09:24:32 +1200 Subject: [PATCH 43/44] remove unused markdwontest --- tests/MarkdownTest/MarkdownTest.spec.js | 23 --------------------- tests/MarkdownTest/MarkdownTest.vue | 27 ------------------------- 2 files changed, 50 deletions(-) delete mode 100644 tests/MarkdownTest/MarkdownTest.spec.js delete mode 100644 tests/MarkdownTest/MarkdownTest.vue diff --git a/tests/MarkdownTest/MarkdownTest.spec.js b/tests/MarkdownTest/MarkdownTest.spec.js deleted file mode 100644 index c9286557..00000000 --- a/tests/MarkdownTest/MarkdownTest.spec.js +++ /dev/null @@ -1,23 +0,0 @@ -import { mount } from '@vue/test-utils' -import MarkdownTest from './MarkdownTest' - -describe('MarkdownTest', () => { - const wrapper = mount(MarkdownTest) - - it('Renders the correct markup', () => { - expect(wrapper.find('#externalWrap a').exists()).toBe(true) - expect(wrapper.find('#externalWrap h1').exists()).toBe(true) - }) - - it('Adds target="blank" to links', () => { - expect(wrapper.find('#externalWrap a').element.getAttribute('target')).toBe( - '_blank' - ) - }) - - it('Renders an anchor tag properly', () => { - expect(wrapper.find('#anchorWrap a').element.getAttribute('target')).toBe( - null - ) - }) -}) diff --git a/tests/MarkdownTest/MarkdownTest.vue b/tests/MarkdownTest/MarkdownTest.vue deleted file mode 100644 index 7655382d..00000000 --- a/tests/MarkdownTest/MarkdownTest.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - From db5a3b6d9426948cd01db6590f5790b612f3a2ec Mon Sep 17 00:00:00 2001 From: "David J. Yu" <87633683+ddjnw1yu@users.noreply.github.com> Date: Fri, 10 May 2024 09:24:47 +1200 Subject: [PATCH 44/44] remove empty line --- tests/cypress/e2e/datasets.cy.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/cypress/e2e/datasets.cy.js b/tests/cypress/e2e/datasets.cy.js index 364e0fdb..541c1bf3 100644 --- a/tests/cypress/e2e/datasets.cy.js +++ b/tests/cypress/e2e/datasets.cy.js @@ -16,7 +16,6 @@ datasetIds.forEach(datasetId => { cy.intercept('**/query?**').as('query') }) - it("Gallery Tab", function () { cy.waitForLoadingMask()