diff --git a/package-lock.json b/package-lock.json index 4b00a1626..7a4119451 100644 --- a/package-lock.json +++ b/package-lock.json @@ -122,7 +122,7 @@ "typescript": "^5.7.2", "webpack": "5", "webpack-cli": "^5.0.1", - "webpack-dev-server": "^4.13.1", + "webpack-dev-server": "^5.2.2", "webpack-merge": "^5.8.0", "workbox-webpack-plugin": "^6.5.4", "yaml-loader": "^0.8.0" @@ -4503,29 +4503,6 @@ "@img/sharp-libvips-linux-s390x": "1.0.4" } }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.1.tgz", - "integrity": "sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.1.0" - } - }, "node_modules/@img/sharp-linuxmusl-arm64": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", @@ -5692,6 +5669,60 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.2.0.tgz", + "integrity": "sha512-io1zEbbYcElht3tdlqEOFxZ0dMTYrHz9iMf0gqn1pPjZFTCgM5R4R5IMA20Chb2UPYYsxjzs8CgZ7Nb5n2K2rA==", + "dev": true, + "dependencies": { + "@jsonjoy.com/base64": "^1.1.1", + "@jsonjoy.com/util": "^1.1.2", + "hyperdyperid": "^1.2.0", + "thingies": "^1.20.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.6.0.tgz", + "integrity": "sha512-sw/RMbehRhN68WRtcKCpQOPfnH6lLP4GJfqzi3iYej8tnzpZUDr6UkZYJjcjjC0FWEJOJbyM3PTIwxucUmDG2A==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", @@ -7393,11 +7424,10 @@ } }, "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "dev": true, - "license": "MIT" + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true }, "node_modules/@types/semver": { "version": "7.5.8", @@ -25086,48 +25116,6 @@ "dev": true, "license": "ISC" }, - "node_modules/appium-xcuitest-driver/node_modules/sharp": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.1.tgz", - "integrity": "sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.3", - "semver": "^7.7.1" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.1", - "@img/sharp-darwin-x64": "0.34.1", - "@img/sharp-libvips-darwin-arm64": "1.1.0", - "@img/sharp-libvips-darwin-x64": "1.1.0", - "@img/sharp-libvips-linux-arm": "1.1.0", - "@img/sharp-libvips-linux-arm64": "1.1.0", - "@img/sharp-libvips-linux-ppc64": "1.1.0", - "@img/sharp-libvips-linux-s390x": "1.1.0", - "@img/sharp-libvips-linux-x64": "1.1.0", - "@img/sharp-libvips-linuxmusl-arm64": "1.1.0", - "@img/sharp-libvips-linuxmusl-x64": "1.1.0", - "@img/sharp-linux-arm": "0.34.1", - "@img/sharp-linux-arm64": "0.34.1", - "@img/sharp-linux-s390x": "0.34.1", - "@img/sharp-linux-x64": "0.34.1", - "@img/sharp-linuxmusl-arm64": "0.34.1", - "@img/sharp-linuxmusl-x64": "0.34.1", - "@img/sharp-wasm32": "0.34.1", - "@img/sharp-win32-ia32": "0.34.1", - "@img/sharp-win32-x64": "0.34.1" - } - }, "node_modules/appium-xcuitest-driver/node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -27650,6 +27638,21 @@ "dev": true, "license": "MIT" }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -30330,92 +30333,34 @@ "node": ">=16.0.0" } }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/default-gateway/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", "dev": true, - "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/default-gateway/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/default-gateway/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/default-gateway/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/default-gateway/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -33328,13 +33273,6 @@ "dev": true, "license": "ISC" }, - "node_modules/fs-monkey": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", - "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", - "dev": true, - "license": "Unlicense" - }, "node_modules/fs-native-extensions": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/fs-native-extensions/-/fs-native-extensions-1.3.3.tgz", @@ -34425,23 +34363,6 @@ "node": ">=12" } }, - "node_modules/html-entities": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", - "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ], - "license": "MIT" - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -34699,6 +34620,15 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "dev": true, + "engines": { + "node": ">=10.18" + } + }, "node_modules/i18next": { "version": "22.5.1", "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.5.1.tgz", @@ -35329,6 +35259,39 @@ "node": ">=0.10.0" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container/node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-installed-globally": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", @@ -35393,6 +35356,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-network-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", + "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -38748,16 +38723,22 @@ } }, "node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.17.2.tgz", + "integrity": "sha512-NgYhCOWgovOXSzvYgUW0LQ7Qy72rWQMGGFJDoWg4G30RHd3z77VbYdtJ4fembJXBy8pMIUA31XNAupobOQlwdg==", "dev": true, - "license": "Unlicense", "dependencies": { - "fs-monkey": "^1.0.4" + "@jsonjoy.com/json-pack": "^1.0.3", + "@jsonjoy.com/util": "^1.3.0", + "tree-dump": "^1.0.1", + "tslib": "^2.0.0" }, "engines": { "node": ">= 4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" } }, "node_modules/memory-chunk-store": { @@ -40267,17 +40248,20 @@ } }, "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", + "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", "dev": true, - "license": "MIT", "dependencies": { - "@types/retry": "0.12.0", + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", "retry": "^0.13.1" }, "engines": { - "node": ">=8" + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-try": { @@ -43304,7 +43288,6 @@ "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 4" } @@ -43529,6 +43512,18 @@ "node": ">=8" } }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/run-async": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", @@ -45845,6 +45840,18 @@ "node": ">=0.8" } }, + "node_modules/thingies": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", + "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", + "dev": true, + "engines": { + "node": ">=10.18" + }, + "peerDependencies": { + "tslib": "^2" + } + }, "node_modules/throttle-debounce": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.3.0.tgz", @@ -46094,6 +46101,22 @@ "node": ">=12" } }, + "node_modules/tree-dump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.3.tgz", + "integrity": "sha512-il+Cv80yVHFBwokQSfd4bldvr1Md951DpgAGfmhydt04L+YzHgubm2tQ7zueWDcGENKHq0ZvGFR/hjvNXilHEg==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -47486,79 +47509,81 @@ } }, "node_modules/webpack-dev-middleware": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", - "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz", + "integrity": "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==", "dev": true, - "license": "MIT", "dependencies": { "colorette": "^2.0.10", - "memfs": "^3.4.3", + "memfs": "^4.6.0", "mime-types": "^2.1.31", + "on-finished": "^2.4.1", "range-parser": "^1.2.1", "schema-utils": "^4.0.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } } }, "node_modules/webpack-dev-server": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", - "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.5", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.2.tgz", + "integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==", + "dev": true, + "dependencies": { + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/express-serve-static-core": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", "colorette": "^2.0.10", "compression": "^1.7.4", "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", + "express": "^4.21.2", "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", + "http-proxy-middleware": "^2.0.9", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", "serve-index": "^1.9.1", "sockjs": "^0.3.24", "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.4", - "ws": "^8.13.0" + "webpack-dev-middleware": "^7.4.2", + "ws": "^8.18.0" }, "bin": { "webpack-dev-server": "bin/webpack-dev-server.js" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" + "webpack": "^5.0.0" }, "peerDependenciesMeta": { "webpack": { @@ -47569,6 +47594,18 @@ } } }, + "node_modules/webpack-dev-server/node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, "node_modules/webpack-dev-server/node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -47594,26 +47631,16 @@ "fsevents": "~2.3.2" } }, - "node_modules/webpack-dev-server/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/webpack-dev-server/node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, "engines": { - "node": "*" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/webpack-dev-server/node_modules/glob-parent": { @@ -47629,34 +47656,50 @@ "node": ">= 6" } }, - "node_modules/webpack-dev-server/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/webpack-dev-server/node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "dev": true, - "license": "MIT", "dependencies": { - "picomatch": "^2.2.1" + "is-inside-container": "^1.0.0" }, "engines": { - "node": ">=8.10.0" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/webpack-dev-server/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "node_modules/webpack-dev-server/node_modules/open": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.2.tgz", + "integrity": "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==", "dev": true, - "license": "ISC", "dependencies": { - "glob": "^7.1.3" + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/webpack-dev-server/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" } }, "node_modules/webpack-merge": { diff --git a/package.json b/package.json index cb4dcf6e7..e4400f4b7 100644 --- a/package.json +++ b/package.json @@ -135,7 +135,7 @@ "typescript": "^5.7.2", "webpack": "5", "webpack-cli": "^5.0.1", - "webpack-dev-server": "^4.13.1", + "webpack-dev-server": "^5.2.2", "webpack-merge": "^5.8.0", "workbox-webpack-plugin": "^6.5.4", "yaml-loader": "^0.8.0" diff --git a/src/ui/components/CardDetails/CardDetailsBlock/CardBlock.tsx b/src/ui/components/CardDetails/CardDetailsBlock/CardBlock.tsx index 1b4c83403..c91e73c30 100644 --- a/src/ui/components/CardDetails/CardDetailsBlock/CardBlock.tsx +++ b/src/ui/components/CardDetails/CardDetailsBlock/CardBlock.tsx @@ -21,11 +21,13 @@ const CardBlock = ({ }); const buttonTestId = testId ? `${testId}-nav-button` : undefined; + const containerTestId = testId ? `${testId}-card-block` : undefined; return ( {title && ( { const classes = combineClassNames("card-details-info-block", className); return ( -
+
{title && (

{children} diff --git a/src/ui/components/CardDetails/CardDetailsBlock/CardDetailsBlock.types.ts b/src/ui/components/CardDetails/CardDetailsBlock/CardDetailsBlock.types.ts index f61b511f9..6feae598f 100644 --- a/src/ui/components/CardDetails/CardDetailsBlock/CardDetailsBlock.types.ts +++ b/src/ui/components/CardDetails/CardDetailsBlock/CardDetailsBlock.types.ts @@ -6,6 +6,7 @@ interface CardDetailsBlockProps { children?: ReactNode; className?: string; onClick?: () => void; + dataTestId?: string; } enum FlatBorderType { diff --git a/src/ui/components/CardDetails/CardDetailsExpandAttributes/CardDetailsAttribute.test.tsx b/src/ui/components/CardDetails/CardDetailsExpandAttributes/CardDetailsAttribute.test.tsx new file mode 100644 index 000000000..789153869 --- /dev/null +++ b/src/ui/components/CardDetails/CardDetailsExpandAttributes/CardDetailsAttribute.test.tsx @@ -0,0 +1,87 @@ +import { render } from "@testing-library/react"; +import { Provider } from "react-redux"; +import Eng_trans from "../../../../locales/en/en.json"; +import { store } from "../../../../store"; +import { CardDetailsAttribute } from "./CardDetailsAttribute"; + +describe("CardDetailsAttribute", () => { + test("Render nested value", async () => { + const { getAllByTestId, getByText } = render( + + + + ); + + expect(getAllByTestId("nested-attributes").length).toBe(3); + expect( + getByText( + Eng_trans.tabs.credentials.details.attributes.issuee.concat(":") + ) + ).toBeVisible(); + expect( + getByText( + Eng_trans.tabs.credentials.details.attributes.issuancedate.concat(":") + ) + ).toBeVisible(); + expect( + getByText(Eng_trans.tabs.credentials.details.status.label) + ).toBeVisible(); + expect( + getByText("EJ3HSnEqtSm3WiucWkeBbKspmEAIjf2N6wr5EKOcQ9Vl") + ).toBeVisible(); + expect( + getByText("EJWgO4hwKxNMxu2aUpmGFMozKt9Eq2Jz8n-xXR7CYtY_") + ).toBeVisible(); + expect(getByText("5493001KJTIIGC8Y1R17")).toBeVisible(); + expect(getByText("Qualified vLEI Issuer Credential")).toBeVisible(); + expect( + getByText( + "A vLEI Credential issued by GLEIF to Qualified vLEI Issuers which allows the Qualified vLEI Issuers to issue, verify and revoke Legal Entity vLEI Credentials and Legal Entity Official Organizational Role vLEI Credentials" + ) + ).toBeVisible(); + expect(getByText("description:")).toBeVisible(); + }); + + test("Ignore key", async () => { + const { queryAllByTestId } = render( + + + + ); + + expect(queryAllByTestId("nested-attributes").length).toBe(0); + }); +}); diff --git a/src/ui/components/ListHeader/ListHeader.test.tsx b/src/ui/components/ListHeader/ListHeader.test.tsx new file mode 100644 index 000000000..5cf2cdda3 --- /dev/null +++ b/src/ui/components/ListHeader/ListHeader.test.tsx @@ -0,0 +1,17 @@ +import { render } from "@testing-library/react"; +import { ListHeader } from "./ListHeader"; + +describe("List Header", () => { + test("Render back button", async () => { + const { getByTestId, getByText } = render( + + ); + + expect(getByText("title")).toBeVisible(); + expect(getByTestId("list-header-first-icon")).toBeVisible(); + expect(getByTestId("list-header-second-icon")).toBeVisible(); + }); +}); diff --git a/src/ui/components/PageFooter/PageFooter.test.tsx b/src/ui/components/PageFooter/PageFooter.test.tsx index 6e180bce9..0780f78c7 100644 --- a/src/ui/components/PageFooter/PageFooter.test.tsx +++ b/src/ui/components/PageFooter/PageFooter.test.tsx @@ -1,4 +1,5 @@ import { fireEvent, render } from "@testing-library/react"; +import { chevronForwardOutline } from "ionicons/icons"; import { PageFooter } from "./PageFooter"; describe("Page Footer", () => { @@ -9,17 +10,31 @@ describe("Page Footer", () => { const secondaryButtonAction = jest.fn(); const tertiaryButtonText = "tertiaryButtonText"; const tertiaryButtonAction = jest.fn(); + const archiveButtonText = "archiveButtonText"; + const archiveButtonAction = jest.fn(); + const declineButtonText = "declineButtonText"; + const declineButtonAction = jest.fn(); + const deleteButtonText = "deleteButtonText"; + const deleteButtonAction = jest.fn(); test("Renders all enabled buttons + page id", () => { const { getByText, getByTestId } = render( ); @@ -35,6 +50,15 @@ describe("Page Footer", () => { fireEvent.click(getByTestId(`tertiary-button${`-${pageId}`}`)); expect(tertiaryButtonAction.mock.calls.length).toEqual(1); + + fireEvent.click(getByTestId(`archive-button${`-${pageId}`}`)); + expect(archiveButtonAction.mock.calls.length).toEqual(1); + + fireEvent.click(getByTestId(`decline-button${`-${pageId}`}`)); + expect(declineButtonAction.mock.calls.length).toEqual(1); + + fireEvent.click(getByTestId(`delete-button${`-${pageId}`}`)); + expect(deleteButtonAction.mock.calls.length).toEqual(1); }); test("Renders all disabled buttons + no page id", () => { @@ -43,21 +67,52 @@ describe("Page Footer", () => { primaryButtonText={primaryButtonText} primaryButtonAction={primaryButtonAction} primaryButtonDisabled={true} + primaryButtonIcon={chevronForwardOutline} secondaryButtonText={secondaryButtonText} secondaryButtonAction={secondaryButtonAction} + secondaryButtonIcon={chevronForwardOutline} secondaryButtonDisabled={true} tertiaryButtonText={tertiaryButtonText} tertiaryButtonAction={tertiaryButtonAction} tertiaryButtonDisabled={true} + tertiaryButtonIcon={chevronForwardOutline} + archiveButtonText={archiveButtonText} + archiveButtonAction={archiveButtonAction} + archiveButtonDisabled + declineButtonText={declineButtonText} + declineButtonAction={declineButtonAction} + declineButtonDisabled + declineButtonIcon={chevronForwardOutline} + deleteButtonText={deleteButtonText} + deleteButtonAction={deleteButtonAction} + deleteButtonDisabled /> ); expect(getByText(primaryButtonText)).toBeInTheDocument(); expect(getByText(secondaryButtonText)).toBeInTheDocument(); expect(getByText(tertiaryButtonText)).toBeInTheDocument(); + expect(getByText(archiveButtonText)).toBeInTheDocument(); + expect(getByText(declineButtonText)).toBeInTheDocument(); expect(getByTestId("primary-button")).toHaveAttribute("disabled", "true"); expect(getByTestId("secondary-button")).toHaveAttribute("disabled", "true"); expect(getByTestId("tertiary-button")).toHaveAttribute("disabled", "true"); + expect(getByTestId("primary-button")).toHaveAttribute("disabled", "true"); + expect(getByTestId("archive-button")).toHaveAttribute("disabled", "true"); + expect(getByTestId("decline-button")).toHaveAttribute("disabled", "true"); + }); + + test("Render button with link", () => { + const link = "samplelink"; + + const { getByText } = render( + + ); + + expect(getByText(primaryButtonText).getAttribute("href")).toBe(link); }); }); diff --git a/src/ui/components/VerifyPasscode/VerifyPasscode.test.tsx b/src/ui/components/VerifyPasscode/VerifyPasscode.test.tsx index f3dfaf28b..4f9992b4a 100644 --- a/src/ui/components/VerifyPasscode/VerifyPasscode.test.tsx +++ b/src/ui/components/VerifyPasscode/VerifyPasscode.test.tsx @@ -1,7 +1,7 @@ const verifySecretMock = jest.fn(); import { AnyAction, Store } from "@reduxjs/toolkit"; -import { fireEvent, render, waitFor } from "@testing-library/react"; +import { fireEvent, getByText, render, waitFor } from "@testing-library/react"; import { act } from "react"; import { Provider } from "react-redux"; import { MemoryRouter, Route } from "react-router-dom"; @@ -13,6 +13,7 @@ import { TabsRoutePath } from "../../components/navigation/TabsMenu"; import { CredentialDetails } from "../../pages/CredentialDetails"; import { VerifyPasscode } from "./VerifyPasscode"; import { connectionsMapFix } from "../../__fixtures__/connectionsFix"; +import { passcodeFiller } from "../../utils/passcodeFiller"; const path = TabsRoutePath.CREDENTIALS + "/" + credsFixAcdc[0].id; @@ -24,6 +25,12 @@ jest.mock("react-router-dom", () => ({ useRouteMatch: () => ({ url: path }), })); +jest.mock("@ionic/react", () => ({ + ...jest.requireActual("@ionic/react"), + IonModal: ({ children, isOpen, ...props }: any) => + isOpen ?
{children}
: null, +})); + jest.mock("../../../core/agent/agent", () => ({ Agent: { agent: { @@ -109,20 +116,58 @@ describe("Verify Passcode on Cards Details page", () => { }); }); + test("Remove passcode", async () => { + const mockStore = configureStore(); + const dispatchMock = jest.fn(); + storeMocked = { + ...mockStore(initialStateNoPassword), + dispatch: dispatchMock, + }; + + const closeFn = jest.fn(); + + const { getByTestId, getByText } = render( + + + + ); + + await waitFor(() => { + expect(getByTestId("close-button-label")).toBeInTheDocument(); + }); + + await passcodeFiller(getByText, getByTestId, "12223"); + + fireEvent.click(getByTestId("setpasscode-backspace-button")); + + await waitFor(() => { + expect( + getByTestId("circle-" + 4).classList.contains( + "passcode-module-circle-fill" + ) + ).toBe(false); + }); + }); + test("It renders verify passcode when clicking on the big button", async () => { jest .spyOn(Agent.agent.credentials, "getCredentialDetailsById") .mockResolvedValue(credsFixAcdc[0]); - const { findByTestId, getAllByText, getAllByTestId, findByText } = render( - - - - - - ); + const { findByTestId, getAllByText, queryByTestId, findByText, getByText } = + render( + + + + + + ); const archiveButton = await findByTestId( "archive-button-credential-card-details" @@ -138,6 +183,7 @@ describe("Verify Passcode on Cards Details page", () => { ); expect(text).toBeVisible(); + expect(queryByTestId("verify-passcode")).toBeNull(); }); act(() => { @@ -149,10 +195,87 @@ describe("Verify Passcode on Cards Details page", () => { }); await waitFor(() => { - expect(getAllByTestId("verify-passcode")[0]).toHaveAttribute( - "is-open", - "true" - ); + expect(getByText(EN_TRANSLATIONS.verifypasscode.title)).toBeVisible(); + }); + }); + + test("Invalid passcode", async () => { + verifySecretMock.mockImplementation(() => Promise.reject({ code: -35 })); + + const closeFn = jest.fn(); + + const { getByTestId, getByText } = render( + + + + ); + + await passcodeFiller(getByText, getByTestId, "122236"); + + await waitFor(() => { + expect(getByText(EN_TRANSLATIONS.verifypasscode.error)).toBeVisible(); + }); + }); + + test("Open forgot password modal", async () => { + const closeFn = jest.fn(); + + const { getByTestId, getByText, getAllByText, queryByText } = render( + + + + ); + + fireEvent.click(getByTestId("secondary-button-verify-passcode")); + + await waitFor(() => { + expect( + getByText(EN_TRANSLATIONS.verifypasscode.alert.text.verify) + ).toBeVisible(); + }); + + fireEvent.click( + getByText(EN_TRANSLATIONS.verifypasscode.alert.button.verify) + ); + + await waitFor(() => { + expect(getByTestId("forgot-auth-info-modal")).toBeVisible(); + }); + + fireEvent.click(getAllByText(EN_TRANSLATIONS.forgotauth.cancel)[0]); + + await waitFor(() => { + expect( + queryByText(EN_TRANSLATIONS.forgotauth.newpasscode.title) + ).toBeNull(); + }); + }); + + test("Open forgot password modal", async () => { + const closeFn = jest.fn(); + + const { getByTestId } = render( + + + + ); + + fireEvent.click(getByTestId("close-button")); + + await waitFor(() => { + expect(closeFn).toBeCalled(); }); }); }); diff --git a/src/ui/components/VerifyPasscode/VerifyPasscode.tsx b/src/ui/components/VerifyPasscode/VerifyPasscode.tsx index 20e655cca..3de1ba7de 100644 --- a/src/ui/components/VerifyPasscode/VerifyPasscode.tsx +++ b/src/ui/components/VerifyPasscode/VerifyPasscode.tsx @@ -74,12 +74,14 @@ const VerifyPasscode = ({ setOpenRecoveryAuth(true); }; + const onClose = () => handleClearState(true); + return ( handleClearState(true)} + onDidDismiss={onClose} > handleClearState(true)} + closeButtonAction={onClose} /> } pageId={`${componentId}-content`} diff --git a/src/ui/components/VerifyPassword/VerifyPassword.test.tsx b/src/ui/components/VerifyPassword/VerifyPassword.test.tsx index fe116e666..084ffdf2d 100644 --- a/src/ui/components/VerifyPassword/VerifyPassword.test.tsx +++ b/src/ui/components/VerifyPassword/VerifyPassword.test.tsx @@ -3,17 +3,18 @@ const verifySecretMock = jest.fn(); import { IonInput } from "@ionic/react"; import { ionFireEvent } from "@ionic/react-test-utils"; import { AnyAction, Store } from "@reduxjs/toolkit"; -import { render, waitFor } from "@testing-library/react"; +import { fireEvent, render, waitFor } from "@testing-library/react"; import { act } from "react"; import { Provider } from "react-redux"; import configureStore from "redux-mock-store"; import { Agent } from "../../../core/agent/agent"; +import { BasicRecord } from "../../../core/agent/records"; import { SecureStorage } from "../../../core/storage"; +import ENG_Trans from "../../../locales/en/en.json"; import { credsFixAcdc } from "../../__fixtures__/credsFix"; import { TabsRoutePath } from "../../components/navigation/TabsMenu"; import { CustomInputProps } from "../CustomInput/CustomInput.types"; import { VerifyPassword } from "./VerifyPassword"; -import { BasicRecord } from "../../../core/agent/records"; const path = TabsRoutePath.CREDENTIALS + "/" + credsFixAcdc[0].id; @@ -244,7 +245,7 @@ describe("Verify Password", () => { const setIsOpenMock = jest.fn(); const onVerifyMock = jest.fn(); - const { getByTestId } = render( + const { getByTestId, getByText, queryByText } = render( { await waitFor(() => { expect(getByTestId("forgot-hint-btn")).toBeVisible(); }); + + fireEvent.click(getByTestId("forgot-hint-btn")); + + await waitFor(() => { + expect( + getByText(ENG_Trans.verifypassword.alert.choice.title) + ).toBeVisible(); + }); + + fireEvent.click( + getByText(ENG_Trans.verifypassword.alert.button.seepasswordhint) + ); + + await waitFor(() => { + expect( + getByText(ENG_Trans.verifypassword.alert.hint.title) + ).toBeVisible(); + }); + + fireEvent.click(getByText(ENG_Trans.verifypassword.alert.button.tryagain)); + + await waitFor(() => { + expect(queryByText(ENG_Trans.verifypassword.alert.hint.title)).toBeNull(); + }); + }); + + test("Recovery password", async () => { + jest.spyOn(Agent.agent.basicStorage, "findById").mockResolvedValue( + Promise.resolve({ + content: { + value: "1111", + }, + } as any) + ); + + const mockStore = configureStore(); + const dispatchMock = jest.fn(); + storeMocked = { + ...mockStore(initialStateWithPassword), + dispatch: dispatchMock, + }; + + const setIsOpenMock = jest.fn(); + const onVerifyMock = jest.fn(); + + const { + getByTestId, + getByText, + getAllByTestId, + queryByText, + getAllByText, + } = render( + + + + ); + + await waitFor(() => { + expect(getByTestId("forgot-hint-btn")).toBeVisible(); + }); + + fireEvent.click(getByTestId("forgot-hint-btn")); + + await waitFor(() => { + expect( + getByText(ENG_Trans.verifypassword.alert.choice.title) + ).toBeVisible(); + }); + + fireEvent.click( + getByText(ENG_Trans.verifypassword.alert.button.seepasswordhint) + ); + + await waitFor(() => { + expect( + getByText(ENG_Trans.verifypassword.alert.hint.title) + ).toBeVisible(); + }); + + fireEvent.click( + getAllByText(ENG_Trans.verifypassword.alert.button.resetmypassword)[1] + ); + + await waitFor(() => { + expect(getByText(ENG_Trans.forgotauth.password.title)).toBeVisible(); + }); + }); + + test("Close verify password", async () => { + jest.spyOn(Agent.agent.basicStorage, "findById").mockResolvedValue( + Promise.resolve({ + content: { + value: "1111", + }, + } as any) + ); + + const mockStore = configureStore(); + const dispatchMock = jest.fn(); + storeMocked = { + ...mockStore(initialStateWithPassword), + dispatch: dispatchMock, + }; + + const setIsOpenMock = jest.fn(); + const onVerifyMock = jest.fn(); + + const { getAllByText } = render( + + + + ); + + fireEvent.click(getAllByText(ENG_Trans.verifypassword.cancel)[0]); + + expect(setIsOpenMock).toBeCalled(); }); }); diff --git a/src/ui/components/VerifyPassword/VerifyPassword.tsx b/src/ui/components/VerifyPassword/VerifyPassword.tsx index 3fd7dbd1c..2a1008441 100644 --- a/src/ui/components/VerifyPassword/VerifyPassword.tsx +++ b/src/ui/components/VerifyPassword/VerifyPassword.tsx @@ -124,7 +124,7 @@ const VerifyPassword = ({ modalIsOpen={isOpen} componentId="verify-password" customClasses="verify-password-modal" - onDismiss={() => resetModal()} + onDismiss={resetModal} header={headerOptions} >
diff --git a/src/ui/components/layout/TabLayout/TabLayout.test.tsx b/src/ui/components/layout/TabLayout/TabLayout.test.tsx new file mode 100644 index 000000000..adb1ffa49 --- /dev/null +++ b/src/ui/components/layout/TabLayout/TabLayout.test.tsx @@ -0,0 +1,62 @@ +import { fireEvent, render, waitFor } from "@testing-library/react"; +import { mockIonicReact } from "@ionic/react-test-utils"; +import { TabLayout } from "./TabLayout"; + +mockIonicReact(); + +describe("Tab layout", () => { + test("Render back button", async () => { + const backButtonAction = jest.fn(); + const { getByTestId } = render( + + ); + + await waitFor(() => { + expect(getByTestId("tab-back-button")).toBeVisible(); + }); + + fireEvent.click(getByTestId("tab-back-button")); + expect(backButtonAction).toBeCalled(); + }); + + test("Render done button", async () => { + const doneAction = jest.fn(); + const { getByTestId } = render( + + ); + + await waitFor(() => { + expect(getByTestId("tab-done-button")).toBeVisible(); + }); + + fireEvent.click(getByTestId("tab-done-button")); + expect(doneAction).toBeCalled(); + }); + + test("Render action button", async () => { + const actionButtonAction = jest.fn(); + const { getByTestId } = render( + + ); + + await waitFor(() => { + expect(getByTestId("action-button")).toBeVisible(); + }); + + fireEvent.click(getByTestId("action-button")); + expect(actionButtonAction).toBeCalled(); + }); +}); diff --git a/src/ui/pages/IncomingRequest/IncomingRequest.test.tsx b/src/ui/pages/IncomingRequest/IncomingRequest.test.tsx index d76b94bdf..46d26bcc4 100644 --- a/src/ui/pages/IncomingRequest/IncomingRequest.test.tsx +++ b/src/ui/pages/IncomingRequest/IncomingRequest.test.tsx @@ -262,4 +262,42 @@ describe("Sign request", () => { getByText(JSON.parse(signObjectFix.payload.payload).data.id) ).toBeVisible(); }); + + test("Incoming request is empty", async () => { + const initialState = { + stateCache: { + routes: [TabsRoutePath.IDENTIFIERS], + authentication: { + loggedIn: true, + time: Date.now(), + passcodeIsSet: true, + passwordIsSet: false, + }, + queueIncomingRequest: { + isProcessing: true, + queues: [], + isPaused: false, + }, + }, + biometricsCache: { + enabled: false, + }, + }; + + const storeMocked = { + ...mockStore(initialState), + dispatch: dispatchMock, + }; + + const { queryByText } = render( + + + + ); + + expect(queryByText(requestData.peerConnection?.name)).toBeNull(); + }); }); diff --git a/src/ui/pages/NotificationDetails/components/CredentialRequest/CredentialRequestInformation/CredentialRequestInformation.test.tsx b/src/ui/pages/NotificationDetails/components/CredentialRequest/CredentialRequestInformation/CredentialRequestInformation.test.tsx index 2be13298d..610b53123 100644 --- a/src/ui/pages/NotificationDetails/components/CredentialRequest/CredentialRequestInformation/CredentialRequestInformation.test.tsx +++ b/src/ui/pages/NotificationDetails/components/CredentialRequest/CredentialRequestInformation/CredentialRequestInformation.test.tsx @@ -19,6 +19,7 @@ jest.mock("@ionic/react", () => ({ const deleteNotificationMock = jest.fn((id: string) => Promise.resolve(id)); const joinMultisigOfferMock = jest.fn(); +const getOfferedCredentialSaid = jest.fn(() => "cred-id"); jest.mock("../../../../../../core/agent/agent", () => ({ Agent: { @@ -29,7 +30,7 @@ jest.mock("../../../../../../core/agent/agent", () => ({ }, ipexCommunications: { joinMultisigOffer: () => joinMultisigOfferMock(), - getOfferedCredentialSaid: jest.fn(() => "cred-id"), + getOfferedCredentialSaid: () => getOfferedCredentialSaid(), }, auth: { verifySecret: jest.fn().mockResolvedValue(true), @@ -114,6 +115,10 @@ describe("Credential request information", () => { getByTestId("multisig-request-alert-decline-confirm-button") ); + fireEvent.click( + getByTestId("multisig-request-alert-decline-cancel-button") + ); + await waitFor(() => { expect( queryByText( @@ -1810,4 +1815,80 @@ describe("Credential request information: multisig", () => { unmount(); document.getElementsByTagName("body")[0].innerHTML = ""; }); + + test("Open proposed cred", async () => { + const linkedGroup = { + linkedRequest: { + accepted: true, + current: "EKfweht5lOkjaguB5dz42BMkfejhBFIF9-ghumzCJ6nv", + previous: undefined, + }, + threshold: "2", + members: ["member-1", "member-2", "member-3"], + othersJoined: ["member-1"], + memberInfos: [ + { + aid: "member-1", + name: "Member 1", + joined: true, + }, + { + aid: "member-2", + name: "Member 2", + joined: true, + }, + { + aid: "member-3", + name: "Member 3", + joined: false, + }, + ], + }; + + const storeMocked = { + ...mockStore({ + ...initialState, + credsCache: { + creds: [{ ...credsFixAcdc[0], id: "cred-id" }], + }, + }), + dispatch: dispatchMock, + }; + + const back = jest.fn(); + + const { getByTestId, getByText, queryByTestId } = render( + + + + ); + + await waitFor(() => { + expect(getOfferedCredentialSaid).toBeCalled(); + }); + + expect(getByTestId("proposed-cred-card")).toBeVisible(); + + fireEvent.click(getByTestId("proposed-cred-card")); + + await waitFor(() => { + expect(getByTestId("request-cred-detail-modal")).toBeVisible(); + }); + + fireEvent.click(getByText(EN_TRANSLATIONS.tabs.credentials.details.done)); + + await waitFor(() => { + expect(queryByTestId("request-cred-detail-modal")).toBeNull(); + }); + }); }); diff --git a/src/ui/pages/NotificationDetails/components/CredentialRequest/CredentialRequestInformation/CredentialRequestInformation.tsx b/src/ui/pages/NotificationDetails/components/CredentialRequest/CredentialRequestInformation/CredentialRequestInformation.tsx index fa9b8c238..cf41d9d23 100644 --- a/src/ui/pages/NotificationDetails/components/CredentialRequest/CredentialRequestInformation/CredentialRequestInformation.tsx +++ b/src/ui/pages/NotificationDetails/components/CredentialRequest/CredentialRequestInformation/CredentialRequestInformation.tsx @@ -344,6 +344,7 @@ const CredentialRequestInformation = ({ {linkedGroup?.linkedRequest.current && ( <> setViewCredId(undefined)} + setIsOpen={handleClose} onClose={handleClose} joinedCredRequestMembers={linkedGroup?.memberInfos} viewOnly diff --git a/src/ui/pages/Onboarding/Onboarding.test.tsx b/src/ui/pages/Onboarding/Onboarding.test.tsx index 8e8b29a4c..6894c2214 100644 --- a/src/ui/pages/Onboarding/Onboarding.test.tsx +++ b/src/ui/pages/Onboarding/Onboarding.test.tsx @@ -12,18 +12,6 @@ import { CreatePassword } from "../CreatePassword"; import { SetPasscode } from "../SetPasscode"; import { Onboarding } from "./index"; -jest.mock("../../../core/configuration", () => ({ - ...jest.requireActual("../../../core/configuration"), - ConfigurationService: { - env: { - features: { - cut: [], - customContent: [], - }, - }, - }, -})); - const exitApp = jest.fn(); jest.mock("@capacitor/app", () => ({ ...jest.requireActual("@capacitor/app"),