diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index eb5cba75bf..0000000000 --- a/jest.config.js +++ /dev/null @@ -1,23 +0,0 @@ -/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', - globals: { - 'ts-jest': {} - }, - testTimeout: 35000, - setupFilesAfterEnv: ['./jest.setup.ts'], - collectCoverageFrom: ['**/*.{js,jsx,ts,tsx}', '!**/*.config.js'], - coverageDirectory: '/coverage', - coveragePathIgnorePatterns: [ - '/node_modules', - '/public', - '/dist', - '/build', - '/coverage' - ], - coverageReporters: ['text', 'html'], - projects: ['/src/backend', '/src/frontend'], - - rootDir: '.' -} diff --git a/jest.setup.ts b/jest.setup.ts deleted file mode 100644 index 31775ac4da..0000000000 --- a/jest.setup.ts +++ /dev/null @@ -1 +0,0 @@ -jest.setTimeout(35000) diff --git a/package.json b/package.json index 513eef0838..a6d9704e0a 100644 --- a/package.json +++ b/package.json @@ -21,15 +21,16 @@ "debug:react": "react-devtools", "codecheck": "tsc --noEmit", "find-deadcode": "ts-prune --error", - "test": "jest", - "testProxy": "jest proxy.test.ts", - "test-watch": "jest --watch --maxWorkers=25%", - "test:ci": "jest --runInBand --silent", + "test": "vitest", + "test:coverage": "vitest --coverage", + "testProxy": "vitest proxy.test.ts", + "test-watch": "vitest --watch --maxWorkers=25%", + "test:ci": "vitest --runInBand --silent", "test:e2e-ci": "cross-env-shell bash e2e/entrypoint.sh", "test:e2ePackaged-ci": "cross-env TEST_PACKAGED=true pnpm test:e2e-ci", "test:e2e": "cross-env-shell docker compose -f e2e/docker-compose.yml run --rm --build process_all bash e2e/entrypoint.sh", "test:e2ePackaged": "cross-env TEST_PACKAGED=true pnpm test:e2e", - "manualTestProxyJest": "jest mmExtIntegration.test.ts", + "manualUnitTestProxy": "vitest mmExtIntegration.test.ts", "release:linux": "pnpm pkgResetExtension:x64:linux && export NODE_ENV_ELECTRON_VITE=production && electron-vite build && cross-env ELECTRON_MIRROR=https://github.com/HyperPlay-Gaming/electron-releases/releases/download/ ELECTRON_CUSTOM_DIR=v33.2.0 electron-builder -p always --linux deb rpm pacman tar.xz", "release:updateFlathub:ci": "tsc flathub/update-flathub.ts --skipLibCheck --target es2015 --moduleResolution node --module commonjs && node flathub/update-flathub.js", "release:mac:x64": "pnpm pkgResetExtension:x64:mac && export NODE_ENV_ELECTRON_VITE=production && electron-vite build && cross-env ELECTRON_MIRROR=https://github.com/HyperPlay-Gaming/electron-releases/releases/download/ ELECTRON_CUSTOM_DIR=v33.2.0 electron-builder -p always --mac --x64", @@ -119,7 +120,6 @@ "i18next-fs-backend": "^2.3.2", "i18next-http-backend": "^2.5.2", "ini": "^3.0.1", - "jest-environment-jsdom": "^29.7.0", "jsdom": "^20.0.0", "json5": "^2.2.3", "launchdarkly-electron-client-sdk": "^1.7.0", @@ -159,8 +159,7 @@ }, "eslintConfig": { "extends": [ - "react-app", - "react-app/jest" + "react-app" ] }, "devDependencies": { @@ -172,7 +171,6 @@ "@playwright/test": "^1.46.0", "@tanstack/react-query-devtools": "^5.59.20", "@testing-library/dom": "^7.31.2", - "@testing-library/jest-dom": "^6.4.8", "@testing-library/react": "^14.3.1", "@testing-library/user-event": "^14.5.2", "@types/auto-launch": "^5.0.5", @@ -183,7 +181,6 @@ "@types/graceful-fs": "^4.1.9", "@types/i18next-fs-backend": "^1.1.5", "@types/ini": "^1.3.34", - "@types/jest": "^29.5.14", "@types/jsdom": "^20.0.1", "@types/mime": "^3.0.2", "@types/node": "^20.16.2", @@ -199,6 +196,7 @@ "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", "@vitejs/plugin-react": "^4.3.1", + "@vitest/coverage-v8": "3.0.9", "cross-env": "^7.0.3", "electron": "33.2.0", "electron-builder": "^25.1.8", @@ -211,7 +209,6 @@ "fast-xml-parser": "^4.4.1", "husky": "^9.1.4", "i18next-parser": "^9.0.1", - "jest": "^29.7.0", "pkg": "^5.8.1", "playwright": "^1.46.0", "prettier": "^2.8.8", @@ -220,11 +217,11 @@ "rimraf": "^6.0.1", "sass": "^1.55.0", "tmp": "^0.2.3", - "ts-jest": "^29.2.5", "type-fest": "^3.2.0", "typescript": "5.3.3", "vite": "^5.4.0", - "vite-plugin-svgr": "^2.2.2" + "vite-plugin-svgr": "^2.2.2", + "vitest": "^3.0.9" }, "optionalDependencies": { "@hyperplay/extension-importer": "^0.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f096e6d150..dc53459f7f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -185,9 +185,6 @@ importers: ini: specifier: ^3.0.1 version: 3.0.1 - jest-environment-jsdom: - specifier: ^29.7.0 - version: 29.7.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) jsdom: specifier: ^20.0.0 version: 20.0.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -343,9 +340,6 @@ importers: '@testing-library/dom': specifier: ^7.31.2 version: 7.31.2 - '@testing-library/jest-dom': - specifier: ^6.4.8 - version: 6.6.3 '@testing-library/react': specifier: ^14.3.1 version: 14.3.1(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -376,9 +370,6 @@ importers: '@types/ini': specifier: ^1.3.34 version: 1.3.34 - '@types/jest': - specifier: ^29.5.14 - version: 29.5.14 '@types/jsdom': specifier: ^20.0.1 version: 20.0.1 @@ -424,6 +415,9 @@ importers: '@vitejs/plugin-react': specifier: ^4.3.1 version: 4.3.4(vite@5.4.11(@types/node@20.17.10)(sass@1.83.0)(terser@5.37.0)) + '@vitest/coverage-v8': + specifier: 3.0.9 + version: 3.0.9(vitest@3.0.9(@types/debug@4.1.12)(@types/node@20.17.10)(jsdom@20.0.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(sass@1.83.0)(terser@5.37.0)) cross-env: specifier: ^7.0.3 version: 7.0.3 @@ -460,9 +454,6 @@ importers: i18next-parser: specifier: ^9.0.1 version: 9.0.2 - jest: - specifier: ^29.7.0 - version: 29.7.0(@types/node@20.17.10)(babel-plugin-macros@3.1.0) pkg: specifier: ^5.8.1 version: 5.8.1(encoding@0.1.13) @@ -484,9 +475,6 @@ importers: tmp: specifier: ^0.2.3 version: 0.2.3 - ts-jest: - specifier: ^29.2.5 - version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.10)(babel-plugin-macros@3.1.0))(typescript@5.3.3) type-fest: specifier: ^3.2.0 version: 3.13.1 @@ -499,6 +487,9 @@ importers: vite-plugin-svgr: specifier: ^2.2.2 version: 2.4.0(rollup@4.28.1)(vite@5.4.11(@types/node@20.17.10)(sass@1.83.0)(terser@5.37.0)) + vitest: + specifier: ^3.0.9 + version: 3.0.9(@types/debug@4.1.12)(@types/node@20.17.10)(jsdom@20.0.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(sass@1.83.0)(terser@5.37.0) packages: @@ -519,9 +510,6 @@ packages: graphql: ^15.5.0 || ^16.0.0 || ^17.0.0 typescript: ^5.0.0 - '@adobe/css-tools@4.4.1': - resolution: {integrity: sha512-12WGKBQzjUAI4ayyF4IAtfw2QR/IDoqk6jTddXDhtYTJF9ASmoE1zst7cVtP0aL/F1jUJL5r+JxKXKEgHNbEUQ==} - '@adraffy/ens-normalize@1.10.1': resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} @@ -1226,8 +1214,9 @@ packages: resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==} engines: {node: '>=6.9.0'} - '@bcoe/v8-coverage@0.2.3': - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} '@coinbase/wallet-sdk@3.9.3': resolution: {integrity: sha512-N/A2DRIf0Y3PHc1XAMvbBUu4zisna6qAdqABMZwBMNEfWrXpAwx16pZGkYCLGE+Rvv1edbcB2LYDRnACNcmCiw==} @@ -1924,19 +1913,6 @@ packages: resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} - '@jest/console@29.7.0': - resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/core@29.7.0': - resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - '@jest/create-cache-key-function@29.7.0': resolution: {integrity: sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1945,47 +1921,14 @@ packages: resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/expect-utils@29.7.0': - resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/expect@29.7.0': - resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/fake-timers@29.7.0': resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/globals@29.7.0': - resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/reporters@29.7.0': - resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - '@jest/schemas@29.6.3': resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/source-map@29.6.3': - resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/test-result@29.7.0': - resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/test-sequencer@29.7.0': - resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/transform@29.7.0': resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2984,10 +2927,6 @@ packages: resolution: {integrity: sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==} engines: {node: '>=14'} - '@testing-library/jest-dom@6.6.3': - resolution: {integrity: sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==} - engines: {node: '>=14', npm: '>=6', yarn: '>=1'} - '@testing-library/react@14.3.1': resolution: {integrity: sha512-H99XjUhWQw0lTgyMN05W3xQG1Nh4lq574D8keFf1dDoNTJgp66VbJozRaczoF+wsiaPJNt/TcnfpLGufGxSrZQ==} engines: {node: '>=14'} @@ -3141,9 +3080,6 @@ packages: '@types/istanbul-reports@3.0.4': resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} - '@types/jest@29.5.14': - resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} - '@types/jsdom@20.0.1': resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} @@ -3358,6 +3294,44 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 + '@vitest/coverage-v8@3.0.9': + resolution: {integrity: sha512-15OACZcBtQ34keIEn19JYTVuMFTlFrClclwWjHo/IRPg/8ELpkgNTl0o7WLP9WO9XGH6+tip9CPYtEOrIDJvBA==} + peerDependencies: + '@vitest/browser': 3.0.9 + vitest: 3.0.9 + peerDependenciesMeta: + '@vitest/browser': + optional: true + + '@vitest/expect@3.0.9': + resolution: {integrity: sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==} + + '@vitest/mocker@3.0.9': + resolution: {integrity: sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.0.9': + resolution: {integrity: sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==} + + '@vitest/runner@3.0.9': + resolution: {integrity: sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==} + + '@vitest/snapshot@3.0.9': + resolution: {integrity: sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==} + + '@vitest/spy@3.0.9': + resolution: {integrity: sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==} + + '@vitest/utils@3.0.9': + resolution: {integrity: sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==} + '@wagmi/connectors@5.7.8': resolution: {integrity: sha512-idLCc+GQ/GcGgxakEMC7/NSbpD6r1GB07lfDyEjvI5TMzl18pOZhKiqOTENzNi3hDas6ZMvS1xaGwrWufsb1rA==} peerDependencies: @@ -3610,10 +3584,6 @@ packages: anser@1.4.10: resolution: {integrity: sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==} - ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -3700,10 +3670,6 @@ packages: aria-query@5.1.3: resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} - aria-query@5.3.2: - resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} - engines: {node: '>= 0.4'} - array-buffer-byte-length@1.0.1: resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} engines: {node: '>= 0.4'} @@ -3750,6 +3716,10 @@ packages: resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} engines: {node: '>=0.8'} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + ast-types@0.15.2: resolution: {integrity: sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==} engines: {node: '>=4'} @@ -3969,10 +3939,6 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - bs-logger@0.2.6: - resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} - engines: {node: '>= 6'} - bs58@5.0.0: resolution: {integrity: sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==} @@ -4087,18 +4053,14 @@ packages: ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - chalk@3.0.0: - resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} - engines: {node: '>=8'} + chai@5.2.0: + resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} + engines: {node: '>=12'} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - char-regex@1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} - character-entities-html4@2.1.0: resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} @@ -4114,6 +4076,10 @@ packages: charenc@0.0.2: resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + cheerio-select@2.1.0: resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} @@ -4157,9 +4123,6 @@ packages: citty@0.1.6: resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} - cjs-module-lexer@1.4.1: - resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} - classic-level@1.4.1: resolution: {integrity: sha512-qGx/KJl3bvtOHrGau2WklEZuXhS3zme+jf+fsu6Ej7W7IP/C49v7KNlWIsT1jZu0YnfzSIYDGcEWpCa1wKGWXQ==} engines: {node: '>=12'} @@ -4231,16 +4194,9 @@ packages: resolution: {integrity: sha512-FMabTRlc5t5zjdenF6mS0MBeFZm0XqHqeOkcskKFb/LYCcRQ5fVgLOHVc4Lq9CqABd9zhjwPjMBCJvMCziSVtA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - co@4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - code-block-writer@11.0.3: resolution: {integrity: sha512-NiujjUFB4SwScJq2bwbYUtXbZhBSlY6vYzm++3Q6oC+U+injTqfPYFK8wS9COOmb2lueqp0ZRB4nK1VYeHgNyw==} - collect-v8-coverage@1.0.2: - resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} - color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -4413,11 +4369,6 @@ packages: buffer: optional: true - create-jest@29.7.0: - resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - cron-parser@4.9.0: resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} engines: {node: '>=12.0.0'} @@ -4454,9 +4405,6 @@ packages: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} - css.escape@1.5.1: - resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} - cssom@0.3.8: resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} @@ -4605,13 +4553,9 @@ packages: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} - dedent@1.5.3: - resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} deep-equal@2.2.3: resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} @@ -4628,10 +4572,6 @@ packages: resolution: {integrity: sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==} engines: {node: '>=0.10.0'} - deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} @@ -4698,10 +4638,6 @@ packages: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} - detect-newline@3.1.0: - resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} - engines: {node: '>=8'} - detect-node-es@1.1.0: resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} @@ -4714,10 +4650,6 @@ packages: dezalgo@1.0.4: resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} - diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dijkstrajs@1.0.3: resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} @@ -4758,9 +4690,6 @@ packages: dom-accessibility-api@0.5.16: resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} - dom-accessibility-api@0.6.3: - resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} - dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} @@ -4898,10 +4827,6 @@ packages: emitter-component@1.1.2: resolution: {integrity: sha512-QdXO3nXOzZB4pAjM0n6ZE+R9/+kPpECA/XSELIcc54NeYVnBqIk+4DFiBgK+8QbV3mdvTG6nedl7dTYgO+5wDw==} - emittery@0.13.1: - resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} - engines: {node: '>=12'} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -4980,6 +4905,9 @@ packages: resolution: {integrity: sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==} engines: {node: '>= 0.4'} + es-module-lexer@1.6.0: + resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} + es-object-atoms@1.0.0: resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} engines: {node: '>= 0.4'} @@ -5115,6 +5043,9 @@ packages: estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -5172,17 +5103,13 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} - exit@0.1.2: - resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} - engines: {node: '>= 0.8.0'} - expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} - expect@29.7.0: - resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + expect-type@1.2.0: + resolution: {integrity: sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA==} + engines: {node: '>=12.0.0'} exponential-backoff@3.1.1: resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} @@ -5805,11 +5732,6 @@ packages: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} - import-local@3.2.0: - resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} - engines: {node: '>=8'} - hasBin: true - imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -5967,10 +5889,6 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-generator-fn@2.1.0: - resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} - engines: {node: '>=6'} - is-generator-function@1.0.10: resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} engines: {node: '>= 0.4'} @@ -6139,16 +6057,12 @@ packages: resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} engines: {node: '>=8'} - istanbul-lib-instrument@6.0.3: - resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} - engines: {node: '>=10'} - istanbul-lib-report@3.0.1: resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} engines: {node: '>=10'} - istanbul-lib-source-maps@4.0.1: - resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} engines: {node: '>=10'} istanbul-reports@3.1.7: @@ -6171,57 +6085,6 @@ packages: engines: {node: '>=10'} hasBin: true - jest-changed-files@29.7.0: - resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-circus@29.7.0: - resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-cli@29.7.0: - resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - jest-config@29.7.0: - resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@types/node': '*' - ts-node: '>=9.0.0' - peerDependenciesMeta: - '@types/node': - optional: true - ts-node: - optional: true - - jest-diff@29.7.0: - resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-docblock@29.7.0: - resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-each@29.7.0: - resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-environment-jsdom@29.7.0: - resolution: {integrity: sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - jest-environment-node@29.7.0: resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -6234,14 +6097,6 @@ packages: resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-leak-detector@29.7.0: - resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-matcher-utils@29.7.0: - resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-message-util@29.7.0: resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -6250,39 +6105,10 @@ packages: resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-pnp-resolver@1.2.3: - resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} - engines: {node: '>=6'} - peerDependencies: - jest-resolve: '*' - peerDependenciesMeta: - jest-resolve: - optional: true - jest-regex-util@29.6.3: resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-resolve-dependencies@29.7.0: - resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-resolve@29.7.0: - resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-runner@29.7.0: - resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-runtime@29.7.0: - resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-snapshot@29.7.0: - resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-util@29.7.0: resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -6291,24 +6117,10 @@ packages: resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-watcher@29.7.0: - resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-worker@29.7.0: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest@29.7.0: - resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - jiti@2.4.1: resolution: {integrity: sha512-yPBThwecp1wS9DmoA4x4KR2h3QoslacnDR8ypuFM962kI4/456Iy1oHx2RAgh4jfZNdn0bctsdadceiBUgpU1g==} hasBin: true @@ -6456,10 +6268,6 @@ packages: klaw-sync@6.0.0: resolution: {integrity: sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==} - kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - kuler@2.0.0: resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} @@ -6596,9 +6404,6 @@ packages: lodash.isstring@4.0.1: resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} - lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -6629,6 +6434,9 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + loupe@3.1.3: + resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} + lowercase-keys@2.0.0: resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} engines: {node: '>=8'} @@ -6662,6 +6470,9 @@ packages: magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + magicast@0.3.5: + resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} + make-dir@2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} engines: {node: '>=6'} @@ -6670,9 +6481,6 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} - make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - make-fetch-happen@10.2.1: resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -6921,10 +6729,6 @@ packages: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} - min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} @@ -7455,6 +7259,13 @@ packages: pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + pe-library@0.4.1: resolution: {integrity: sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==} engines: {node: '>=12', npm: '>=6'} @@ -7507,10 +7318,6 @@ packages: resolution: {integrity: sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==} engines: {node: '>=6'} - pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - pkg-fetch@3.4.2: resolution: {integrity: sha512-0+uijmzYcnhC0hStDjm/cl2VYdrmVVBpe7Q8k9YBojxmR5tG8mvR9/nooQq3QSXiQqORDVOTY3XqMEqJVIzkHA==} hasBin: true @@ -7636,10 +7443,6 @@ packages: promise@8.3.0: resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==} - prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} @@ -7666,9 +7469,6 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - pure-rand@6.1.0: - resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} - qr-code-styling@1.8.4: resolution: {integrity: sha512-uxykNuvXaPDK/jGDERDIdDvvocefbHu1oxVYi6K87FUdPPAezkBdcIeFJ8XVX2HSsyLFINile5uzfOMYpGu5ZA==} engines: {node: '>=18.18.0'} @@ -7938,10 +7738,6 @@ packages: react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} - redis-errors@1.2.0: resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} engines: {node: '>=4'} @@ -8026,10 +7822,6 @@ packages: resolve-alpn@1.2.1: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} - resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} - resolve-from@3.0.0: resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==} engines: {node: '>=4'} @@ -8046,10 +7838,6 @@ packages: resolution: {integrity: sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A==} engines: {node: '>= 10.13.0'} - resolve.exports@2.0.3: - resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} - engines: {node: '>=10'} - resolve@1.22.8: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true @@ -8274,6 +8062,9 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -8297,9 +8088,6 @@ packages: resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} engines: {node: '>=10'} - sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - siwe@2.3.2: resolution: {integrity: sha512-aSf+6+Latyttbj5nMu6GF3doMfv2UYj83hhwZgUF20ky6fTS83uVhkQABdIVnEuS8y1bBdk7p6ltb9SmlhTTlA==} peerDependencies: @@ -8352,9 +8140,6 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map-support@0.5.13: - resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} - source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -8414,6 +8199,9 @@ packages: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + stackframe@1.3.4: resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} @@ -8470,10 +8258,6 @@ packages: resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} engines: {node: '>=4'} - string-length@4.0.2: - resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} - engines: {node: '>=10'} - string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -8522,10 +8306,6 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - strip-bom@4.0.0: - resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} - engines: {node: '>=8'} - strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} @@ -8534,10 +8314,6 @@ packages: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} - strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - strip-json-comments@2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} @@ -8636,6 +8412,10 @@ packages: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} + test-exclude@7.0.1: + resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} + engines: {node: '>=18'} + text-decoder@1.2.3: resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} @@ -8660,6 +8440,24 @@ packages: tiny-typed-emitter@2.1.0: resolution: {integrity: sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinypool@1.0.2: + resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + tmp-promise@3.0.3: resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==} @@ -8728,30 +8526,6 @@ packages: peerDependencies: typescript: '>=4.2.0' - ts-jest@29.2.5: - resolution: {integrity: sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==} - engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@babel/core': '>=7.0.0-beta.0 <8' - '@jest/transform': ^29.0.0 - '@jest/types': ^29.0.0 - babel-jest: ^29.0.0 - esbuild: '*' - jest: ^29.0.0 - typescript: '>=4.3 <6' - peerDependenciesMeta: - '@babel/core': - optional: true - '@jest/transform': - optional: true - '@jest/types': - optional: true - babel-jest: - optional: true - esbuild: - optional: true - ts-morph@13.0.3: resolution: {integrity: sha512-pSOfUMx8Ld/WUreoSzvMFQG5i9uEiWIsBYjpU9+TTASOeUa89j5HykomeqVULm1oqWtBdleI3KEFRLrlA3zGIw==} @@ -8793,10 +8567,6 @@ packages: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} - type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - type-fest@0.7.1: resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} engines: {node: '>=8'} @@ -9104,10 +8874,6 @@ packages: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true - v8-to-istanbul@9.3.0: - resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} - engines: {node: '>=10.12.0'} - valid-url@1.0.9: resolution: {integrity: sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==} @@ -9175,6 +8941,11 @@ packages: resolution: {integrity: sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g==} engines: {node: '>=10.13.0'} + vite-node@3.0.9: + resolution: {integrity: sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + vite-plugin-svgr@2.4.0: resolution: {integrity: sha512-q+mJJol6ThvqkkJvvVFEndI4EaKIjSI0I3jNFgSoC9fXAz1M7kYTVUin8fhUsFojFDKZ9VHKtX6NXNaOLpbsHA==} peerDependencies: @@ -9211,6 +8982,34 @@ packages: terser: optional: true + vitest@3.0.9: + resolution: {integrity: sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.0.9 + '@vitest/ui': 3.0.9 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vlq@1.0.1: resolution: {integrity: sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==} @@ -9322,6 +9121,11 @@ packages: engines: {node: ^16.13.0 || >=18.0.0} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + wide-align@1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} @@ -9535,8 +9339,6 @@ snapshots: graphql: 16.10.0 typescript: 5.3.3 - '@adobe/css-tools@4.4.1': {} - '@adraffy/ens-normalize@1.10.1': {} '@adraffy/ens-normalize@1.11.0': {} @@ -10418,7 +10220,7 @@ snapshots: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@bcoe/v8-coverage@0.2.3': {} + '@bcoe/v8-coverage@1.0.2': {} '@coinbase/wallet-sdk@3.9.3': dependencies: @@ -11260,152 +11062,39 @@ snapshots: '@istanbuljs/schema@0.1.3': {} - '@jest/console@29.7.0': + '@jest/create-cache-key-function@29.7.0': + dependencies: + '@jest/types': 29.6.3 + + '@jest/environment@29.7.0': + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.17.10 + jest-mock: 29.7.0 + + '@jest/fake-timers@29.7.0': dependencies: '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 '@types/node': 20.17.10 - chalk: 4.1.2 jest-message-util: 29.7.0 + jest-mock: 29.7.0 jest-util: 29.7.0 - slash: 3.0.0 - '@jest/core@29.7.0(babel-plugin-macros@3.1.0)': + '@jest/schemas@29.6.3': dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 + '@sinclair/typebox': 0.27.8 + + '@jest/transform@29.7.0': + dependencies: + '@babel/core': 7.26.0 '@jest/types': 29.6.3 - '@types/node': 20.17.10 - ansi-escapes: 4.3.2 + '@jridgewell/trace-mapping': 0.3.25 + babel-plugin-istanbul: 6.1.1 chalk: 4.1.2 - ci-info: 3.9.0 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.17.10)(babel-plugin-macros@3.1.0) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - - '@jest/create-cache-key-function@29.7.0': - dependencies: - '@jest/types': 29.6.3 - - '@jest/environment@29.7.0': - dependencies: - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.17.10 - jest-mock: 29.7.0 - - '@jest/expect-utils@29.7.0': - dependencies: - jest-get-type: 29.6.3 - - '@jest/expect@29.7.0': - dependencies: - expect: 29.7.0 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - - '@jest/fake-timers@29.7.0': - dependencies: - '@jest/types': 29.6.3 - '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.17.10 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 - - '@jest/globals@29.7.0': - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/types': 29.6.3 - jest-mock: 29.7.0 - transitivePeerDependencies: - - supports-color - - '@jest/reporters@29.7.0': - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.17.10 - chalk: 4.1.2 - collect-v8-coverage: 1.0.2 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.3 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.7 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - jest-worker: 29.7.0 - slash: 3.0.0 - string-length: 4.0.2 - strip-ansi: 6.0.1 - v8-to-istanbul: 9.3.0 - transitivePeerDependencies: - - supports-color - - '@jest/schemas@29.6.3': - dependencies: - '@sinclair/typebox': 0.27.8 - - '@jest/source-map@29.6.3': - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - callsites: 3.1.0 - graceful-fs: 4.2.11 - - '@jest/test-result@29.7.0': - dependencies: - '@jest/console': 29.7.0 - '@jest/types': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - collect-v8-coverage: 1.0.2 - - '@jest/test-sequencer@29.7.0': - dependencies: - '@jest/test-result': 29.7.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - slash: 3.0.0 - - '@jest/transform@29.7.0': - dependencies: - '@babel/core': 7.26.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - babel-plugin-istanbul: 6.1.1 - chalk: 4.1.2 - convert-source-map: 2.0.0 - fast-json-stable-stringify: 2.1.0 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 graceful-fs: 4.2.11 jest-haste-map: 29.7.0 jest-regex-util: 29.6.3 @@ -12810,16 +12499,6 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.6.3': - dependencies: - '@adobe/css-tools': 4.4.1 - aria-query: 5.3.2 - chalk: 3.0.0 - css.escape: 1.5.1 - dom-accessibility-api: 0.6.3 - lodash: 4.17.21 - redent: 3.0.0 - '@testing-library/react@14.3.1(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 @@ -12999,11 +12678,6 @@ snapshots: dependencies: '@types/istanbul-lib-report': 3.0.3 - '@types/jest@29.5.14': - dependencies: - expect: 29.7.0 - pretty-format: 29.7.0 - '@types/jsdom@20.0.1': dependencies: '@types/node': 20.17.10 @@ -13277,6 +12951,64 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitest/coverage-v8@3.0.9(vitest@3.0.9(@types/debug@4.1.12)(@types/node@20.17.10)(jsdom@20.0.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(sass@1.83.0)(terser@5.37.0))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@bcoe/v8-coverage': 1.0.2 + debug: 4.4.0 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.1.7 + magic-string: 0.30.17 + magicast: 0.3.5 + std-env: 3.8.0 + test-exclude: 7.0.1 + tinyrainbow: 2.0.0 + vitest: 3.0.9(@types/debug@4.1.12)(@types/node@20.17.10)(jsdom@20.0.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(sass@1.83.0)(terser@5.37.0) + transitivePeerDependencies: + - supports-color + + '@vitest/expect@3.0.9': + dependencies: + '@vitest/spy': 3.0.9 + '@vitest/utils': 3.0.9 + chai: 5.2.0 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.0.9(vite@5.4.11(@types/node@20.17.10)(sass@1.83.0)(terser@5.37.0))': + dependencies: + '@vitest/spy': 3.0.9 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 5.4.11(@types/node@20.17.10)(sass@1.83.0)(terser@5.37.0) + + '@vitest/pretty-format@3.0.9': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.0.9': + dependencies: + '@vitest/utils': 3.0.9 + pathe: 2.0.3 + + '@vitest/snapshot@3.0.9': + dependencies: + '@vitest/pretty-format': 3.0.9 + magic-string: 0.30.17 + pathe: 2.0.3 + + '@vitest/spy@3.0.9': + dependencies: + tinyspy: 3.0.2 + + '@vitest/utils@3.0.9': + dependencies: + '@vitest/pretty-format': 3.0.9 + loupe: 3.1.3 + tinyrainbow: 2.0.0 + '@wagmi/connectors@5.7.8(@types/react@18.3.17)(@wagmi/core@2.16.5(@tanstack/query-core@5.62.7)(@types/react@18.3.17)(react@18.3.1)(typescript@5.3.3)(use-sync-external-store@1.4.0(react@18.3.1))(viem@2.21.55(bufferutil@4.0.8)(typescript@5.3.3)(utf-8-validate@5.0.10)(zod@3.24.1)))(bufferutil@4.0.8)(encoding@0.1.13)(ioredis@5.4.1)(react@18.3.1)(typescript@5.3.3)(utf-8-validate@5.0.10)(viem@2.21.55(bufferutil@4.0.8)(typescript@5.3.3)(utf-8-validate@5.0.10)(zod@3.24.1))(zod@3.24.1)': dependencies: '@coinbase/wallet-sdk': 4.3.0 @@ -13960,10 +13692,6 @@ snapshots: anser@1.4.10: {} - ansi-escapes@4.3.2: - dependencies: - type-fest: 0.21.3 - ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} @@ -14123,8 +13851,6 @@ snapshots: dependencies: deep-equal: 2.2.3 - aria-query@5.3.2: {} - array-buffer-byte-length@1.0.1: dependencies: call-bind: 1.0.8 @@ -14198,6 +13924,8 @@ snapshots: assert-plus@1.0.0: optional: true + assertion-error@2.0.1: {} + ast-types@0.15.2: dependencies: tslib: 2.8.1 @@ -14496,10 +14224,6 @@ snapshots: node-releases: 2.0.19 update-browserslist-db: 1.1.1(browserslist@4.24.3) - bs-logger@0.2.6: - dependencies: - fast-json-stable-stringify: 2.1.0 - bs58@5.0.0: dependencies: base-x: 4.0.0 @@ -14690,18 +14414,19 @@ snapshots: ccount@2.0.1: {} - chalk@3.0.0: + chai@5.2.0: dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.3 + pathval: 2.0.0 chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - char-regex@1.0.2: {} - character-entities-html4@2.1.0: {} character-entities-legacy@3.0.0: {} @@ -14712,6 +14437,8 @@ snapshots: charenc@0.0.2: {} + check-error@2.1.1: {} + cheerio-select@2.1.0: dependencies: boolbase: 1.0.0 @@ -14785,8 +14512,6 @@ snapshots: dependencies: consola: 3.2.3 - cjs-module-lexer@1.4.1: {} - classic-level@1.4.1: dependencies: abstract-level: 1.0.4 @@ -14860,12 +14585,8 @@ snapshots: cmd-shim@6.0.3: {} - co@4.6.0: {} - code-block-writer@11.0.3: {} - collect-v8-coverage@1.0.2: {} - color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -15036,21 +14757,6 @@ snapshots: optionalDependencies: buffer: 6.0.3 - create-jest@29.7.0(@types/node@20.17.10)(babel-plugin-macros@3.1.0): - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.17.10)(babel-plugin-macros@3.1.0) - jest-util: 29.7.0 - prompts: 2.4.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - cron-parser@4.9.0: dependencies: luxon: 3.5.0 @@ -15100,8 +14806,6 @@ snapshots: css-what@6.1.0: {} - css.escape@1.5.1: {} - cssom@0.3.8: {} cssom@0.5.0: {} @@ -15228,9 +14932,7 @@ snapshots: dependencies: mimic-response: 3.1.0 - dedent@1.5.3(babel-plugin-macros@3.1.0): - optionalDependencies: - babel-plugin-macros: 3.1.0 + deep-eql@5.0.2: {} deep-equal@2.2.3: dependencies: @@ -15259,8 +14961,6 @@ snapshots: deepmerge@4.3.0: {} - deepmerge@4.3.1: {} - defaults@1.0.4: dependencies: clone: 1.0.4 @@ -15308,8 +15008,6 @@ snapshots: detect-libc@2.0.3: {} - detect-newline@3.1.0: {} - detect-node-es@1.1.0: {} detect-node@2.1.0: @@ -15325,8 +15023,6 @@ snapshots: wrappy: 1.0.2 optional: true - diff-sequences@29.6.3: {} - dijkstrajs@1.0.3: {} dir-compare@3.3.0: @@ -15399,8 +15095,6 @@ snapshots: dom-accessibility-api@0.5.16: {} - dom-accessibility-api@0.6.3: {} - dom-helpers@5.2.1: dependencies: '@babel/runtime': 7.26.0 @@ -15617,8 +15311,6 @@ snapshots: emitter-component@1.1.2: {} - emittery@0.13.1: {} - emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -15762,6 +15454,8 @@ snapshots: iterator.prototype: 1.1.4 safe-array-concat: 1.1.3 + es-module-lexer@1.6.0: {} + es-object-atoms@1.0.0: dependencies: es-errors: 1.3.0 @@ -15999,6 +15693,10 @@ snapshots: estree-walker@2.0.2: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.6 + esutils@2.0.3: {} etag@1.8.1: {} @@ -16088,17 +15786,9 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 - exit@0.1.2: {} - expand-template@2.0.3: {} - expect@29.7.0: - dependencies: - '@jest/expect-utils': 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 + expect-type@1.2.0: {} exponential-backoff@3.1.1: {} @@ -16890,11 +16580,6 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 - import-local@3.2.0: - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - imurmurhash@0.1.4: {} indent-string@4.0.0: {} @@ -17041,8 +16726,6 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-generator-fn@2.1.0: {} - is-generator-function@1.0.10: dependencies: has-tostringtag: 1.0.2 @@ -17177,27 +16860,17 @@ snapshots: transitivePeerDependencies: - supports-color - istanbul-lib-instrument@6.0.3: - dependencies: - '@babel/core': 7.26.0 - '@babel/parser': 7.26.3 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 7.6.3 - transitivePeerDependencies: - - supports-color - istanbul-lib-report@3.0.1: dependencies: istanbul-lib-coverage: 3.2.2 make-dir: 4.0.0 supports-color: 7.2.0 - istanbul-lib-source-maps@4.0.1: + istanbul-lib-source-maps@5.0.6: dependencies: + '@jridgewell/trace-mapping': 0.3.25 debug: 4.4.0 istanbul-lib-coverage: 3.2.2 - source-map: 0.6.1 transitivePeerDependencies: - supports-color @@ -17232,121 +16905,6 @@ snapshots: filelist: 1.0.4 minimatch: 3.1.2 - jest-changed-files@29.7.0: - dependencies: - execa: 5.1.1 - jest-util: 29.7.0 - p-limit: 3.1.0 - - jest-circus@29.7.0(babel-plugin-macros@3.1.0): - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.17.10 - chalk: 4.1.2 - co: 4.6.0 - dedent: 1.5.3(babel-plugin-macros@3.1.0) - is-generator-fn: 2.1.0 - jest-each: 29.7.0 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - p-limit: 3.1.0 - pretty-format: 29.7.0 - pure-rand: 6.1.0 - slash: 3.0.0 - stack-utils: 2.0.6 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-cli@29.7.0(@types/node@20.17.10)(babel-plugin-macros@3.1.0): - dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0) - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.17.10)(babel-plugin-macros@3.1.0) - exit: 0.1.2 - import-local: 3.2.0 - jest-config: 29.7.0(@types/node@20.17.10)(babel-plugin-macros@3.1.0) - jest-util: 29.7.0 - jest-validate: 29.7.0 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - jest-config@29.7.0(@types/node@20.17.10)(babel-plugin-macros@3.1.0): - dependencies: - '@babel/core': 7.26.0 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.26.0) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0(babel-plugin-macros@3.1.0) - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.8 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 20.17.10 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-diff@29.7.0: - dependencies: - chalk: 4.1.2 - diff-sequences: 29.6.3 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-docblock@29.7.0: - dependencies: - detect-newline: 3.1.0 - - jest-each@29.7.0: - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - jest-get-type: 29.6.3 - jest-util: 29.7.0 - pretty-format: 29.7.0 - - jest-environment-jsdom@29.7.0(bufferutil@4.0.8)(utf-8-validate@5.0.10): - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/jsdom': 20.0.1 - '@types/node': 20.17.10 - jest-mock: 29.7.0 - jest-util: 29.7.0 - jsdom: 20.0.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - jest-environment-node@29.7.0: dependencies: '@jest/environment': 29.7.0 @@ -17374,18 +16932,6 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - jest-leak-detector@29.7.0: - dependencies: - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-matcher-utils@29.7.0: - dependencies: - chalk: 4.1.2 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - jest-message-util@29.7.0: dependencies: '@babel/code-frame': 7.26.2 @@ -17404,109 +16950,8 @@ snapshots: '@types/node': 20.17.10 jest-util: 29.7.0 - jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): - optionalDependencies: - jest-resolve: 29.7.0 - jest-regex-util@29.6.3: {} - jest-resolve-dependencies@29.7.0: - dependencies: - jest-regex-util: 29.6.3 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - - jest-resolve@29.7.0: - dependencies: - chalk: 4.1.2 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) - jest-util: 29.7.0 - jest-validate: 29.7.0 - resolve: 1.22.9 - resolve.exports: 2.0.3 - slash: 3.0.0 - - jest-runner@29.7.0: - dependencies: - '@jest/console': 29.7.0 - '@jest/environment': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.17.10 - chalk: 4.1.2 - emittery: 0.13.1 - graceful-fs: 4.2.11 - jest-docblock: 29.7.0 - jest-environment-node: 29.7.0 - jest-haste-map: 29.7.0 - jest-leak-detector: 29.7.0 - jest-message-util: 29.7.0 - jest-resolve: 29.7.0 - jest-runtime: 29.7.0 - jest-util: 29.7.0 - jest-watcher: 29.7.0 - jest-worker: 29.7.0 - p-limit: 3.1.0 - source-map-support: 0.5.13 - transitivePeerDependencies: - - supports-color - - jest-runtime@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/globals': 29.7.0 - '@jest/source-map': 29.6.3 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.17.10 - chalk: 4.1.2 - cjs-module-lexer: 1.4.1 - collect-v8-coverage: 1.0.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - strip-bom: 4.0.0 - transitivePeerDependencies: - - supports-color - - jest-snapshot@29.7.0: - dependencies: - '@babel/core': 7.26.0 - '@babel/generator': 7.26.3 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.0) - '@babel/types': 7.26.3 - '@jest/expect-utils': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.0) - chalk: 4.1.2 - expect: 29.7.0 - graceful-fs: 4.2.11 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - natural-compare: 1.4.0 - pretty-format: 29.7.0 - semver: 7.6.3 - transitivePeerDependencies: - - supports-color - jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 @@ -17525,17 +16970,6 @@ snapshots: leven: 3.1.0 pretty-format: 29.7.0 - jest-watcher@29.7.0: - dependencies: - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.17.10 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - emittery: 0.13.1 - jest-util: 29.7.0 - string-length: 4.0.2 - jest-worker@29.7.0: dependencies: '@types/node': 20.17.10 @@ -17543,18 +16977,6 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.17.10)(babel-plugin-macros@3.1.0): - dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0) - '@jest/types': 29.6.3 - import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@20.17.10)(babel-plugin-macros@3.1.0) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - jiti@2.4.1: {} join-component@1.1.0: {} @@ -17747,8 +17169,6 @@ snapshots: dependencies: graceful-fs: 4.2.11 - kleur@3.0.3: {} - kuler@2.0.0: {} launchdarkly-electron-client-sdk@1.7.0: @@ -17913,8 +17333,6 @@ snapshots: lodash.isstring@4.0.1: {} - lodash.memoize@4.1.2: {} - lodash.merge@4.6.2: {} lodash.throttle@4.1.1: {} @@ -17945,6 +17363,8 @@ snapshots: dependencies: js-tokens: 4.0.0 + loupe@3.1.3: {} + lowercase-keys@2.0.0: {} lru-cache@10.4.3: {} @@ -17970,6 +17390,12 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 + magicast@0.3.5: + dependencies: + '@babel/parser': 7.26.3 + '@babel/types': 7.26.3 + source-map-js: 1.2.1 + make-dir@2.1.0: dependencies: pify: 4.0.1 @@ -17979,8 +17405,6 @@ snapshots: dependencies: semver: 7.6.3 - make-error@1.3.6: {} - make-fetch-happen@10.2.1: dependencies: agentkeepalive: 4.6.0 @@ -18489,8 +17913,6 @@ snapshots: mimic-response@3.1.0: {} - min-indent@1.0.1: {} - minimalistic-assert@1.0.1: {} minimalistic-crypto-utils@1.0.1: {} @@ -19062,6 +18484,10 @@ snapshots: pathe@1.1.2: {} + pathe@2.0.3: {} + + pathval@2.0.0: {} + pe-library@0.4.1: {} pend@1.2.0: {} @@ -19107,10 +18533,6 @@ snapshots: dependencies: find-up: 3.0.0 - pkg-dir@4.2.0: - dependencies: - find-up: 4.1.0 - pkg-fetch@3.4.2(encoding@0.1.13): dependencies: chalk: 4.1.2 @@ -19257,11 +18679,6 @@ snapshots: dependencies: asap: 2.0.6 - prompts@2.4.2: - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - prop-types@15.8.1: dependencies: loose-envify: 1.4.0 @@ -19290,8 +18707,6 @@ snapshots: punycode@2.3.1: {} - pure-rand@6.1.0: {} - qr-code-styling@1.8.4: dependencies: qrcode-generator: 1.4.4 @@ -19641,11 +19056,6 @@ snapshots: tiny-invariant: 1.3.3 victory-vendor: 36.9.2 - redent@3.0.0: - dependencies: - indent-string: 4.0.0 - strip-indent: 3.0.0 - redis-errors@1.2.0: optional: true @@ -19744,10 +19154,6 @@ snapshots: resolve-alpn@1.2.1: {} - resolve-cwd@3.0.0: - dependencies: - resolve-from: 5.0.0 - resolve-from@3.0.0: {} resolve-from@4.0.0: {} @@ -19758,8 +19164,6 @@ snapshots: dependencies: value-or-function: 4.0.0 - resolve.exports@2.0.3: {} - resolve@1.22.8: dependencies: is-core-module: 2.16.0 @@ -20044,6 +19448,8 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} + signal-exit@3.0.7: {} signal-exit@4.1.0: {} @@ -20066,8 +19472,6 @@ snapshots: dependencies: semver: 7.6.3 - sisteransi@1.0.5: {} - siwe@2.3.2(ethers@6.13.4(bufferutil@4.0.8)(utf-8-validate@5.0.10)): dependencies: '@spruceid/siwe-parser': 2.1.2 @@ -20138,11 +19542,6 @@ snapshots: source-map-js@1.2.1: {} - source-map-support@0.5.13: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 @@ -20192,6 +19591,8 @@ snapshots: dependencies: escape-string-regexp: 2.0.0 + stackback@0.0.2: {} + stackframe@1.3.4: {} stacktrace-parser@0.1.10: @@ -20249,11 +19650,6 @@ snapshots: strict-uri-encode@2.0.0: {} - string-length@4.0.2: - dependencies: - char-regex: 1.0.2 - strip-ansi: 6.0.1 - string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -20332,16 +19728,10 @@ snapshots: strip-bom@3.0.0: {} - strip-bom@4.0.0: {} - strip-final-newline@2.0.0: {} strip-final-newline@3.0.0: {} - strip-indent@3.0.0: - dependencies: - min-indent: 1.0.1 - strip-json-comments@2.0.1: {} strip-json-comments@3.1.1: {} @@ -20458,6 +19848,12 @@ snapshots: glob: 7.2.3 minimatch: 3.1.2 + test-exclude@7.0.1: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 10.4.5 + minimatch: 9.0.5 + text-decoder@1.2.3: dependencies: b4a: 1.6.7 @@ -20481,6 +19877,16 @@ snapshots: tiny-typed-emitter@2.1.0: {} + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + + tinypool@1.0.2: {} + + tinyrainbow@2.0.0: {} + + tinyspy@3.0.2: {} + tmp-promise@3.0.3: dependencies: tmp: 0.2.3 @@ -20539,25 +19945,6 @@ snapshots: dependencies: typescript: 5.3.3 - ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.10)(babel-plugin-macros@3.1.0))(typescript@5.3.3): - dependencies: - bs-logger: 0.2.6 - ejs: 3.1.10 - fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.17.10)(babel-plugin-macros@3.1.0) - jest-util: 29.7.0 - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.6.3 - typescript: 5.3.3 - yargs-parser: 21.1.1 - optionalDependencies: - '@babel/core': 7.26.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.26.0) - ts-morph@13.0.3: dependencies: '@ts-morph/common': 0.12.3 @@ -20602,8 +19989,6 @@ snapshots: type-fest@0.20.2: {} - type-fest@0.21.3: {} - type-fest@0.7.1: {} type-fest@2.19.0: {} @@ -20874,12 +20259,6 @@ snapshots: uuid@9.0.1: {} - v8-to-istanbul@9.3.0: - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - '@types/istanbul-lib-coverage': 2.0.6 - convert-source-map: 2.0.0 - valid-url@1.0.9: {} validate-npm-package-license@3.0.4: @@ -20992,6 +20371,24 @@ snapshots: replace-ext: 2.0.0 teex: 1.0.1 + vite-node@3.0.9(@types/node@20.17.10)(sass@1.83.0)(terser@5.37.0): + dependencies: + cac: 6.7.14 + debug: 4.4.0 + es-module-lexer: 1.6.0 + pathe: 2.0.3 + vite: 5.4.11(@types/node@20.17.10)(sass@1.83.0)(terser@5.37.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vite-plugin-svgr@2.4.0(rollup@4.28.1)(vite@5.4.11(@types/node@20.17.10)(sass@1.83.0)(terser@5.37.0)): dependencies: '@rollup/pluginutils': 5.1.4(rollup@4.28.1) @@ -21012,6 +20409,43 @@ snapshots: sass: 1.83.0 terser: 5.37.0 + vitest@3.0.9(@types/debug@4.1.12)(@types/node@20.17.10)(jsdom@20.0.3(bufferutil@4.0.8)(utf-8-validate@5.0.10))(sass@1.83.0)(terser@5.37.0): + dependencies: + '@vitest/expect': 3.0.9 + '@vitest/mocker': 3.0.9(vite@5.4.11(@types/node@20.17.10)(sass@1.83.0)(terser@5.37.0)) + '@vitest/pretty-format': 3.0.9 + '@vitest/runner': 3.0.9 + '@vitest/snapshot': 3.0.9 + '@vitest/spy': 3.0.9 + '@vitest/utils': 3.0.9 + chai: 5.2.0 + debug: 4.4.0 + expect-type: 1.2.0 + magic-string: 0.30.17 + pathe: 2.0.3 + std-env: 3.8.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: 5.4.11(@types/node@20.17.10)(sass@1.83.0)(terser@5.37.0) + vite-node: 3.0.9(@types/node@20.17.10)(sass@1.83.0)(terser@5.37.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/debug': 4.1.12 + '@types/node': 20.17.10 + jsdom: 20.0.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vlq@1.0.1: {} void-elements@3.1.0: {} @@ -21165,6 +20599,11 @@ snapshots: dependencies: isexe: 3.1.1 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + wide-align@1.1.5: dependencies: string-width: 4.2.3 diff --git a/src/backend/__mocks__/electron-store.ts b/src/backend/__mocks__/electron-store.ts deleted file mode 100644 index e9db99338a..0000000000 --- a/src/backend/__mocks__/electron-store.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { StoreOptions } from './../../common/types/electron_store' -import tmp from 'tmp' -import { join } from 'path' - -const OriginalStore = jest.requireActual('electron-store') -const tmpStoreRootDirectory = tmp.dirSync({ unsafeCleanup: true }) - -export default class Store< - T extends Record = Record -> extends OriginalStore { - constructor(options?: StoreOptions) { - if (options) { - if (options.cwd) { - options.cwd = join(tmpStoreRootDirectory.name, options.cwd) - } else { - options.cwd = tmpStoreRootDirectory.name - } - } else { - options = { - cwd: tmpStoreRootDirectory.name - } - } - super(options) - } -} diff --git a/src/backend/__mocks__/electron.ts b/src/backend/__mocks__/electron.ts index b65383e5f5..5822aa73c6 100644 --- a/src/backend/__mocks__/electron.ts +++ b/src/backend/__mocks__/electron.ts @@ -6,26 +6,27 @@ import { } from 'electron' import { tmpdir } from 'os' import { join } from 'path' +import { vi } from 'vitest' -const fs = jest.createMockFromModule('fs') +const fs = vi.createMockFromModule('fs') const appBasePath = tmpdir() const dialog = { // dialog override - showErrorBox: jest.fn(), - showMessageBox: jest.fn() + showErrorBox: vi.fn(), + showMessageBox: vi.fn() } class App extends EventEmitter { // app override - getPath = jest.fn().mockImplementation((path: string) => { + getPath = vi.fn().mockImplementation((path: string) => { return join(appBasePath, path) }) getVersion(): string { return '1.0.0' } - requestSingleInstanceLock = jest.fn().mockReturnValue(true) + requestSingleInstanceLock = vi.fn().mockReturnValue(true) } const app = new App() @@ -157,11 +158,11 @@ class Tray { } const ipcMain = { - on: jest.fn().mockReturnThis(), - handle: jest.fn().mockReturnThis(), - once: jest.fn().mockReturnThis(), - emit: jest.fn().mockReturnThis(), - prependListener: jest.fn().mockReturnThis() + on: vi.fn().mockReturnThis(), + handle: vi.fn().mockReturnThis(), + once: vi.fn().mockReturnThis(), + emit: vi.fn().mockReturnThis(), + prependListener: vi.fn().mockReturnThis() } export { diff --git a/src/backend/__tests__/cache.test.ts b/src/backend/__tests__/cache.test.ts index 5d2d7ceb91..b0bd3cbd62 100644 --- a/src/backend/__tests__/cache.test.ts +++ b/src/backend/__tests__/cache.test.ts @@ -1,7 +1,8 @@ +import { vi, test, describe, expect, afterEach, afterAll } from 'vitest' + import Store from 'electron-store' -import CacheStore from '../cache' -jest.mock('electron-store') +import CacheStore from '../cache' describe('backend/cache.ts', () => { const testStore = new CacheStore('test_store') @@ -11,10 +12,10 @@ describe('backend/cache.ts', () => { }) const now = new Date() - jest.useFakeTimers().setSystemTime(now) + vi.useFakeTimers().setSystemTime(now) - afterEach(testStore.clear) - afterAll(jest.useRealTimers) + afterEach(() => testStore.clear()) + afterAll(vi.useRealTimers) test('Value is written', () => { testStore.set('foo', 'bar') @@ -33,9 +34,9 @@ describe('backend/cache.ts', () => { test('Invalid value is cleared', () => { const eight_hours_ago = new Date(now).setHours(now.getHours() - 8) - jest.setSystemTime(eight_hours_ago) + vi.setSystemTime(eight_hours_ago) testStore.set('foo', 'bar') - jest.setSystemTime(now) + vi.setSystemTime(now) expect(testStore.get('foo')).toBe(undefined) expect(internalStore.has('foo')).toBe(false) expect(internalStore.has('__timestamp.foo')).toBe(false) @@ -44,18 +45,18 @@ describe('backend/cache.ts', () => { test('Custom lifetime works', () => { const testStore2 = new CacheStore('test_store_2', 60) const three_hours_ago = new Date(now).setHours(now.getHours() - 3) - jest.setSystemTime(three_hours_ago) + vi.setSystemTime(three_hours_ago) testStore2.set('foo', 'bar') - jest.setSystemTime(now) + vi.setSystemTime(now) expect(testStore2.get('foo')).toBe(undefined) }) test('Allows having no expiration time', () => { const testStore2 = new CacheStore('test_store_2', null) const three_hours_ago = new Date(now).setHours(now.getHours() - 3) - jest.setSystemTime(three_hours_ago) + vi.setSystemTime(three_hours_ago) testStore2.set('foo', 'bar') - jest.setSystemTime(now) + vi.setSystemTime(now) expect(testStore2.get('foo')).toBe('bar') }) }) diff --git a/src/backend/__tests__/constants.test.ts b/src/backend/__tests__/constants.test.ts index 4d9a2aae82..171dc0becb 100644 --- a/src/backend/__tests__/constants.test.ts +++ b/src/backend/__tests__/constants.test.ts @@ -1,10 +1,11 @@ import { fixAsarPath } from '../constants' +import { vi, describe, expect, test } from 'vitest' -jest.mock('../logger/logfile') -jest.mock('backend/vite_constants', () => ({ +vi.mock('../logger/logfile') +vi.mock('backend/vite_constants', () => ({ VITE_IPFS_API: 'https://ipfs.io/ipfs/' })) -jest.mock('backend/flags/flags', () => ({ +vi.mock('backend/flags/flags', () => ({ VITE_LD_ENVIRONMENT_ID: '123' })) @@ -33,7 +34,7 @@ describe('Constants - getShell', () => { } async function getShell(): Promise { - jest.resetModules() + vi.resetModules() return import('../constants').then((module) => { return module.execOptions.shell }) diff --git a/src/backend/__tests__/main_window.test.ts b/src/backend/__tests__/main_window.test.ts index 2c6d4a320d..9f9425e2b4 100644 --- a/src/backend/__tests__/main_window.test.ts +++ b/src/backend/__tests__/main_window.test.ts @@ -1,12 +1,21 @@ import { createMainWindow, sendFrontendMessage } from '../main_window' import { BrowserWindow, Display, screen } from 'electron' import { configStore } from '../constants' - -jest.mock('../logger/logfile') -jest.mock('backend/vite_constants', () => ({ +import { + vi, + describe, + expect, + beforeEach, + it, + beforeAll, + afterAll +} from 'vitest' + +vi.mock('../logger/logfile') +vi.mock('backend/vite_constants', () => ({ VITE_IPFS_API: 'https://ipfs.io/ipfs/' })) -jest.mock('backend/flags/flags', () => ({ +vi.mock('backend/flags/flags', () => ({ VITE_LD_ENVIRONMENT_ID: '123' })) @@ -25,7 +34,7 @@ describe('main_window', () => { describe('if there is a main window', () => { const window = { webContents: { - send: jest.fn() + send: vi.fn() } } @@ -36,7 +45,7 @@ describe('main_window', () => { // spy the `send` method beforeEach(() => { - window.webContents.send = jest.fn() + window.webContents.send = vi.fn() }) // cleanup stubs @@ -59,8 +68,8 @@ describe('main_window', () => { describe('createMainWindow', () => { describe('with stored window geometry', () => { beforeEach(() => { - jest.spyOn(configStore, 'has').mockReturnValue(true) - jest.spyOn(configStore, 'get').mockReturnValue({ + vi.spyOn(configStore, 'has').mockReturnValue(true) + vi.spyOn(configStore, 'get').mockReturnValue({ width: 800, height: 600, x: 0, @@ -83,7 +92,7 @@ describe('main_window', () => { describe('without stored window geometry', () => { beforeAll(() => { - jest.spyOn(configStore, 'has').mockReturnValue(false) + vi.spyOn(configStore, 'has').mockReturnValue(false) }) it('creates the new window with the default geometry', async () => { @@ -98,7 +107,7 @@ describe('main_window', () => { it('ensures windows is not bigger than the screen', async () => { // mock a smaller screen info - jest.spyOn(screen, 'getPrimaryDisplay').mockReturnValue({ + vi.spyOn(screen, 'getPrimaryDisplay').mockReturnValue({ workAreaSize: { height: 768, width: 1024 diff --git a/src/backend/__tests__/utils.test.ts b/src/backend/__tests__/utils.test.ts index d5ccc886e1..513f74021f 100644 --- a/src/backend/__tests__/utils.test.ts +++ b/src/backend/__tests__/utils.test.ts @@ -6,15 +6,16 @@ import { existsSync } from 'fs' import { rimraf } from 'rimraf' import os from 'os' import * as fs from 'fs' +import { vi, test, describe, expect, it, beforeEach, afterEach } from 'vitest' -jest.mock('electron') -jest.mock('../logger/logger') -jest.mock('../logger/logfile') -jest.mock('../dialog/dialog') -jest.mock('backend/vite_constants', () => ({ +vi.mock('electron') +vi.mock('../logger/logger') +vi.mock('../logger/logfile') +vi.mock('../dialog/dialog') +vi.mock('backend/vite_constants', () => ({ VITE_IPFS_API: 'https://ipfs.io/ipfs/' })) -jest.mock('backend/flags/flags', () => ({ +vi.mock('backend/flags/flags', () => ({ VITE_LD_ENVIRONMENT_ID: '123' })) @@ -319,14 +320,14 @@ describe('backend/utils.ts', () => { const destDir = join(testDir, 'dest') beforeEach(async () => { - jest.useFakeTimers({ advanceTimers: true }) + vi.useFakeTimers({ shouldAdvanceTime: true }) await mkdir(sourceDir, { recursive: true }) await mkdir(destDir, { recursive: true }) }) afterEach(async () => { - jest.clearAllTimers() // Clear pending timers - jest.useRealTimers() // Restore real timers + vi.clearAllTimers() // Clear pending timers + vi.useRealTimers() // Restore real timers await rimraf(testDir) }) @@ -368,7 +369,7 @@ describe('backend/utils.ts', () => { await writeFile(testFile, 'test content') // Mock the copyFile function to simulate a slow operation - const mockCopyFile = jest + const mockCopyFile = vi .spyOn(fs.promises, 'copyFile') .mockImplementation(async () => { return new Promise((resolve) => { @@ -382,7 +383,7 @@ describe('backend/utils.ts', () => { const copyPromise = copyRecursiveAsync(testFile, destFile) // Advance timers to trigger timeout - jest.advanceTimersByTime(COPY_TIMEOUT_MS + 100) + vi.advanceTimersByTime(COPY_TIMEOUT_MS + 100) // Now check if it throws await expect(copyPromise).rejects.toThrow('Timeout') diff --git a/src/backend/jest.config.js b/src/backend/jest.config.js deleted file mode 100644 index 9861d7c219..0000000000 --- a/src/backend/jest.config.js +++ /dev/null @@ -1,27 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/no-var-requires -const { compilerOptions } = require('../../tsconfig') - -module.exports = { - displayName: 'Backend', - - moduleDirectories: ['node_modules', ''], - // Module file extensions for importing - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'], - testPathIgnorePatterns: ['./node_modules/'], - resetMocks: true, - - rootDir: '../..', - - // The root of your source code, typically /src - // `` is a token Jest substitutes - roots: ['/src/backend'], - - testMatch: ['**/__tests__/**/*.test.ts'], - // Jest transformations -- this adds support for TypeScript - // using ts-jest - transform: { - '^.+\\.tsx?$': 'ts-jest' - }, - - modulePaths: [compilerOptions.baseUrl] -} diff --git a/src/backend/logger/__mocks__/logger.ts b/src/backend/logger/__mocks__/logger.ts index c981528836..b6c86794cf 100644 --- a/src/backend/logger/__mocks__/logger.ts +++ b/src/backend/logger/__mocks__/logger.ts @@ -1,9 +1,11 @@ -const logger = jest.requireActual('../logger') +import { vi } from 'vitest' -logger.logError = jest.fn() -logger.logInfo = jest.fn() -logger.logDebug = jest.fn() -logger.logWarning = jest.fn() +const logger = vi.requireActual('../logger') + +logger.logError = vi.fn() +logger.logInfo = vi.fn() +logger.logDebug = vi.fn() +logger.logWarning = vi.fn() module.exports = logger export {} diff --git a/src/backend/logger/__tests__/logfile.test.ts b/src/backend/logger/__tests__/logfile.test.ts index 392fd34c02..56a2724bbe 100644 --- a/src/backend/logger/__tests__/logfile.test.ts +++ b/src/backend/logger/__tests__/logfile.test.ts @@ -6,16 +6,17 @@ import { configStore } from '../../constants' import * as logfile from '../logfile' import { logError } from '../logger' import { platform } from 'os' - -jest.mock('electron') -jest.mock('electron-store') -jest.mock('../../constants') -jest.mock('../logger') -jest.unmock('../logfile') -jest.mock('backend/vite_constants', () => ({ +import { vi, test, describe, expect, beforeEach, it, afterEach } from 'vitest' + +vi.mock('electron') +vi.mock('electron-store') +vi.mock('../../constants') +vi.mock('../logger') +vi.unmock('../logfile') +vi.mock('backend/vite_constants', () => ({ VITE_IPFS_API: 'https://ipfs.io/ipfs/' })) -jest.mock('backend/flags/flags', () => ({ +vi.mock('backend/flags/flags', () => ({ VITE_LD_ENVIRONMENT_ID: '123' })) let tmpDir = {} as DirResult @@ -37,13 +38,13 @@ describe('logger/logfile.ts', () => { }) afterEach(() => { - jest.restoreAllMocks() + vi.restoreAllMocks() tmpDir.removeCallback() }) test('createNewLogFileAndClearOldOnes fails because logDir does not exist', () => { - const spyAppGetPath = jest.spyOn(app, 'getPath').mockReturnValue('invalid') - const spyOpenSync = jest.spyOn(graceful_fs, 'openSync') + const spyAppGetPath = vi.spyOn(app, 'getPath').mockReturnValue('invalid') + const spyOpenSync = vi.spyOn(graceful_fs, 'openSync') logfile.createNewLogFileAndClearOldOnes() @@ -64,7 +65,7 @@ describe('logger/logfile.ts', () => { }) test('createNewLogFileAndClearOldOnes success', () => { - jest.spyOn(app, 'getPath').mockReturnValue(tmpDir.name) + vi.spyOn(app, 'getPath').mockReturnValue(tmpDir.name) configStore.set('general-logs', { currentLogFile: 'old/log/path/file.log', @@ -73,7 +74,7 @@ describe('logger/logfile.ts', () => { gogdlLogFile: '' }) - jest.spyOn(app, 'requestSingleInstanceLock').mockImplementation(() => true) + vi.spyOn(app, 'requestSingleInstanceLock').mockImplementation(() => true) const data = logfile.createNewLogFileAndClearOldOnes() expect(logError).not.toBeCalled() @@ -94,7 +95,7 @@ describe('logger/logfile.ts', () => { }) test('appendMessageToLogFile success', () => { - const appendFileSyncSpy = jest + const appendFileSyncSpy = vi .spyOn(graceful_fs, 'appendFileSync') .mockReturnValue() @@ -103,23 +104,17 @@ describe('logger/logfile.ts', () => { }) test('appendMessageToLogFile logfile undefined', () => { - const appendFileSyncSpy = jest + const appendFileSyncSpy = vi .spyOn(graceful_fs, 'appendFileSync') .mockReturnValue() - const mockConstants = jest.requireMock('../../constants') - const defaultCurrentLogName = mockConstants.currentLogFile - mockConstants.currentLogFile = '' - logfile.appendMessageToLogFile('Hello World') - mockConstants.currentLogFile = defaultCurrentLogName - expect(appendFileSyncSpy).not.toBeCalled() }) test('appendMessageToLogFile fails', () => { - jest.spyOn(graceful_fs, 'appendFileSync').mockImplementation(() => { + vi.spyOn(graceful_fs, 'appendFileSync').mockImplementation(() => { throw Error('append failed') }) diff --git a/src/backend/logger/__tests__/logger.test.ts b/src/backend/logger/__tests__/logger.test.ts index 2b045e56a8..b87dbade48 100644 --- a/src/backend/logger/__tests__/logger.test.ts +++ b/src/backend/logger/__tests__/logger.test.ts @@ -2,13 +2,14 @@ import * as logger from '../logger' import { appendMessageToLogFile } from '../logfile' import { showDialogBoxModalAuto } from '../../dialog/dialog' import { platform } from 'os' +import { vi, test, describe, expect, it, afterEach } from 'vitest' -jest.mock('../logfile') -jest.mock('../../dialog/dialog') -jest.mock('backend/vite_constants', () => ({ +vi.mock('../logfile') +vi.mock('../../dialog/dialog') +vi.mock('backend/vite_constants', () => ({ VITE_IPFS_API: 'https://ipfs.io/ipfs/' })) -jest.mock('backend/flags/flags', () => ({ +vi.mock('backend/flags/flags', () => ({ VITE_LD_ENVIRONMENT_ID: '123' })) @@ -58,20 +59,22 @@ describe('logger/logger.ts', () => { emptyTest return } - afterEach(jest.restoreAllMocks) + afterEach(vi.restoreAllMocks) test('log invokes console', () => { - const spyConsoleError = jest + const spyConsoleError = vi .spyOn(global.console, 'error') - .mockImplementation() - const spyConsoleLog = jest.spyOn(global.console, 'log').mockImplementation() - const spyConsoleWarn = jest + .mockImplementation(() => undefined) + const spyConsoleLog = vi + .spyOn(global.console, 'log') + .mockImplementation(() => undefined) + const spyConsoleWarn = vi .spyOn(global.console, 'warn') - .mockImplementation() + .mockImplementation(() => undefined) interface TestCaseProps { function: logger.LogFunction - spyConsole: jest.SpyInstance + spyConsole: typeof spyConsoleError } const testCases = new Map([ @@ -99,9 +102,9 @@ describe('logger/logger.ts', () => { }) test('log appends to log file', () => { - jest.spyOn(global.console, 'error').mockImplementation() - jest.spyOn(global.console, 'log').mockImplementation() - jest.spyOn(global.console, 'warn').mockImplementation() + vi.spyOn(global.console, 'error').mockImplementation(() => undefined) + vi.spyOn(global.console, 'log').mockImplementation(() => undefined) + vi.spyOn(global.console, 'warn').mockImplementation(() => undefined) const testCases = new Map([ ['ERROR', logger.logError], @@ -120,9 +123,9 @@ describe('logger/logger.ts', () => { }) test('log can be shown as dialog', () => { - jest.spyOn(global.console, 'error').mockImplementation() - jest.spyOn(global.console, 'log').mockImplementation() - jest.spyOn(global.console, 'warn').mockImplementation() + vi.spyOn(global.console, 'error').mockImplementation(() => undefined) + vi.spyOn(global.console, 'log').mockImplementation(() => undefined) + vi.spyOn(global.console, 'warn').mockImplementation(() => undefined) const testCases = new Map([ ['ERROR', logger.logError], @@ -147,7 +150,9 @@ describe('logger/logger.ts', () => { }) test('log undefined variable works', () => { - const spyConsoleLog = jest.spyOn(global.console, 'log').mockImplementation() + const spyConsoleLog = vi + .spyOn(global.console, 'log') + .mockImplementation(() => undefined) logger.logInfo(undefined, logger.LogPrefix.Backend) diff --git a/src/backend/services/__tests__/ExtractZipService.test.ts b/src/backend/services/__tests__/ExtractZipService.test.ts index 85b78359ac..674b633983 100644 --- a/src/backend/services/__tests__/ExtractZipService.test.ts +++ b/src/backend/services/__tests__/ExtractZipService.test.ts @@ -3,6 +3,7 @@ import yauzl from 'yauzl' import { resolve } from 'path' import { mkdirSync } from 'graceful-fs' import { ExtractZipService } from '../ExtractZipService' +import { vi, beforeEach, describe, expect, it, afterEach } from 'vitest' const returnDataMockup = { progressPercentage: 0, @@ -10,19 +11,19 @@ const returnDataMockup = { totalSizeInBytes: 1000, processedSizeInBytes: 500 } -jest.mock('yauzl', () => ({ - open: jest.fn() +vi.mock('yauzl', () => ({ + open: vi.fn() })) -jest.mock('@sentry/electron', () => ({ - captureException: jest.fn() +vi.mock('@sentry/electron', () => ({ + captureException: vi.fn() })) -jest.mock('graceful-fs', () => ({ - ...jest.requireActual('graceful-fs'), - mkdirSync: jest.fn(), +vi.mock('graceful-fs', () => ({ + ...vi.requireActual('graceful-fs'), + mkdirSync: vi.fn(), createWriteStream: () => ({ - pipe: jest.fn((writeStream) => writeStream), - once: jest.fn(), - on: jest.fn((event, streamCallback) => { + pipe: vi.fn((writeStream) => writeStream), + once: vi.fn(), + on: vi.fn((event, streamCallback) => { if (event === 'close') { streamCallback() } else if (event === 'data') { @@ -34,9 +35,9 @@ jest.mock('graceful-fs', () => ({ } }) }), - rm: jest.fn(), - rmSync: jest.fn(), - copyFileSync: jest.fn() + rm: vi.fn(), + rmSync: vi.fn(), + copyFileSync: vi.fn() })) const yauzlMockupLib = ( fileName = 'test.zip', @@ -48,14 +49,14 @@ const yauzlMockupLib = ( const stream = { _read: () => null, destroyed: false, - pipe: jest.fn((args) => args), - unpipe: jest.fn(), - destroy: jest.fn(() => { + pipe: vi.fn((args) => args), + unpipe: vi.fn(), + destroy: vi.fn(() => { stream.destroyed = true }), - resume: jest.fn(), - pause: jest.fn(), - on: jest.fn( + resume: vi.fn(), + pause: vi.fn(), + on: vi.fn( ( event: string, streamCallback: (...args: unknown[]) => ReadableStream @@ -81,17 +82,17 @@ const yauzlMockupLib = ( const mockZipFile = { fileSize, - readEntry: jest.fn(), - close: jest.fn(), + readEntry: vi.fn(), + close: vi.fn(), isOpen: true, - once: jest.fn((event, streamCallback) => { + once: vi.fn((event, streamCallback) => { if (event === 'end') { streamCallback() } else if (event === 'error') { streamCallback() } }), - on: jest.fn((event, entryCallback) => { + on: vi.fn((event, entryCallback) => { if (event === 'entry') { entryCallback({ fileName, @@ -100,12 +101,12 @@ const yauzlMockupLib = ( }) } }), - openReadStream: jest.fn((entry, openReadStreamCallback) => { + openReadStream: vi.fn((entry, openReadStreamCallback) => { openReadStreamCallback(error, stream) }) } - ;(yauzl.open as jest.Mock).mockImplementation( + ;(yauzl.open as vi.Mock).mockImplementation( (_path, _options, yauzlOpenCallback) => { yauzlOpenCallback(error, mockZipFile) } @@ -134,14 +135,14 @@ describe('ExtractZipService', () => { beforeEach(() => { yauzlMockupLib('test.zip', false) - jest.useFakeTimers() + vi.useFakeTimers() extractZipService = new ExtractZipService(zipFile, destinationPath) extractZipService.getUncompressedSize = async () => Promise.resolve(15000) }, 1000) afterEach(() => { - jest.clearAllMocks() - jest.useRealTimers() + vi.clearAllMocks() + vi.useRealTimers() }) it('should have `source` and `destination` always available', () => { @@ -153,7 +154,7 @@ describe('ExtractZipService', () => { it('should emit progress events', async () => { const { makeFakeProgress } = yauzlMockupLib('test.zip') - const progressListener = jest.fn() + const progressListener = vi.fn() extractZipService.on('progress', progressListener) extractZipService.extract() @@ -166,7 +167,7 @@ describe('ExtractZipService', () => { }) it('should emit end event on successful extraction', async () => { - const endListener = jest.fn() + const endListener = vi.fn() extractZipService.on('finished', endListener) await extractZipService.extract() @@ -177,7 +178,7 @@ describe('ExtractZipService', () => { it('should emit error event on extraction failure', async () => { yauzlMockupLib('test.zip', true) const error = 'Mock example' - const mockEventListener = jest.fn() + const mockEventListener = vi.fn() extractZipService.on('error', mockEventListener) process.nextTick(async () => { @@ -190,9 +191,9 @@ describe('ExtractZipService', () => { it('should cancel extraction when cancel is called', async () => { const { makeFakeProgress } = yauzlMockupLib('test.zip') - const endListener = jest.fn() - const progressListener = jest.fn() - const onCanceledListener = jest.fn() + const endListener = vi.fn() + const progressListener = vi.fn() + const onCanceledListener = vi.fn() extractZipService.on('finished', endListener) extractZipService.on('progress', progressListener) extractZipService.on('canceled', onCanceledListener) @@ -233,7 +234,7 @@ describe('ExtractZipService', () => { it('should handle directory entry', async () => { yauzlMockupLib('directory/test.zip', false) - const endListener = jest.fn() + const endListener = vi.fn() extractZipService.on('finished', endListener) await extractZipService.extract() @@ -248,7 +249,7 @@ describe('ExtractZipService', () => { it('should emit correct progress values', async () => { const { makeFakeProgress } = yauzlMockupLib('test.zip') - const progressListener = jest.fn(() => returnDataMockup) + const progressListener = vi.fn(() => returnDataMockup) extractZipService.on('progress', progressListener) extractZipService.extract() @@ -268,7 +269,7 @@ describe('ExtractZipService', () => { }) it('should emit correct end values', async () => { - const endListener = jest.fn(() => returnDataMockup) + const endListener = vi.fn(() => returnDataMockup) extractZipService.on('finished', endListener) await extractZipService.extract() @@ -288,7 +289,7 @@ describe('ExtractZipService', () => { it('should emit correct pause values', async () => { const { makeFakeProgress } = yauzlMockupLib('test.zip') - const pausedListener = jest.fn(() => returnDataMockup) + const pausedListener = vi.fn(() => returnDataMockup) extractZipService.on('paused', pausedListener) extractZipService.extract() @@ -311,7 +312,7 @@ describe('ExtractZipService', () => { it('should emit correct resume values', async () => { const { makeFakeProgress } = yauzlMockupLib('test.zip') - const resumedListener = jest.fn(() => returnDataMockup) + const resumedListener = vi.fn(() => returnDataMockup) extractZipService.on('resumed', resumedListener) extractZipService.extract() @@ -334,7 +335,7 @@ describe('ExtractZipService', () => { it('should not continue the progress upon paused', async () => { const { makeFakeProgress } = yauzlMockupLib('test.zip') - const progressListener = jest.fn() + const progressListener = vi.fn() extractZipService.on('progress', progressListener) extractZipService.extract() @@ -348,7 +349,7 @@ describe('ExtractZipService', () => { it('should continue the progress after resumed', async () => { const { makeFakeProgress } = yauzlMockupLib('test.zip') - const progressListener = jest.fn() + const progressListener = vi.fn() extractZipService.on('progress', progressListener) extractZipService.extract() @@ -366,8 +367,8 @@ describe('ExtractZipService', () => { it('should extract files successfully', async () => { const { makeFakeProgress } = yauzlMockupLib('test.zip') - const onProgress = jest.fn() - const onEnd = jest.fn() + const onProgress = vi.fn() + const onEnd = vi.fn() extractZipService.on('progress', onProgress) extractZipService.on('finished', onEnd) @@ -385,7 +386,7 @@ describe('ExtractZipService', () => { it('should throttle emit progress', async () => { const { makeFakeProgress } = yauzlMockupLib('test.zip') - const mockEventListener = jest.fn() + const mockEventListener = vi.fn() extractZipService.on('progress', mockEventListener) extractZipService.extract() @@ -398,7 +399,7 @@ describe('ExtractZipService', () => { }) it('should clear all event listeners after finished, canceled or error', () => { - const removeAllListenersSpy = jest.spyOn( + const removeAllListenersSpy = vi.spyOn( extractZipService, 'removeAllListeners' ) @@ -413,7 +414,7 @@ describe('ExtractZipService', () => { it('Should fail validation if the zip file does not exist for extracting', async () => { const error = 'Zip file not found' const service = new ExtractZipService('noneexisting.zip', destinationPath) - const mockEventListener = jest.fn() + const mockEventListener = vi.fn() service.on('error', mockEventListener) process.nextTick(async () => { @@ -429,7 +430,7 @@ describe('ExtractZipService', () => { '谷���新道ひばりヶ�.zip', destinationPath ) - const mockEventListener = jest.fn() + const mockEventListener = vi.fn() service.on('error', mockEventListener) process.nextTick(async () => { diff --git a/src/backend/shortcuts/nonesteamgame/__tests__/nonesteamgame.test.ts b/src/backend/shortcuts/nonesteamgame/__tests__/nonesteamgame.test.ts index d9071c2112..3e7d007d04 100644 --- a/src/backend/shortcuts/nonesteamgame/__tests__/nonesteamgame.test.ts +++ b/src/backend/shortcuts/nonesteamgame/__tests__/nonesteamgame.test.ts @@ -4,14 +4,15 @@ import { join } from 'path' import { DirResult, dirSync } from 'tmp' import { addNonSteamGame, removeNonSteamGame } from '../nonesteamgame' import { showDialogBoxModalAuto } from 'backend/dialog/dialog' +import { vi, beforeEach, describe, expect, test, afterEach } from 'vitest' -jest.mock('backend/logger/logfile') -jest.mock('backend/dialog/dialog') -jest.mock('backend/utils') -jest.mock('backend/vite_constants', () => ({ +vi.mock('backend/logger/logfile') +vi.mock('backend/dialog/dialog') +vi.mock('backend/utils') +vi.mock('backend/vite_constants', () => ({ VITE_IPFS_API: 'https://ipfs.io/ipfs/' })) -jest.mock('backend/flags/flags', () => ({ +vi.mock('backend/flags/flags', () => ({ VITE_LD_ENVIRONMENT_ID: '123' })) @@ -31,9 +32,9 @@ describe('NonSteamGame', () => { tmpDir = dirSync({ unsafeCleanup: true }) tmpSteamUserConfigDir = join(tmpDir.name, 'steam_user', 'config') mkdirSync(tmpSteamUserConfigDir, { recursive: true }) - console.log = jest.fn() - console.error = jest.fn() - console.warn = jest.fn() + console.log = vi.fn() + console.error = vi.fn() + console.warn = vi.fn() }) afterEach(() => { diff --git a/src/backend/storeManagers/hyperplay/__tests__/utils.test.ts b/src/backend/storeManagers/hyperplay/__tests__/utils.test.ts index 1dca5631c7..bfb894b619 100644 --- a/src/backend/storeManagers/hyperplay/__tests__/utils.test.ts +++ b/src/backend/storeManagers/hyperplay/__tests__/utils.test.ts @@ -1,12 +1,13 @@ import * as HpStoreUtils from '../utils' import { GameInfo, HyperPlayRelease } from '../../../../common/types' -jest.mock('electron') -jest.mock('../../../logger/logger') -jest.mock('../../../logger/logfile') -jest.mock('backend/vite_constants', () => ({ +import { vi, describe, expect } from 'vitest' +vi.mock('electron') +vi.mock('../../../logger/logger') +vi.mock('../../../logger/logfile') +vi.mock('backend/vite_constants', () => ({ VITE_IPFS_API: 'https://ipfs.io/ipfs/' })) -jest.mock('backend/flags/flags', () => ({ +vi.mock('backend/flags/flags', () => ({ VITE_LD_ENVIRONMENT_ID: '123' })) const TESTS_ENABLED = false diff --git a/src/backend/storeManagers/legendary/__tests__/games.ts b/src/backend/storeManagers/legendary/__tests__/games.ts index 07dc707879..0f13391f13 100644 --- a/src/backend/storeManagers/legendary/__tests__/games.ts +++ b/src/backend/storeManagers/legendary/__tests__/games.ts @@ -1,12 +1,13 @@ import { LegendaryGame } from '../games' import * as library from '../library' +import { vi, describe, expect, it } from 'vitest' -jest.mock('../../logger/logger') -jest.mock('../../logger/logfile') +vi.mock('../../logger/logger') +vi.mock('../../logger/logfile') describe('LegendaryGame', () => { it('Save-sync uses correct path', async () => { - const spy = jest + const spy = vi .spyOn(library, 'runLegendaryCommand') .mockImplementation(async () => { return { stderr: '', stdout: '' } @@ -28,7 +29,7 @@ describe('LegendaryGame', () => { }) it('Save-sync fails with empty path', async () => { - jest.spyOn(library, 'runLegendaryCommand') + vi.spyOn(library, 'runLegendaryCommand') const game = LegendaryGame.get('SomeAppName') expect(await game.syncSaves('', '')).toBe('No path provided.') }) diff --git a/src/backend/test_setup/index.ts b/src/backend/test_setup/index.ts new file mode 100644 index 0000000000..57f61c5241 --- /dev/null +++ b/src/backend/test_setup/index.ts @@ -0,0 +1,34 @@ +import { vi } from 'vitest' +/* eslint-disable @typescript-eslint/no-explicit-any */ +const allStores: Map> = new Map() +vi.mock('electron-store', () => { + class MockElectronStore { + store_name + constructor(args: Record) { + this.store_name = args.name + if (!allStores.has(this.store_name)) { + const x = new Map() + allStores.set(this.store_name, x) + } + } + get(key: any, defaultValue: any) { + return allStores.get(this.store_name)?.has(key) + ? allStores.get(this.store_name)?.get(key) + : defaultValue + } + set(key: any, value: any) { + allStores.get(this.store_name)?.set(key, value) + return true + } + has(key: any) { + return allStores.get(this.store_name)?.has(key) + } + delete(key: any) { + return allStores.get(this.store_name)?.delete(key) + } + clear() { + allStores.get(this.store_name)?.clear() + } + } + return { default: MockElectronStore } +}) diff --git a/src/backend/tray_icon/__tests__/tray_icon.test.ts b/src/backend/tray_icon/__tests__/tray_icon.test.ts index f4714931a8..ffae4d4947 100644 --- a/src/backend/tray_icon/__tests__/tray_icon.test.ts +++ b/src/backend/tray_icon/__tests__/tray_icon.test.ts @@ -7,13 +7,14 @@ import { configStore } from '../../constants' import { wait } from '../../utils' import i18next from 'i18next' import translations_en from '../../../../public/locales/en/translation.json' +import { vi, it, describe, expect, afterEach } from 'vitest' -jest.mock('../../logger/logfile') -jest.mock('../../config') -jest.mock('backend/vite_constants', () => ({ +vi.mock('../../logger/logfile') +vi.mock('../../config') +vi.mock('backend/vite_constants', () => ({ VITE_IPFS_API: 'https://ipfs.io/ipfs/' })) -jest.mock('backend/flags/flags', () => ({ +vi.mock('backend/flags/flags', () => ({ VITE_LD_ENVIRONMENT_ID: '123' })) i18next.init({ resources: { en: { translations_en } } }) @@ -22,11 +23,11 @@ describe('TrayIcon', () => { const mainWindow = new BrowserWindow() const setRecentGames = (games: RecentGame[]) => { - jest.spyOn(configStore, 'get').mockReturnValue(games) + vi.spyOn(configStore, 'get').mockReturnValue(games) } afterEach(() => { - configStore.get = jest.fn() + configStore.get = vi.fn() }) describe('content', () => { diff --git a/src/backend/utils/__tests__/compatibility_layers.test.ts b/src/backend/utils/__tests__/compatibility_layers.test.ts index b30d028f89..c7026bbb86 100644 --- a/src/backend/utils/__tests__/compatibility_layers.test.ts +++ b/src/backend/utils/__tests__/compatibility_layers.test.ts @@ -11,12 +11,13 @@ import { NonEmptyString, Path } from '../../storeManagers/legendary/commands/base' +import { vi, describe, expect, test, it } from 'vitest' -jest.mock('../../logger/logfile') -jest.mock('backend/vite_constants', () => ({ +vi.mock('../../logger/logfile') +vi.mock('backend/vite_constants', () => ({ VITE_IPFS_API: 'https://ipfs.io/ipfs/' })) -jest.mock('backend/flags/flags', () => ({ +vi.mock('backend/flags/flags', () => ({ VITE_LD_ENVIRONMENT_ID: '123' })) describe('getDefaultWine', () => { @@ -41,7 +42,7 @@ describe('getDefaultWine', () => { // spy on the execSync calling which wine and returning /usr/bin/wine // eslint-disable-next-line @typescript-eslint/no-var-requires - const execSync = jest.spyOn(require('child_process'), 'execSync') + const execSync = vi.spyOn(require('child_process'), 'execSync') execSync.mockImplementation((command: unknown) => { if (command === 'which wine') { return '/usr/bin/wine\n' diff --git a/src/backend/wiki_game_info/__tests__/wiki_game_info.test.ts b/src/backend/wiki_game_info/__tests__/wiki_game_info.test.ts index baaf5e6756..3f68a68142 100644 --- a/src/backend/wiki_game_info/__tests__/wiki_game_info.test.ts +++ b/src/backend/wiki_game_info/__tests__/wiki_game_info.test.ts @@ -8,28 +8,29 @@ import { getWikiGameInfo } from '../wiki_game_info' import * as PCGamingWiki from '../pcgamingwiki/utils' import * as AppleGamingWiki from '../applegamingwiki/utils' import { logError } from '../../logger/logger' +import { vi, describe, expect, test } from 'vitest' -jest.mock('electron-store') -jest.mock('../../logger/logfile') -jest.mock('../../logger/logger') -jest.mock('../../constants', () => { +vi.mock('electron-store') +vi.mock('../../logger/logfile') +vi.mock('../../logger/logger') +vi.mock('../../constants', () => { return { isMac: true } }) -jest.mock('backend/vite_constants', () => ({ +vi.mock('backend/vite_constants', () => ({ VITE_IPFS_API: 'https://ipfs.io/ipfs/' })) -jest.mock('backend/flags/flags', () => ({ +vi.mock('backend/flags/flags', () => ({ VITE_LD_ENVIRONMENT_ID: '123' })) describe('getWikiGameInfo', () => { test('use cached data', async () => { - const mockPCGamingWiki = jest + const mockPCGamingWiki = vi .spyOn(PCGamingWiki, 'getInfoFromPCGamingWiki') .mockResolvedValue(testPCGamingWikiInfo) - const mockAppleGamingWiki = jest + const mockAppleGamingWiki = vi .spyOn(AppleGamingWiki, 'getInfoFromAppleGamingWiki') .mockResolvedValue(testAppleGamingWikiInfo) @@ -58,10 +59,10 @@ describe('getWikiGameInfo', () => { const oneMonthAgo = new Date(testExtraGameInfo.timestampLastFetch) oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1) - const mockPCGamingWiki = jest + const mockPCGamingWiki = vi .spyOn(PCGamingWiki, 'getInfoFromPCGamingWiki') .mockResolvedValue(testPCGamingWikiInfo) - const mockAppleGamingWiki = jest + const mockAppleGamingWiki = vi .spyOn(AppleGamingWiki, 'getInfoFromAppleGamingWiki') .mockResolvedValue(testAppleGamingWikiInfo) @@ -90,9 +91,9 @@ describe('getWikiGameInfo', () => { }) test('catches throws', async () => { - jest - .spyOn(PCGamingWiki, 'getInfoFromPCGamingWiki') - .mockRejectedValueOnce(new Error('Failed')) + vi.spyOn(PCGamingWiki, 'getInfoFromPCGamingWiki').mockRejectedValueOnce( + new Error('Failed') + ) wikiGameInfoStore.clear() diff --git a/src/backend/wiki_game_info/applegamingwiki/__tests__/utils.test.ts b/src/backend/wiki_game_info/applegamingwiki/__tests__/utils.test.ts index 7f56084e54..f5679364f3 100644 --- a/src/backend/wiki_game_info/applegamingwiki/__tests__/utils.test.ts +++ b/src/backend/wiki_game_info/applegamingwiki/__tests__/utils.test.ts @@ -2,19 +2,20 @@ import { logError } from '../../../logger/logger' import { getInfoFromAppleGamingWiki } from '../utils' import axios from 'axios' import { AppleGamingWikiInfo } from '../../../../common/types' +import { vi, describe, expect, test } from 'vitest' -jest.mock('backend/logger/logfile') -jest.mock('backend/logger/logger') -jest.mock('electron-store') -jest.mock('backend/vite_constants', () => ({ +vi.mock('backend/logger/logfile') +vi.mock('backend/logger/logger') +vi.mock('electron-store') +vi.mock('backend/vite_constants', () => ({ VITE_IPFS_API: 'https://ipfs.io/ipfs/' })) -jest.mock('backend/flags/flags', () => ({ +vi.mock('backend/flags/flags', () => ({ VITE_LD_ENVIRONMENT_ID: '123' })) describe('getAppleGamingWikiInfo', () => { test('fetches successfully', async () => { - const mockAxios = jest.spyOn(axios, 'get').mockResolvedValueOnce({ + const mockAxios = vi.spyOn(axios, 'get').mockResolvedValueOnce({ data: { cargoquery: [{ title: { pageID: 1, crossover: 'perfect' } }] } }) mockAxios.mockResolvedValueOnce({ @@ -34,7 +35,7 @@ describe('getAppleGamingWikiInfo', () => { }) test('does not find page id', async () => { - jest.spyOn(axios, 'get').mockResolvedValueOnce({ + vi.spyOn(axios, 'get').mockResolvedValueOnce({ data: { cargoquery: [{ title: { pageID: undefined } }] } }) @@ -43,7 +44,7 @@ describe('getAppleGamingWikiInfo', () => { }) test('does not find wikitext', async () => { - const mockAxios = jest.spyOn(axios, 'get').mockResolvedValueOnce({ + const mockAxios = vi.spyOn(axios, 'get').mockResolvedValueOnce({ data: { cargoquery: [{ title: { pageID: 1, crossover: undefined } }] } }) mockAxios.mockResolvedValueOnce({ @@ -63,7 +64,7 @@ describe('getAppleGamingWikiInfo', () => { }) test('wikitext empty', async () => { - const mockAxios = jest.spyOn(axios, 'get').mockResolvedValueOnce({ + const mockAxios = vi.spyOn(axios, 'get').mockResolvedValueOnce({ data: { cargoquery: [{ title: { pageID: 1, crossover: 'perfect' } }] } }) mockAxios.mockResolvedValueOnce({ @@ -82,7 +83,7 @@ describe('getAppleGamingWikiInfo', () => { }) test('catches axios throws', async () => { - jest.spyOn(axios, 'get').mockRejectedValueOnce(new Error('Failed')) + vi.spyOn(axios, 'get').mockRejectedValueOnce(new Error('Failed')) const result = await getInfoFromAppleGamingWiki('The Witcher 3') expect(result).toBeNull() diff --git a/src/backend/wiki_game_info/pcgamingwiki/__tests__/utils.test.ts b/src/backend/wiki_game_info/pcgamingwiki/__tests__/utils.test.ts index d65f7e5a2e..979afd11e6 100644 --- a/src/backend/wiki_game_info/pcgamingwiki/__tests__/utils.test.ts +++ b/src/backend/wiki_game_info/pcgamingwiki/__tests__/utils.test.ts @@ -1,19 +1,20 @@ import { logError } from 'backend/logger/logger' import { getInfoFromPCGamingWiki } from '../utils' import axios from 'axios' +import { vi, test, describe, expect } from 'vitest' -jest.mock('backend/logger/logfile') -jest.mock('backend/logger/logger') -jest.mock('backend/vite_constants', () => ({ +vi.mock('backend/logger/logfile') +vi.mock('backend/logger/logger') +vi.mock('backend/vite_constants', () => ({ VITE_IPFS_API: 'https://ipfs.io/ipfs/' })) -jest.mock('backend/flags/flags', () => ({ +vi.mock('backend/flags/flags', () => ({ VITE_LD_ENVIRONMENT_ID: '123' })) describe('getPCGamingWikiInfo', () => { test('fetches successfully via title', async () => { - const mockAxios = jest.spyOn(axios, 'get').mockResolvedValueOnce({ + const mockAxios = vi.spyOn(axios, 'get').mockResolvedValueOnce({ data: { cargoquery: [{ title: { pageID: 1 } }] } }) mockAxios.mockResolvedValueOnce({ @@ -37,7 +38,7 @@ describe('getPCGamingWikiInfo', () => { }) test('fetches successfully via id', async () => { - const mockAxios = jest.spyOn(axios, 'get').mockResolvedValueOnce({ + const mockAxios = vi.spyOn(axios, 'get').mockResolvedValueOnce({ data: { cargoquery: [{ title: { pageID: 1 } }] } }) mockAxios.mockResolvedValueOnce({ @@ -61,7 +62,7 @@ describe('getPCGamingWikiInfo', () => { }) test('does not find page id', async () => { - jest.spyOn(axios, 'get').mockResolvedValueOnce({ + vi.spyOn(axios, 'get').mockResolvedValueOnce({ data: { cargoquery: [{ title: { pageID: undefined } }] } }) @@ -70,7 +71,7 @@ describe('getPCGamingWikiInfo', () => { }) test('does not find wikitext', async () => { - const mockAxios = jest.spyOn(axios, 'get').mockResolvedValueOnce({ + const mockAxios = vi.spyOn(axios, 'get').mockResolvedValueOnce({ data: { cargoquery: [{ title: { pageID: 1 } }] } }) mockAxios.mockResolvedValueOnce({ @@ -86,7 +87,7 @@ describe('getPCGamingWikiInfo', () => { }) test('wikitext empty', async () => { - const mockAxios = jest.spyOn(axios, 'get').mockResolvedValueOnce({ + const mockAxios = vi.spyOn(axios, 'get').mockResolvedValueOnce({ data: { cargoquery: [{ title: { pageID: 1 } }] } }) mockAxios.mockResolvedValueOnce({ @@ -102,7 +103,7 @@ describe('getPCGamingWikiInfo', () => { }) test('catches axios throws', async () => { - jest.spyOn(axios, 'get').mockRejectedValueOnce(new Error('Failed')) + vi.spyOn(axios, 'get').mockRejectedValueOnce(new Error('Failed')) const result = await getInfoFromPCGamingWiki('The Witcher 3') expect(result).toBeNull() diff --git a/src/backend/wine/manager/downloader/__test__/main/getter.test.ts b/src/backend/wine/manager/downloader/__test__/main/getter.test.ts index 6e5189571d..93392489d4 100644 --- a/src/backend/wine/manager/downloader/__test__/main/getter.test.ts +++ b/src/backend/wine/manager/downloader/__test__/main/getter.test.ts @@ -2,10 +2,11 @@ import { Repositorys, VersionInfo } from 'common/types' import { getAvailableVersions } from '../../main' import { test_data_release_list } from '../test_data/github-api-test-data.json' import * as axios from 'axios' +import { vi, test, describe, expect } from 'vitest' describe('Main - GetAvailableVersions', () => { test('fetch releases succesfully', async () => { - axios.default.get = jest.fn().mockResolvedValue(test_data_release_list) + axios.default.get = vi.fn().mockResolvedValue(test_data_release_list) await getAvailableVersions({}) .then((releases: VersionInfo[]) => { @@ -23,7 +24,7 @@ describe('Main - GetAvailableVersions', () => { }) test('fetch releases succesfully independent', async () => { - axios.default.get = jest.fn().mockResolvedValue(test_data_release_list) + axios.default.get = vi.fn().mockResolvedValue(test_data_release_list) for (let key = 0; key < Object.keys(Repositorys).length / 2; key++) { await getAvailableVersions({ @@ -45,7 +46,7 @@ describe('Main - GetAvailableVersions', () => { }) test('fetch releases failed because of 404', async () => { - axios.default.get = jest.fn().mockRejectedValue('Could not fetch tag 404') + axios.default.get = vi.fn().mockRejectedValue('Could not fetch tag 404') for (let key = 0; key < Object.keys(Repositorys).length / 2; key++) { await getAvailableVersions({ repositorys: [key] }) @@ -63,8 +64,8 @@ describe('Main - GetAvailableVersions', () => { }) test('Invalid repository key returns nothing', async () => { - axios.default.get = jest.fn() - console.warn = jest.fn() + axios.default.get = vi.fn() + console.warn = vi.fn() /* eslint-disable-next-line */ //@ts-ignore diff --git a/src/backend/wine/manager/downloader/__test__/main/install.test.ts b/src/backend/wine/manager/downloader/__test__/main/install.test.ts index a4f49497d7..85831153a7 100644 --- a/src/backend/wine/manager/downloader/__test__/main/install.test.ts +++ b/src/backend/wine/manager/downloader/__test__/main/install.test.ts @@ -10,12 +10,13 @@ import { VersionInfo } from 'common/types' import * as axios from 'axios' import * as crypto from 'crypto' import { clearInterval } from 'timers' +import { vi, describe, expect, test } from 'vitest' const workDir = process.cwd() describe('Main - InstallVersion', () => { test('install fails because installDir does not exist', async () => { - const progress = jest.fn() + const progress = vi.fn() const releaseVersion: VersionInfo = { version: '1.2.3', @@ -42,7 +43,7 @@ describe('Main - InstallVersion', () => { }) test('install fails because installDir is not a directory', async () => { - const progress = jest.fn() + const progress = vi.fn() const releaseVersion: VersionInfo = { version: '1.2.3', @@ -69,7 +70,7 @@ describe('Main - InstallVersion', () => { }) test('install fails because no download link provided', async () => { - const progress = jest.fn() + const progress = vi.fn() const releaseVersion: VersionInfo = { version: '1.2.3', @@ -94,7 +95,7 @@ describe('Main - InstallVersion', () => { }) test('install fails because no download link provided', async () => { - const progress = jest.fn() + const progress = vi.fn() const releaseVersion: VersionInfo = { version: '1.2.3', @@ -123,8 +124,8 @@ describe('Main - InstallVersion', () => { const installDir = __dirname + '/test_install' let failed = false - axios.default.get = jest.fn().mockReturnValue({ data: checksum }) - const progress = jest.fn() + axios.default.get = vi.fn().mockReturnValue({ data: checksum }) + const progress = vi.fn() if (!existsSync(installDir)) { mkdirSync(installDir) @@ -175,9 +176,9 @@ describe('Main - InstallVersion', () => { test('install warns because no checksum provided', async () => { const installDir = __dirname + '/test_install' let failed = false - axios.default.get = jest.fn() - const progress = jest.fn() - console.warn = jest.fn() + axios.default.get = vi.fn() + const progress = vi.fn() + console.warn = vi.fn() if (!existsSync(installDir)) { mkdirSync(installDir) @@ -229,8 +230,8 @@ describe('Main - InstallVersion', () => { test('install succeed because already exist', async () => { const installDir = __dirname + '/test_install' let failed = false - axios.default.get = jest.fn().mockReturnValue({ data: '' }) - const progress = jest.fn() + axios.default.get = vi.fn().mockReturnValue({ data: '' }) + const progress = vi.fn() if (!existsSync(installDir)) { mkdirSync(`${installDir}/Wine-1.2.3`, { recursive: true }) @@ -280,8 +281,8 @@ describe('Main - InstallVersion', () => { const installDir = __dirname + '/test_install' let failed = false - axios.default.get = jest.fn().mockReturnValue({ data: checksum }) - const progress = jest.fn() + axios.default.get = vi.fn().mockReturnValue({ data: checksum }) + const progress = vi.fn() if (!existsSync(installDir)) { mkdirSync(installDir) @@ -347,8 +348,8 @@ describe('Main - InstallVersion', () => { const installDir = __dirname + '/test_install' let failed = false - axios.default.get = jest.fn().mockReturnValue({ data: checksum }) - const progress = jest.fn() + axios.default.get = vi.fn().mockReturnValue({ data: checksum }) + const progress = vi.fn() if (!existsSync(installDir)) { mkdirSync(installDir) @@ -414,8 +415,8 @@ describe('Main - InstallVersion', () => { const installDir = __dirname + '/test_install' let failed = false - axios.default.get = jest.fn().mockReturnValue({ data: checksum }) - const progress = jest.fn() + axios.default.get = vi.fn().mockReturnValue({ data: checksum }) + const progress = vi.fn() if (!existsSync(installDir)) { mkdirSync(installDir) @@ -473,8 +474,8 @@ describe('Main - InstallVersion', () => { const installDir = __dirname + '/test_install' let failed = false - axios.default.get = jest.fn().mockReturnValue({ data: checksum }) - const progress = jest.fn() + axios.default.get = vi.fn().mockReturnValue({ data: checksum }) + const progress = vi.fn() if (!existsSync(installDir)) { mkdirSync(installDir) @@ -537,8 +538,8 @@ describe('Main - InstallVersion', () => { const installDir = __dirname + '/test_install' let failed = false - axios.default.get = jest.fn().mockReturnValue({ data: checksum }) - const progress = jest.fn() + axios.default.get = vi.fn().mockReturnValue({ data: checksum }) + const progress = vi.fn() if (!existsSync(installDir)) { mkdirSync(installDir) diff --git a/src/backend/wine/manager/downloader/__test__/utilities/download.test.ts b/src/backend/wine/manager/downloader/__test__/utilities/download.test.ts index e97f384948..2dc805a7f3 100644 --- a/src/backend/wine/manager/downloader/__test__/utilities/download.test.ts +++ b/src/backend/wine/manager/downloader/__test__/utilities/download.test.ts @@ -1,11 +1,12 @@ import { existsSync, mkdirSync, rmSync } from 'graceful-fs' import { downloadFile } from '../../utilities' +import { vi, test, describe, expect } from 'vitest' const workDir = process.cwd() describe('Utilities - Download', () => { test('download file fails because of invalid installDir', async () => { - const progress = jest.fn() + const progress = vi.fn() await downloadFile({ url: '', downloadDir: 'invalid', @@ -21,7 +22,7 @@ describe('Utilities - Download', () => { }) test('download file fails because of installDir is a file', async () => { - const progress = jest.fn() + const progress = vi.fn() await downloadFile({ url: '', downloadDir: __filename, @@ -39,7 +40,7 @@ describe('Utilities - Download', () => { }) test('download file can be aborted', async () => { - const progress = jest.fn() + const progress = vi.fn() const installDir = __dirname + '/test_download' let failed = false @@ -77,7 +78,7 @@ describe('Utilities - Download', () => { }) test('download file succeed', async () => { - const progress = jest.fn() + const progress = vi.fn() const installDir = __dirname + '/test_download' let failed = false diff --git a/src/backend/wine/manager/downloader/__test__/utilities/rest.test.ts b/src/backend/wine/manager/downloader/__test__/utilities/rest.test.ts index 57165bf5ad..05fcea5bbc 100644 --- a/src/backend/wine/manager/downloader/__test__/utilities/rest.test.ts +++ b/src/backend/wine/manager/downloader/__test__/utilities/rest.test.ts @@ -1,5 +1,6 @@ import { existsSync, writeFileSync } from 'graceful-fs' import { getFolderSize, unlinkFile } from '../../utilities' +import { test, describe, expect } from 'vitest' const workDir = process.cwd() diff --git a/src/backend/wine/manager/downloader/__test__/utilities/unzip.test.ts b/src/backend/wine/manager/downloader/__test__/utilities/unzip.test.ts index d6a9d9fb35..12780b7bc0 100644 --- a/src/backend/wine/manager/downloader/__test__/utilities/unzip.test.ts +++ b/src/backend/wine/manager/downloader/__test__/utilities/unzip.test.ts @@ -1,11 +1,12 @@ import { existsSync, mkdirSync, rmSync } from 'graceful-fs' import { unzipFile } from '../../utilities' +import { vi, test, describe, expect } from 'vitest' const workDir = process.cwd() describe('Utilities - Unzip', () => { test('unzip file fails because of invalid archive path', async () => { - const progress = jest.fn() + const progress = vi.fn() await unzipFile({ filePath: 'invalid.tar.xz', unzipDir: __dirname, @@ -20,7 +21,7 @@ describe('Utilities - Unzip', () => { }) test('unzip file fails because of archive is not a file', async () => { - const progress = jest.fn() + const progress = vi.fn() await unzipFile({ filePath: __dirname, unzipDir: __dirname, @@ -37,7 +38,7 @@ describe('Utilities - Unzip', () => { }) test('unzip file fails because of invalid install path', async () => { - const progress = jest.fn() + const progress = vi.fn() await unzipFile({ filePath: `${__dirname}/../test_data/test.tar.xz`, unzipDir: 'invalid', @@ -52,7 +53,7 @@ describe('Utilities - Unzip', () => { }) test('unzip file can be aborted', async () => { - const progress = jest.fn() + const progress = vi.fn() const installDir = __dirname + '/test_unzip' let failed = false @@ -89,7 +90,7 @@ describe('Utilities - Unzip', () => { }) test('unzip tar.xz file succeesfully', async () => { - const progress = jest.fn() + const progress = vi.fn() const installDir = __dirname + '/test_unzip' let failed = false @@ -121,7 +122,7 @@ describe('Utilities - Unzip', () => { }) test('unzip tar.gz file succeesfully', async () => { - const progress = jest.fn() + const progress = vi.fn() const installDir = __dirname + '/test_unzip' let failed = false @@ -152,7 +153,7 @@ describe('Utilities - Unzip', () => { }) test('unzip tar.gz file twice to the same direction succeesfully', async () => { - const progress = jest.fn() + const progress = vi.fn() const installDir = __dirname + '/test_unzip' let failed = false diff --git a/src/backend/wine/runtimes/__tests__/runtimes/utils.test.ts b/src/backend/wine/runtimes/__tests__/runtimes/utils.test.ts index 003ced4095..d087efcf6d 100644 --- a/src/backend/wine/runtimes/__tests__/runtimes/utils.test.ts +++ b/src/backend/wine/runtimes/__tests__/runtimes/utils.test.ts @@ -5,6 +5,7 @@ import child_process from 'child_process' import { downloadFile, extractTarFile } from '../../util' import { dirSync } from 'tmp' import { platform } from 'os' +import { vi, afterEach, describe, it, expect } from 'vitest' const testUrl = 'https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher/releases/download/v2.3.9/Heroic-2.3.9.AppImage' @@ -14,7 +15,7 @@ const testTarFileWithSubfolder = join( 'test_data/ArchiveWithSubfolder.tar.xz' ) -afterEach(jest.restoreAllMocks) +afterEach(vi.restoreAllMocks) const shouldSkip = platform() !== 'linux' const skipMessage = 'not on linux so skipping test' @@ -32,17 +33,15 @@ describe('downloadFile', () => { it('Success', async () => { const expectedData = readFileSync(testTarFilePath) - jest.spyOn(axios, 'get').mockResolvedValue({ + vi.spyOn(axios, 'get').mockResolvedValue({ status: 200, data: expectedData }) - jest - .spyOn(graceful_fs, 'writeFile') - .mockImplementation( - (path, data, callback: (err: NodeJS.ErrnoException | null) => void) => { - callback(null) - } - ) + vi.spyOn(graceful_fs, 'writeFile').mockImplementation( + (path, data, callback: (err: NodeJS.ErrnoException | null) => void) => { + callback(null) + } + ) const tmpFileName = '/tmp/someFile' await expect(downloadFile(testUrl, tmpFileName)).resolves.toBeUndefined() @@ -56,7 +55,7 @@ describe('downloadFile', () => { it('Axios error', async () => { expect.assertions(1) - jest.spyOn(axios, 'get').mockRejectedValue({ + vi.spyOn(axios, 'get').mockRejectedValue({ toJSON: () => '{ "message": "Some error message" }' }) @@ -70,7 +69,7 @@ describe('downloadFile', () => { it('HTTP error', async () => { expect.assertions(1) - jest.spyOn(axios, 'get').mockResolvedValue({ + vi.spyOn(axios, 'get').mockResolvedValue({ status: 404, data: {} }) @@ -84,12 +83,12 @@ describe('downloadFile', () => { join(__dirname, 'test_data/TestArchive.tar.xz') ) - jest.spyOn(axios, 'get').mockResolvedValue({ + vi.spyOn(axios, 'get').mockResolvedValue({ status: 200, data: expectedData }) - jest.spyOn(graceful_fs, 'writeFile').mockImplementation((fn, data, cb) => { + vi.spyOn(graceful_fs, 'writeFile').mockImplementation((fn, data, cb) => { cb({ stack: 'Mocked error stack' } as Error) }) @@ -107,7 +106,7 @@ describe('extractTarFile', () => { } it('Success without strip', async () => { const tmpDir = dirSync({ unsafeCleanup: true }) - jest.spyOn(child_process, 'spawn') + vi.spyOn(child_process, 'spawn') await expect( extractTarFile(testTarFilePath, 'application/x-xz', { @@ -129,7 +128,7 @@ describe('extractTarFile', () => { // Largely the same as the test above it('Success with strip', async () => { const tmpDir = dirSync({ unsafeCleanup: true }) - jest.spyOn(child_process, 'spawn') + const spawnMock = vi.spyOn(child_process, 'spawn') await expect( extractTarFile(testTarFileWithSubfolder, 'application/x-xz', { @@ -139,7 +138,7 @@ describe('extractTarFile', () => { ).resolves.toEqual(0) expect(existsSync(join(tmpDir.name, 'empty'))).toBe(true) - expect(child_process.spawn).toBeCalledWith('tar', [ + expect(spawnMock).toBeCalledWith('tar', [ '--directory', tmpDir.name, '--strip-components', @@ -151,12 +150,12 @@ describe('extractTarFile', () => { it('Success without pre-defined extraction dir', async () => { let child: child_process.ChildProcess - jest.spyOn(child_process, 'spawn').mockImplementation(() => { + vi.spyOn(child_process, 'spawn').mockImplementation(() => { child = new child_process.ChildProcess() return child }) - jest.spyOn(graceful_fs, 'mkdirSync').mockImplementation() + vi.spyOn(graceful_fs, 'mkdirSync').mockImplementation(() => undefined) const promise = extractTarFile(testTarFilePath, 'application/x-xz') child!.emit('close', 0) @@ -170,7 +169,7 @@ describe('extractTarFile', () => { it('File does not exist', async () => { expect.assertions(1) - jest.spyOn(graceful_fs, 'existsSync').mockReturnValue(false) + vi.spyOn(graceful_fs, 'existsSync').mockReturnValue(false) await expect(extractTarFile(testTarFilePath, '')).rejects.toEqual( Error('Specified file does not exist: ' + testTarFilePath) @@ -181,7 +180,7 @@ describe('extractTarFile', () => { expect.assertions(1) // Don't create archive extraction directory - jest.spyOn(graceful_fs, 'mkdirSync').mockImplementation() + vi.spyOn(graceful_fs, 'mkdirSync').mockImplementation(() => undefined) // Let's try extracting a PDF file :^) await expect( @@ -194,12 +193,12 @@ describe('extractTarFile', () => { // everything either results in `child` being undefined or a deadlock. If someone successfully // creates a helper to mock spawn, they deserve at least a medal let child: child_process.ChildProcess - jest.spyOn(child_process, 'spawn').mockImplementation(() => { + vi.spyOn(child_process, 'spawn').mockImplementation(() => { child = new child_process.ChildProcess() return child }) - jest.spyOn(graceful_fs, 'mkdirSync').mockImplementation() + vi.spyOn(graceful_fs, 'mkdirSync').mockImplementation(() => undefined) const promise = extractTarFile(testTarFilePath, 'application/x-xz') child!.emit('error', Error('Some error')) diff --git a/src/backend/wine/runtimes/util.ts b/src/backend/wine/runtimes/util.ts index ca52556ba8..19ba11838a 100644 --- a/src/backend/wine/runtimes/util.ts +++ b/src/backend/wine/runtimes/util.ts @@ -1,5 +1,5 @@ import axios from 'axios' -import { spawn } from 'child_process' +import child_process from 'child_process' import { existsSync, mkdirSync, writeFile } from 'graceful-fs' interface GithubAssetMetadata { @@ -100,7 +100,7 @@ async function extractTarFile( const strip = options?.strip return new Promise((res, rej) => { - const child = spawn('tar', [ + const child = child_process.spawn('tar', [ '--directory', extractedPath, ...(strip ? ['--strip-components', `${strip}`] : []), diff --git a/src/frontend/__tests__/helpers/extract-main-domain.test.ts b/src/frontend/__tests__/helpers/extract-main-domain.test.ts index 24b3beb982..1c9b92725f 100644 --- a/src/frontend/__tests__/helpers/extract-main-domain.test.ts +++ b/src/frontend/__tests__/helpers/extract-main-domain.test.ts @@ -1,4 +1,5 @@ import { extractMainDomain } from 'frontend/helpers/extract-main-domain' +import { describe, expect, it } from 'vitest' describe('extractMainDomain', () => { it('should correctly extract main domain without subdomain', () => { @@ -26,7 +27,7 @@ describe('extractMainDomain', () => { }) it('return null when url is invalid', () => { - jest.spyOn(console, 'warn').mockImplementationOnce(jest.fn) + vi.spyOn(console, 'warn').mockImplementationOnce(vi.fn) const url = 'invalid url' const mainDomain = extractMainDomain(url) expect(mainDomain).toEqual(null) diff --git a/src/frontend/jest.config.js b/src/frontend/jest.config.js deleted file mode 100644 index 509aa31a53..0000000000 --- a/src/frontend/jest.config.js +++ /dev/null @@ -1,27 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/no-var-requires -const { compilerOptions } = require('../../tsconfig') - -module.exports = { - displayName: 'Frontend', - - moduleDirectories: ['node_modules', ''], - // Module file extensions for importing - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'], - testPathIgnorePatterns: ['./node_modules/'], - resetMocks: true, - - rootDir: '../..', - - // The root of your source code, typically /src - // `` is a token Jest substitutes - roots: ['/src/frontend'], - - testMatch: ['**/__tests__/**/*.test.{ts,tsx}'], - // Jest transformations -- this adds support for TypeScript - // using ts-jest - transform: { - '^.+\\.tsx?$': 'ts-jest' - }, - - modulePaths: [compilerOptions.baseUrl] -} diff --git a/src/frontend/state/__tests__/libraryState.test.ts b/src/frontend/state/__tests__/libraryState.test.ts index 10172164f0..65ebd5740d 100644 --- a/src/frontend/state/__tests__/libraryState.test.ts +++ b/src/frontend/state/__tests__/libraryState.test.ts @@ -1,12 +1,13 @@ -/** @jest-environment jsdom */ +/** @vi-environment jsdom */ +import { vi, describe, expect, test, beforeEach } from 'vitest' Object.defineProperty(window, 'api', { writable: true, value: { - install: jest.fn(), - storeNew: jest.fn(), - storeGet: jest.fn(), - storeSet: jest.fn() + install: vi.fn(), + storeNew: vi.fn(), + storeGet: vi.fn(), + storeSet: vi.fn() } }) diff --git a/tsconfig.json b/tsconfig.json index df6ae7141e..b84415d685 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,7 +24,7 @@ "noEmit": true, "noFallthroughCasesInSwitch": true, "baseUrl": "./src/", - "types": ["@types/chrome", "@types/jest"], + "types": ["@types/chrome"], "typeRoots": ["./node_modules", "src/common/typedefs"], "strictPropertyInitialization": true }, diff --git a/vite.config.ts b/vite.config.ts index 6a38dbb741..a53d27525b 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -58,6 +58,12 @@ const preloads = [ ] export default defineConfig(({ mode }) => ({ + test: { + coverage: { + include: ['src/backend'] + }, + setupFiles: ['src/backend/test_setup/index.ts'] + }, main: { build: { rollupOptions: {