From d47414f53f3d0057bb352fec8841824c510c3ebb Mon Sep 17 00:00:00 2001 From: John Goodliff Date: Sun, 2 Jun 2024 22:32:48 -0600 Subject: [PATCH 01/15] Add test and ts-jest deps --- package.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 06cbfed..6243508 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,8 @@ "build": "tsc", "watch": "tsc --watch", "clean": "tsc --build --clean", - "prepare": "npm run build" + "test": "jest", + "prepare": "npm run test && npm run build" }, "peerDependencies": { "gatsby": "^5.0.0-next" @@ -51,10 +52,13 @@ }, "devDependencies": { "@biomejs/biome": "1.7.3", + "@jest/globals": "^29.7.0", "@tsconfig/node20": "^20.1.4", "@types/express": "^4.17.21", "gatsby": "^5.0.0-next", "gatsby-plugin-utils": "^4.0.0", + "jest": "^29.7.0", + "ts-jest": "^29.1.4", "typescript": "^5.4.5" }, "engines": { From 375ab007c55ebdf05192065c7235d6034668d7ad Mon Sep 17 00:00:00 2001 From: John Goodliff Date: Sun, 2 Jun 2024 22:33:09 -0600 Subject: [PATCH 02/15] Add Jest config --- jest.config.js | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 jest.config.js diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..d7232d3 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,9 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + collectCoverage: true, + collectCoverageFrom: ['src/**/*.ts'], + coverageDirectory: 'coverage', + coverageProvider: 'v8', +}; From eeb600d788b95371509260c91b14893bc5789c58 Mon Sep 17 00:00:00 2001 From: John Goodliff Date: Sun, 2 Jun 2024 22:33:19 -0600 Subject: [PATCH 03/15] Update yarn.lock --- yarn.lock | 1093 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 1063 insertions(+), 30 deletions(-) diff --git a/yarn.lock b/yarn.lock index 2e82108..bce082e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -40,7 +40,7 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.24.6", "@babel/code-frame@^7.8.3": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.24.6", "@babel/code-frame@^7.8.3": version "7.24.6" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.6.tgz#ab88da19344445c3d8889af2216606d3329f3ef2" integrity sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA== @@ -53,7 +53,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.6.tgz#b3600217688cabb26e25f8e467019e66d71b7ae2" integrity sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ== -"@babel/core@^7.14.0", "@babel/core@^7.20.12": +"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.14.0", "@babel/core@^7.20.12", "@babel/core@^7.23.9": version "7.24.6" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.6.tgz#8650e0e4b03589ebe886c4e4a60398db0a7ec787" integrity sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ== @@ -83,7 +83,7 @@ eslint-visitor-keys "^2.1.0" semver "^6.3.1" -"@babel/generator@^7.14.0", "@babel/generator@^7.20.14", "@babel/generator@^7.24.6": +"@babel/generator@^7.14.0", "@babel/generator@^7.20.14", "@babel/generator@^7.24.6", "@babel/generator@^7.7.2": version "7.24.6" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.6.tgz#dfac82a228582a9d30c959fe50ad28951d4737a7" integrity sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg== @@ -291,7 +291,7 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@^7.14.0", "@babel/parser@^7.16.8", "@babel/parser@^7.20.13", "@babel/parser@^7.24.6": +"@babel/parser@^7.1.0", "@babel/parser@^7.14.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.8", "@babel/parser@^7.20.13", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.24.6": version "7.24.6" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.6.tgz#5e030f440c3c6c78d195528c3b688b101a365328" integrity sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q== @@ -384,7 +384,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.0.0", "@babel/plugin-syntax-class-properties@^7.12.13": +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.0.0", "@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== @@ -433,7 +440,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.24.6" -"@babel/plugin-syntax-import-meta@^7.10.4": +"@babel/plugin-syntax-import-meta@^7.10.4", "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== @@ -447,14 +454,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.24.6": +"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.24.6", "@babel/plugin-syntax-jsx@^7.7.2": version "7.24.6" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.6.tgz#bcca2964150437f88f65e3679e3d68762287b9c8" integrity sha512-lWfvAIFNWMlCsU0DRUun2GpFwZdGTukLaHJqRh1JRb80NdAP5Sb1HDHB5X9P9OtgZHQl089UzQkpYlBq2VTPRw== dependencies: "@babel/helper-plugin-utils" "^7.24.6" -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== @@ -468,7 +475,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.10.4": +"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== @@ -503,14 +510,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-top-level-await@^7.14.5": +"@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.24.6": +"@babel/plugin-syntax-typescript@^7.24.6", "@babel/plugin-syntax-typescript@^7.7.2": version "7.24.6" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.6.tgz#769daf2982d60308bc83d8936eaecb7582463c87" integrity sha512-TzCtxGgVTEJWWwcYwQhCIQ6WaKlo80/B+Onsk4RRCcYqpYGFcG9etPW94VToGte5AAcxRrhjPUFvUS3Y2qKi4A== @@ -1106,7 +1113,7 @@ dependencies: regenerator-runtime "^0.14.0" -"@babel/template@^7.20.7", "@babel/template@^7.24.6": +"@babel/template@^7.20.7", "@babel/template@^7.24.6", "@babel/template@^7.3.3": version "7.24.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.6.tgz#048c347b2787a6072b24c723664c8d02b67a44f9" integrity sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw== @@ -1131,7 +1138,7 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.16.8", "@babel/types@^7.20.7", "@babel/types@^7.24.6", "@babel/types@^7.4.4": +"@babel/types@^7.0.0", "@babel/types@^7.16.8", "@babel/types@^7.20.7", "@babel/types@^7.24.6", "@babel/types@^7.3.3", "@babel/types@^7.4.4": version "7.24.6" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.6.tgz#ba4e1f59870c10dc2fa95a274ac4feec23b21912" integrity sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ== @@ -1140,6 +1147,11 @@ "@babel/helper-validator-identifier" "^7.24.6" to-fast-properties "^2.0.0" +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + "@biomejs/biome@1.7.3": version "1.7.3" resolved "https://registry.yarnpkg.com/@biomejs/biome/-/biome-1.7.3.tgz#847a317b63c811534fc8108389b7a9fae8803eed" @@ -1455,6 +1467,214 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== + dependencies: + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.7.0" + jest-config "^29.7.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.4" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== + dependencies: + jest-get-type "^29.6.3" + +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + dependencies: + "@jest/types" "^29.6.3" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" + +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== + 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.18" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== + dependencies: + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== + dependencies: + "@jest/test-result" "^29.7.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + slash "^3.0.0" + +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + dependencies: + "@jest/schemas" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + "@jridgewell/gen-mapping@^0.3.5": version "0.3.5" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" @@ -1487,7 +1707,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== @@ -2086,6 +2306,11 @@ lodash "^4.17.10" require-package-name "^2.0.1" +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + "@sindresorhus/is@^4.0.0": version "4.6.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" @@ -2112,6 +2337,20 @@ escape-string-regexp "^2.0.0" lodash.deburr "^4.1.0" +"@sinonjs/commons@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" + integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + "@socket.io/component-emitter@~3.1.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2" @@ -2171,6 +2410,39 @@ resolved "https://registry.yarnpkg.com/@turist/time/-/time-0.0.2.tgz#32fe0ce708ea0f4512776bd313409f1459976dda" integrity sha512-qLOvfmlG2vCVw5fo/oz8WAZYlpe5a5OurgTj3diIxJCdjRHpapC+vQCz3er9LV79Vcat+DifBjeAhOAdmndtDQ== +"@types/babel__core@^7.1.14": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.8" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" + integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.20.6" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.6.tgz#8dc9f0ae0f202c08d8d4dab648912c8d6038e3f7" + integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== + dependencies: + "@babel/types" "^7.20.7" + "@types/body-parser@*": version "1.19.5" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" @@ -2293,6 +2565,13 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/graceful-fs@^4.1.3": + version "4.1.9" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" + integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== + dependencies: + "@types/node" "*" + "@types/http-cache-semantics@*", "@types/http-cache-semantics@^4.0.2": version "4.0.4" resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#b979ebad3919799c979b17c72621c0bc0a31c6c4" @@ -2310,6 +2589,25 @@ dependencies: "@types/node" "*" +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + +"@types/istanbul-lib-report@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" @@ -2448,11 +2746,28 @@ "@types/node" "*" "@types/send" "*" +"@types/stack-utils@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + "@types/tmp@^0.0.33": version "0.0.33" resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d" integrity sha512-gVC1InwyVrO326wbBZw+AO3u2vRXz/iRWq9jYhpG4W8LXyIgDv3ZmcLQ5Q4Gs+gFMyqx+viFoFT+l3p61QFCmQ== +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^17.0.8": + version "17.0.32" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" + integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== + dependencies: + "@types/yargs-parser" "*" + "@types/yauzl@^2.9.1": version "2.10.3" resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.3.tgz#e9b2808b4f109504a03cda958259876f61017999" @@ -2832,7 +3147,12 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -anymatch@~3.1.2: +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +anymatch@^3.0.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -3068,6 +3388,19 @@ b4a@^1.6.4: resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.6.6.tgz#a4cc349a3851987c3c4ac2d7785c18744f6da9ba" integrity sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg== +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== + dependencies: + "@jest/transform" "^29.7.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.6.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + babel-jsx-utils@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/babel-jsx-utils/-/babel-jsx-utils-1.1.0.tgz#304ce4fce0c86cbeee849551a45eb4ed1036381a" @@ -3095,6 +3428,27 @@ babel-plugin-dynamic-import-node@^2.3.3: dependencies: object.assign "^4.1.0" +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + babel-plugin-macros@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" @@ -3147,6 +3501,24 @@ babel-plugin-transform-react-remove-prop-types@^0.4.24: resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + babel-preset-fbjs@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz#38a14e5a7a3b285a3f3a86552d650dca5cf6111c" @@ -3201,6 +3573,14 @@ babel-preset-gatsby@^3.13.2: gatsby-core-utils "^4.13.1" gatsby-legacy-polyfills "^3.13.1" +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -3372,6 +3752,13 @@ browserslist@^4.0.0, browserslist@^4.18.1, browserslist@^4.21.10, browserslist@^ node-releases "^2.0.14" update-browserslist-db "^1.0.13" +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -3483,7 +3870,7 @@ camel-case@^4.1.2: pascal-case "^3.1.2" tslib "^2.0.3" -camelcase@^5.0.0: +camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== @@ -3584,6 +3971,11 @@ change-case@^4.1.2: snake-case "^3.0.4" tslib "^2.0.3" +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -3628,6 +4020,16 @@ ci-info@2.0.0, ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +ci-info@^3.2.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + +cjs-module-lexer@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz#c485341ae8fd999ca4ee5af2d7a1c9ae01e0099c" + integrity sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q== + cli-boxes@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" @@ -3693,6 +4095,16 @@ clone@^2.1.1: resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" + integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -3962,6 +4374,19 @@ create-gatsby@^3.13.1: dependencies: "@babel/runtime" "^7.20.13" +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + cross-fetch@^3.1.5: version "3.1.8" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" @@ -4202,6 +4627,11 @@ decompress-response@^6.0.0: dependencies: mimic-response "^3.1.0" +dedent@^1.0.0: + version "1.5.3" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.3.tgz#99aee19eb9bae55a67327717b6e848d0bf777e5a" + integrity sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ== + deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" @@ -4289,6 +4719,11 @@ detect-libc@^2.0.0, detect-libc@^2.0.2: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + detect-port-alt@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/detect-port-alt/-/detect-port-alt-1.1.6.tgz#24707deabe932d4a3cf621302027c2b266568275" @@ -4339,6 +4774,11 @@ devtools-protocol@0.0.1286932: resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1286932.tgz#2303707034426fe0b39012713d4b7339f7dbc815" integrity sha512-wu58HMQll9voDjR4NlPyoDEw1syfzaBNHymMMZ/QOXiHRNluOnDgu9hp1yHOKYoMlxCh4lSSiugLITe6Fvu1eA== +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -4442,6 +4882,11 @@ electron-to-chromium@^1.4.668: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.787.tgz#3eedd0a3b8be2b9e96e21675d399786ad90b99ed" integrity sha512-d0EFmtLPjctczO3LogReyM2pbBiiZbnsKnGF+cdZhsYzHm/A0GV7W94kqzLD8SN4O3f3iHlgLUChqghgyznvCQ== +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -5019,7 +5464,7 @@ events@^3.2.0: resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== -execa@^5.1.1: +execa@^5.0.0, execa@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== @@ -5049,11 +5494,27 @@ execa@^8.0.1: signal-exit "^4.1.0" strip-final-newline "^3.0.0" +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + expand-template@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== +expect@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== + 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" + express-http-proxy@^1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/express-http-proxy/-/express-http-proxy-1.6.3.tgz#f3ef139ffd49a7962e7af0462bbcca557c913175" @@ -5148,7 +5609,7 @@ fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" -fast-json-stable-stringify@^2.0.0: +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -5413,7 +5874,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@~2.3.2: +fsevents@^2.3.2, fsevents@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -5856,6 +6317,11 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@ has-symbols "^1.0.3" hasown "^2.0.0" +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + get-port@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" @@ -5922,7 +6388,7 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.6, glob@^7.2.3: +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -6028,7 +6494,7 @@ graceful-fs@4.2.10: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -6158,6 +6624,11 @@ html-entities@^2.1.0, html-entities@^2.3.3: resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA== +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + htmlparser2@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" @@ -6276,6 +6747,14 @@ import-from@4.0.0, import-from@^4.0.0: resolved "https://registry.yarnpkg.com/import-from/-/import-from-4.0.0.tgz#2710b8d66817d232e16f4166e319248d3d5492e2" integrity sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ== +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -6477,6 +6956,11 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + is-generator-function@^1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" @@ -6734,6 +7218,59 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-instrument@^5.0.4: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-instrument@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz#91655936cf7380e4e473383081e38478b69993b1" + integrity sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw== + dependencies: + "@babel/core" "^7.23.9" + "@babel/parser" "^7.23.9" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.7" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" + integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + iterator.prototype@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" @@ -6750,6 +7287,344 @@ javascript-stringify@^2.0.1: resolved "https://registry.yarnpkg.com/javascript-stringify/-/javascript-stringify-2.1.0.tgz#27c76539be14d8bd128219a2d731b09337904e79" integrity sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg== +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== + dependencies: + execa "^5.0.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^1.0.0" + is-generator-fn "^2.0.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.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + chalk "^4.0.0" + create-jest "^29.7.0" + exit "^0.1.2" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" + +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.7.0" + "@jest/types" "^29.6.3" + babel-jest "^29.7.0" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.7.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.4" + parse-json "^5.2.0" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" + +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== + dependencies: + "@jest/types" "^29.6.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== + dependencies: + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.6.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== + +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== + dependencies: + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" + +jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.7.0" + jest-validate "^29.7.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== + 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" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + 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" + +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + 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" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + 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" + +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.7.0" + graceful-fs "^4.2.9" + 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.5.3" + +jest-util@^29.0.0, jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== + dependencies: + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.7.0" + string-length "^4.0.1" + jest-worker@^26.3.0: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" @@ -6768,6 +7643,26 @@ jest-worker@^27.4.5, jest-worker@^27.5.1: merge-stream "^2.0.0" supports-color "^8.0.0" +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== + dependencies: + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" + joi@^17.9.2: version "17.13.1" resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.1.tgz#9c7b53dc3b44dd9ae200255cc3b398874918a6ca" @@ -6923,6 +7818,11 @@ latest-version@^7.0.0: dependencies: tslib "^2.4.0" +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -7068,7 +7968,7 @@ lodash.maxby@^4.6.0: resolved "https://registry.yarnpkg.com/lodash.maxby/-/lodash.maxby-4.6.0.tgz#082240068f3c7a227aa00a8380e4f38cf0786e3d" integrity sha512-QfTqQTwzmKxLy7VZlbx2M/ipWv8DCQ2F5BI/MRxLharOQ5V78yMSuB+JE+EuUM22txYfj09R2Q7hUlEYj7KdNg== -lodash.memoize@^4.1.2: +lodash.memoize@4.x, lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== @@ -7165,6 +8065,25 @@ make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: dependencies: semver "^6.0.0" +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +make-error@1.x: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + map-age-cleaner@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" @@ -7742,7 +8661,7 @@ p-defer@^3.0.0: resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-3.0.0.tgz#d1dceb4ee9b2b604b1d94ffec83760175d4e6f83" integrity sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw== -p-limit@3.1.0, p-limit@^3.0.2: +p-limit@3.1.0, p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -7963,12 +8882,17 @@ picocolors@^1.0.0, picocolors@^1.0.1: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pkg-dir@^4.1.0: +pirates@^4.0.4: + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +pkg-dir@^4.1.0, pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== @@ -8284,6 +9208,15 @@ pretty-error@^2.1.2: lodash "^4.17.20" renderkid "^2.0.4" +pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -8301,7 +9234,7 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -prompts@^2.4.2: +prompts@^2.0.1, prompts@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== @@ -8403,6 +9336,11 @@ puppeteer@^22.9.0: devtools-protocol "0.0.1286932" puppeteer-core "22.10.0" +pure-rand@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" + integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== + qs@6.11.0: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" @@ -8525,6 +9463,11 @@ react-is@^16.13.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^18.0.0: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" + integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== + react-refresh@^0.14.0: version "0.14.2" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" @@ -8758,7 +9701,12 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.22.4: +resolve.exports@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" + integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== + +resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.4: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -8914,7 +9862,7 @@ semver@^5.7.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@^6.0.0, semver@^6.3.1: +semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== @@ -9205,6 +10153,14 @@ source-map-js@^1.2.0: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -9255,6 +10211,13 @@ stack-trace@^0.0.10: resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + stackframe@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" @@ -9285,6 +10248,14 @@ strict-uri-encode@^2.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + string-natural-compare@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" @@ -9396,6 +10367,11 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + strip-final-newline@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" @@ -9597,6 +10573,15 @@ terser@^5.2.0, terser@^5.26.0: commander "^2.20.0" source-map-support "~0.5.20" +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -9634,6 +10619,11 @@ tmp@^0.2.1: resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -9669,6 +10659,20 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-2.2.1.tgz#c5bf04a5bbec3fd118be4084461b3a27c4d796bf" integrity sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q== +ts-jest@^29.1.4: + version "29.1.4" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.4.tgz#26f8a55ce31e4d2ef7a1fd47dc7fa127e92793ef" + integrity sha512-YiHwDhSvCiItoAgsKtoLFCuakDzDsJ1DLDnSouTaTmdOcOwIkSzbLXduaQ6M5DRVhuZC/NYaaZ/mtHbWMv/S6Q== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^29.0.0" + json5 "^2.2.3" + lodash.memoize "4.x" + make-error "1.x" + semver "^7.5.3" + yargs-parser "^21.0.1" + tsconfig-paths@^3.15.0: version "3.15.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" @@ -9715,6 +10719,11 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" @@ -9962,6 +10971,15 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128" integrity sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw== +v8-to-istanbul@^9.0.1: + version "9.2.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" + integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + value-or-promise@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.12.tgz#0e5abfeec70148c78460a849f6b003ea7986f15c" @@ -9972,6 +10990,13 @@ vary@^1, vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + watchpack@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" @@ -10191,6 +11216,14 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +write-file-atomic@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + ws@8.17.0: version "8.17.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.0.tgz#d145d18eca2ed25aaf791a183903f7be5e295fea" @@ -10278,12 +11311,12 @@ yargs-parser@^18.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^21.1.1: +yargs-parser@^21.0.1, yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@17.7.2: +yargs@17.7.2, yargs@^17.3.1: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From 3e369d1c494636d9c530653f91f49a29db76b857 Mon Sep 17 00:00:00 2001 From: John Goodliff Date: Sun, 2 Jun 2024 22:34:11 -0600 Subject: [PATCH 04/15] Rename utilities.ts to utils.ts --- src/gatsby-node.ts | 2 +- src/index.ts | 2 +- src/logger.ts | 2 +- src/{utilities.ts => utils.ts} | 0 src/validator.ts | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename src/{utilities.ts => utils.ts} (100%) diff --git a/src/gatsby-node.ts b/src/gatsby-node.ts index 37b7fbd..2b12cf2 100644 --- a/src/gatsby-node.ts +++ b/src/gatsby-node.ts @@ -3,7 +3,7 @@ import { setDefaultOptions, setGatsbyCreatePageFunction } from './config'; import { generateImages } from './generator'; import { info, setReporter } from './logger'; import type { DefaultOptions } from './types'; -import { prettify } from './utilities'; +import { prettify } from './utils'; import { getPluginOptionsSchema, setJoi } from './validator'; // Save the reporter and createPage function for later use diff --git a/src/index.ts b/src/index.ts index e9aafc9..806aea7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,7 +6,7 @@ import { } from './config'; import { info } from './logger'; import type { DefaultOptions, JobOptions } from './types'; -import { prettify } from './utilities'; +import { prettify } from './utils'; import { validateJobOptions } from './validator'; // Public function for setting default options diff --git a/src/logger.ts b/src/logger.ts index eeefa87..837fe8d 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -1,6 +1,6 @@ import type { Reporter } from 'gatsby'; import { getDefaultOptions } from './config'; -import { getPackageName } from './utilities'; +import { getPackageName } from './utils'; const LOG_PREFIX = `${getPackageName()}: ` as const; diff --git a/src/utilities.ts b/src/utils.ts similarity index 100% rename from src/utilities.ts rename to src/utils.ts diff --git a/src/validator.ts b/src/validator.ts index c7987ec..96f14f4 100644 --- a/src/validator.ts +++ b/src/validator.ts @@ -1,6 +1,6 @@ import type { PluginOptionsSchemaJoi } from 'gatsby-plugin-utils'; import type { DefaultOptions, JobOptions } from './types'; -import { assertIsDefined } from './utilities'; +import { assertIsDefined } from './utils'; // Types type BooleanSchema = ReturnType; From 4acb5a3af91a85f9868e6d1419ed6eb6cdb088c4 Mon Sep 17 00:00:00 2001 From: John Goodliff Date: Sun, 2 Jun 2024 22:34:32 -0600 Subject: [PATCH 05/15] Add unit tests for utils.ts --- src/utils.test.ts | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/utils.test.ts diff --git a/src/utils.test.ts b/src/utils.test.ts new file mode 100644 index 0000000..f6fdb3c --- /dev/null +++ b/src/utils.test.ts @@ -0,0 +1,36 @@ +import { describe, expect, it } from '@jest/globals'; +import { assertIsDefined, getPackageName, prettify } from './utils'; + +describe('assertIsDefined', () => { + it('should throw an error if value is undefined', () => { + expect(() => assertIsDefined(undefined)).toThrow( + 'Expected value to be defined, but it was not', + ); + }); + + it('should not throw an error if value is defined', () => { + expect(() => assertIsDefined('defined value')).not.toThrow(); + }); +}); + +describe('getPackageName', () => { + it('should return the package name from package.json', () => { + expect(getPackageName()).toBe('gatsby-plugin-component-to-image'); + }); +}); + +describe('prettify', () => { + it('should format an object as a human-readable string', () => { + const obj = { + name: 'Timmy', + size: 'chonky', + color: 'orange', + }; + const expectedOutput = `{ + "name": "Timmy", + "size": "chonky", + "color": "orange" +}`; + expect(prettify(obj)).toBe(expectedOutput); + }); +}); From bfb7aa5b5df147dda9f794ac1c4772f3587d96ac Mon Sep 17 00:00:00 2001 From: John Goodliff Date: Mon, 3 Jun 2024 17:57:22 -0600 Subject: [PATCH 06/15] Disable ts-jest TypeScript errors --- jest.config.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/jest.config.js b/jest.config.js index d7232d3..53ced26 100644 --- a/jest.config.js +++ b/jest.config.js @@ -6,4 +6,14 @@ module.exports = { collectCoverageFrom: ['src/**/*.ts'], coverageDirectory: 'coverage', coverageProvider: 'v8', + transform: { + '^.+\\.ts$': [ + 'ts-jest', + { + diagnostics: { + warnOnly: true, + }, + }, + ], + }, }; From 6f5baf8f8e5526c80fef58dcd9f067635337cc47 Mon Sep 17 00:00:00 2001 From: John Goodliff Date: Mon, 3 Jun 2024 17:57:38 -0600 Subject: [PATCH 07/15] Add Joi as dev dep --- package.json | 1 + yarn.lock | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 6243508..35eaf66 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "gatsby": "^5.0.0-next", "gatsby-plugin-utils": "^4.0.0", "jest": "^29.7.0", + "joi": "^17.13.1", "ts-jest": "^29.1.4", "typescript": "^5.4.5" }, diff --git a/yarn.lock b/yarn.lock index bce082e..e919473 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7663,7 +7663,7 @@ jest@^29.7.0: import-local "^3.0.2" jest-cli "^29.7.0" -joi@^17.9.2: +joi@^17.13.1, joi@^17.9.2: version "17.13.1" resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.1.tgz#9c7b53dc3b44dd9ae200255cc3b398874918a6ca" integrity sha512-vaBlIKCyo4FCUtCm7Eu4QZd/q02bWcxfUO6YSXAZOWF6gzcLBeba8kwotUdYJjDLW8Cz8RywsSOqiNJZW0mNvg== From 4207bed8ecf2413ae327373329100aea872d183a Mon Sep 17 00:00:00 2001 From: John Goodliff Date: Mon, 3 Jun 2024 17:58:11 -0600 Subject: [PATCH 08/15] Add example values to Joi schemas --- src/validator.ts | 60 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/src/validator.ts b/src/validator.ts index 96f14f4..eacbfd1 100644 --- a/src/validator.ts +++ b/src/validator.ts @@ -70,31 +70,59 @@ export function setJoi(newJoi: PluginOptionsSchemaJoi) { joi = newJoi; schemas = { - verbose: joi.boolean().label('verbose'), - pagePath: joi.string().required().label('pagePath'), - imagePath: joi.string().required().label('imagePath'), - component: joi.string().label('component'), - context: joi.object().label('context'), - size: joi.object({ - width: joi.number().integer().min(MIN_SIZE).max(MAX_SIZE).label('width'), - height: joi - .number() - .integer() - .min(MIN_SIZE) - .max(MAX_SIZE) - .label('height'), + verbose: joi.boolean().label('verbose').example(false), + pagePath: joi + .string() + .required() + .label('pagePath') + .example('/__generated/open-graph/blog-post-1'), + imagePath: joi + .string() + .required() + .label('imagePath') + .example('/images/open-graph/blog-post-1.png'), + component: joi + .string() + .label('component') + .example('./src/templates/blog-post.tsx'), + context: joi.object().label('context').example({ + title: 'Blog Post 1', + description: 'This is a blog post', + postDate: '2022-01-01', }), + size: joi + .object({ + width: joi + .number() + .integer() + .min(MIN_SIZE) + .max(MAX_SIZE) + .label('width') + .example(1200), + height: joi + .number() + .integer() + .min(MIN_SIZE) + .max(MAX_SIZE) + .label('height') + .example(630), + }) + .label('size') + .example({ width: 1200, height: 630 }), type: joi .string() .valid(...FILE_TYPES) - .label('type'), + .lowercase() + .label('type') + .example('png'), quality: joi .number() .integer() .min(MIN_QUALITY) .max(MAX_QUALITY) - .label('quality'), - optimizeForSpeed: joi.boolean().label('optimizeForSpeed'), + .label('quality') + .example(95), + optimizeForSpeed: joi.boolean().label('optimizeForSpeed').example(false), }; } From 0859e5f88dee5b8ff838d2e43641688b6c1eb13f Mon Sep 17 00:00:00 2001 From: John Goodliff Date: Mon, 3 Jun 2024 17:59:24 -0600 Subject: [PATCH 09/15] Add unit tests for getPluginOptionsSchema() --- src/validator.test.ts | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/validator.test.ts diff --git a/src/validator.test.ts b/src/validator.test.ts new file mode 100644 index 0000000..6983e8a --- /dev/null +++ b/src/validator.test.ts @@ -0,0 +1,38 @@ +import { beforeAll, describe, expect, it } from '@jest/globals'; +import type { PluginOptionsSchemaJoi } from 'gatsby-plugin-utils'; +import Joi from 'joi'; +import type { DefaultOptions } from './types'; +import { getPluginOptionsSchema, setJoi } from './validator'; + +const DEFAULT_OPTIONS: DefaultOptions = { + verbose: false, + component: undefined, + context: {}, + size: { + width: 1200, + height: 630, + }, + type: 'png', + quality: undefined, + optimizeForSpeed: false, +}; + +// As per https://github.com/jestjs/jest/issues/7997#issuecomment-1455052585, +// the `beforeAll` hook needs to be outside of the `describe` block, +// otherwise it will not work as expected. +beforeAll(() => { + // Set up the joi object + // Gatsby's PluginOptionsSchemaJoi type has an additional `subPlugins` property that we don't need + setJoi(Joi as unknown as PluginOptionsSchemaJoi); +}); + +describe('Validator', () => { + describe('getPluginOptionsSchema', () => { + it.concurrent('should return the plugin options schema', async () => { + const schema = getPluginOptionsSchema(); + + expect(schema).toBeDefined(); + expect(schema).toHaveProperty('type', 'object'); + }); + }); +}); From 8d3e10f770bfc39a1aa1672f85f3c6f3a4d52e7f Mon Sep 17 00:00:00 2001 From: John Goodliff Date: Mon, 3 Jun 2024 18:00:48 -0600 Subject: [PATCH 10/15] Add unit tests for validateDefaultOptions() --- src/validator.test.ts | 626 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 625 insertions(+), 1 deletion(-) diff --git a/src/validator.test.ts b/src/validator.test.ts index 6983e8a..62ced29 100644 --- a/src/validator.test.ts +++ b/src/validator.test.ts @@ -2,7 +2,11 @@ import { beforeAll, describe, expect, it } from '@jest/globals'; import type { PluginOptionsSchemaJoi } from 'gatsby-plugin-utils'; import Joi from 'joi'; import type { DefaultOptions } from './types'; -import { getPluginOptionsSchema, setJoi } from './validator'; +import { + getPluginOptionsSchema, + setJoi, + validateDefaultOptions, +} from './validator'; const DEFAULT_OPTIONS: DefaultOptions = { verbose: false, @@ -35,4 +39,624 @@ describe('Validator', () => { expect(schema).toHaveProperty('type', 'object'); }); }); + + describe('validateDefaultOptions', () => { + it.concurrent( + 'should replace an empty object with default options', + async () => { + const inputDefaultOptions = {}; + const validatedOptions = validateDefaultOptions( + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + + expect(validatedOptions).toBeDefined(); + expect(validatedOptions).toEqual(DEFAULT_OPTIONS); + }, + ); + + it.concurrent( + 'should replace undefined options with default options', + async () => { + const inputDefaultOptions = { + verbose: undefined, + component: undefined, + context: undefined, + size: undefined, + type: undefined, + quality: undefined, + optimizeForSpeed: undefined, + }; + const validatedOptions = validateDefaultOptions( + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + + expect(validatedOptions).toBeDefined(); + expect(validatedOptions).toEqual(DEFAULT_OPTIONS); + }, + ); + + describe('verbose validation', () => { + const PROPERTY_NAME = 'verbose'; + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: 'bruh', + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should convert string ${PROPERTY_NAME} to boolean`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: 'true', + }; + + expect(() => { + const validatedOptions = validateDefaultOptions( + // @ts-expect-error: Testing invalid type + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual(true); + }).not.toThrowError(); + }, + ); + + it.concurrent( + `should not throw an error for boolean ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: true, + }; + + expect(() => { + const validatedOptions = validateDefaultOptions( + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual( + inputDefaultOptions[PROPERTY_NAME], + ); + }).not.toThrowError(); + }, + ); + }); + + describe('component validation', () => { + const PROPERTY_NAME = 'component'; + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: 42, + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for empty ${PROPERTY_NAME} string`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: '', + }; + + expect(() => { + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should not throw an error for non-empty ${PROPERTY_NAME} string`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: 'example-component', + }; + + expect(() => { + const validatedOptions = validateDefaultOptions( + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual( + inputDefaultOptions[PROPERTY_NAME], + ); + }).not.toThrowError(); + }, + ); + }); + + describe('context validation', () => { + const PROPERTY_NAME = 'context'; + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: 'invalid' as const, + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should not throw an error for valid ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: { + example: 'value', + }, + }; + + expect(() => { + const validatedOptions = validateDefaultOptions( + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual( + inputDefaultOptions[PROPERTY_NAME], + ); + }).not.toThrowError(); + }, + ); + }); + + describe('size validation', () => { + const PROPERTY_NAME = 'size'; + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: 'invalid' as const, + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should not throw an error for valid ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: { + width: 1200, + height: 630, + }, + }; + + expect(() => { + const validatedOptions = validateDefaultOptions( + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual( + inputDefaultOptions[PROPERTY_NAME], + ); + }).not.toThrowError(); + }, + ); + + describe('width validation', () => { + const PROPERTY_NAME = 'width'; + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputDefaultOptions = { + size: { + width: 'bruh', + height: 630, + }, + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for non-integer ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + size: { + width: Math.PI, + height: 630, + }, + }; + + expect(() => { + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} below the minimum size`, + async () => { + const inputDefaultOptions = { + size: { + width: 0, + height: 630, + }, + }; + + expect(() => { + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} above the maximum size`, + async () => { + const inputDefaultOptions = { + size: { + width: 20000, + height: 630, + }, + }; + + expect(() => { + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should convert string ${PROPERTY_NAME} to number`, + async () => { + const inputDefaultOptions = { + size: { + width: '1337', + height: 630, + }, + }; + + expect(() => { + const validatedOptions = validateDefaultOptions( + // @ts-expect-error: Testing invalid type + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions.size[PROPERTY_NAME]).toEqual(1337); + }).not.toThrowError(); + }, + ); + }); + + describe('height validation', () => { + const PROPERTY_NAME = 'height'; + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputDefaultOptions = { + size: { + width: 1200, + height: 'bruh', + }, + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for non-integer ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + size: { + width: 1200, + height: Math.PI, + }, + }; + + expect(() => { + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} below the minimum size`, + async () => { + const inputDefaultOptions = { + size: { + width: 1200, + height: 0, + }, + }; + + expect(() => { + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} above the maximum size`, + async () => { + const inputDefaultOptions = { + size: { + width: 1200, + height: 20000, + }, + }; + + expect(() => { + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should convert string ${PROPERTY_NAME} to number`, + async () => { + const inputDefaultOptions = { + size: { + width: 1200, + height: '1337', + }, + }; + + expect(() => { + const validatedOptions = validateDefaultOptions( + // @ts-expect-error: Testing invalid type + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions.size[PROPERTY_NAME]).toEqual(1337); + }).not.toThrowError(); + }, + ); + }); + }); + + describe('type validation', () => { + const PROPERTY_NAME = 'type'; + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: 42, + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for invalid ${PROPERTY_NAME} option`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: 'invalid' as const, + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should convert string ${PROPERTY_NAME} to lowercase`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: 'PNG' as const, + }; + + expect(() => { + const validatedOptions = validateDefaultOptions( + // @ts-expect-error: Testing invalid type + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual('png'); + }).not.toThrowError(); + }, + ); + + it.concurrent( + `should not throw an error for valid ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: 'png' as const, + }; + + expect(() => { + const validatedOptions = validateDefaultOptions( + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual( + inputDefaultOptions[PROPERTY_NAME], + ); + }).not.toThrowError(); + }, + ); + }); + + describe('quality validation', () => { + const PROPERTY_NAME = 'quality'; + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: 'bruh', + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for non-integer ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: Math.PI, + }; + + expect(() => { + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} below the minimum quality`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: -1, + }; + + expect(() => { + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} above the maximum quality`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: 101, + }; + + expect(() => { + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should convert string ${PROPERTY_NAME} to number`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: '95', + }; + + expect(() => { + const validatedOptions = validateDefaultOptions( + // @ts-expect-error: Testing invalid type + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual(95); + }).not.toThrowError(); + }, + ); + + it.concurrent( + `should not throw an error for valid ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: 50, + }; + + expect(() => { + const validatedOptions = validateDefaultOptions( + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual( + inputDefaultOptions[PROPERTY_NAME], + ); + }).not.toThrowError(); + }, + ); + }); + + describe('optimizeForSpeed validation', () => { + const PROPERTY_NAME = 'optimizeForSpeed'; + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: 'bruh', + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateDefaultOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should convert string ${PROPERTY_NAME} to boolean`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: 'true', + }; + + expect(() => { + const validatedOptions = validateDefaultOptions( + // @ts-expect-error: Testing invalid type + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual(true); + }).not.toThrowError(); + }, + ); + + it.concurrent( + `should not throw an error for boolean ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + [PROPERTY_NAME]: true, + }; + + expect(() => { + const validatedOptions = validateDefaultOptions( + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual( + inputDefaultOptions[PROPERTY_NAME], + ); + }).not.toThrowError(); + }, + ); + }); + }); }); From 8e54b4fdaba136e2c8ddd03051ac92a75c9e2219 Mon Sep 17 00:00:00 2001 From: John Goodliff Date: Mon, 3 Jun 2024 21:24:12 -0600 Subject: [PATCH 11/15] Make quality optional in job options --- src/validator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validator.ts b/src/validator.ts index eacbfd1..8e00ad1 100644 --- a/src/validator.ts +++ b/src/validator.ts @@ -173,7 +173,7 @@ export function validateJobOptions( context: (schema) => schema, size: (schema) => schema.required(), type: (schema) => schema.required(), - quality: (schema) => schema.required(), + quality: (schema) => schema, optimizeForSpeed: (schema) => schema.required(), }; From 1c62c94c66fe70ea7a241ce95b900120fb6ab5f3 Mon Sep 17 00:00:00 2001 From: John Goodliff Date: Mon, 3 Jun 2024 21:25:18 -0600 Subject: [PATCH 12/15] Add unit tests for validateJobOptions() --- src/validator.test.ts | 755 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 744 insertions(+), 11 deletions(-) diff --git a/src/validator.test.ts b/src/validator.test.ts index 62ced29..efb7a8a 100644 --- a/src/validator.test.ts +++ b/src/validator.test.ts @@ -6,19 +6,37 @@ import { getPluginOptionsSchema, setJoi, validateDefaultOptions, + validateJobOptions, } from './validator'; +const VALID_PAGE_PATH = 'example-page'; +const VALID_IMAGE_PATH = 'example-image.png'; +const VALID_COMPONENT = 'example-component'; +const VALID_CONTEXT = { + title: 'Blog Post 1', + description: 'This is a blog post', + postDate: '2022-01-01', +}; +const VALID_SIZE = { + width: 1200, + height: 630, +}; +const VALID_TYPE = 'png'; +const VALID_QUALITY = 95; +const VALID_OPTIMIZE_FOR_SPEED = false; +const VALID_REQUIRED_JOB_OPTIONS = { + pagePath: VALID_PAGE_PATH, + imagePath: VALID_IMAGE_PATH, + component: VALID_COMPONENT, +}; const DEFAULT_OPTIONS: DefaultOptions = { verbose: false, component: undefined, context: {}, - size: { - width: 1200, - height: 630, - }, - type: 'png', + size: VALID_SIZE, + type: VALID_TYPE, quality: undefined, - optimizeForSpeed: false, + optimizeForSpeed: VALID_OPTIMIZE_FOR_SPEED, }; // As per https://github.com/jestjs/jest/issues/7997#issuecomment-1455052585, @@ -166,7 +184,7 @@ describe('Validator', () => { `should not throw an error for non-empty ${PROPERTY_NAME} string`, async () => { const inputDefaultOptions = { - [PROPERTY_NAME]: 'example-component', + [PROPERTY_NAME]: VALID_COMPONENT, }; expect(() => { @@ -189,7 +207,7 @@ describe('Validator', () => { `should throw an error for ${PROPERTY_NAME} of invalid type`, async () => { const inputDefaultOptions = { - [PROPERTY_NAME]: 'invalid' as const, + [PROPERTY_NAME]: 'invalid', }; expect(() => { @@ -203,9 +221,7 @@ describe('Validator', () => { `should not throw an error for valid ${PROPERTY_NAME}`, async () => { const inputDefaultOptions = { - [PROPERTY_NAME]: { - example: 'value', - }, + [PROPERTY_NAME]: VALID_CONTEXT, }; expect(() => { @@ -659,4 +675,721 @@ describe('Validator', () => { ); }); }); + + describe('validateJobOptions', () => { + it.concurrent( + 'should not throw an error for valid job options', + async () => { + expect(() => { + const validatedOptions = validateJobOptions( + VALID_REQUIRED_JOB_OPTIONS, + DEFAULT_OPTIONS, + ); + expect(validatedOptions.pagePath).toEqual( + VALID_REQUIRED_JOB_OPTIONS.pagePath, + ); + expect(validatedOptions.imagePath).toEqual( + VALID_REQUIRED_JOB_OPTIONS.imagePath, + ); + expect(validatedOptions.component).toEqual( + VALID_REQUIRED_JOB_OPTIONS.component, + ); + }).not.toThrowError(); + }, + ); + + describe('pagePath validation', () => { + const PROPERTY_NAME = 'pagePath'; + + it.concurrent( + `should throw an error for missing ${PROPERTY_NAME}`, + async () => { + const inputJobOptions = { + imagePath: VALID_IMAGE_PATH, + component: VALID_COMPONENT, + }; + + expect(() => { + validateJobOptions(inputJobOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputJobOptions = { + pagePath: 42, + imagePath: VALID_IMAGE_PATH, + component: VALID_COMPONENT, + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateJobOptions(inputJobOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for empty ${PROPERTY_NAME} string`, + async () => { + const inputJobOptions = { + pagePath: '', + imagePath: VALID_IMAGE_PATH, + component: VALID_COMPONENT, + }; + + expect(() => { + validateJobOptions(inputJobOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + }); + + describe('imagePath validation', () => { + const PROPERTY_NAME = 'imagePath'; + + it.concurrent( + `should throw an error for missing ${PROPERTY_NAME}`, + async () => { + const inputJobOptions = { + pagePath: VALID_PAGE_PATH, + component: VALID_COMPONENT, + }; + + expect(() => { + validateJobOptions(inputJobOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputJobOptions = { + pagePath: VALID_PAGE_PATH, + imagePath: 42, + component: VALID_COMPONENT, + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateJobOptions(inputJobOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for empty ${PROPERTY_NAME} string`, + async () => { + const inputJobOptions = { + pagePath: VALID_PAGE_PATH, + imagePath: '', + component: VALID_COMPONENT, + }; + + expect(() => { + validateJobOptions(inputJobOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + }); + + describe('component validation', () => { + const PROPERTY_NAME = 'component'; + + it.concurrent( + `should throw an error for missing ${PROPERTY_NAME}`, + async () => { + const inputJobOptions = { + pagePath: VALID_PAGE_PATH, + imagePath: VALID_IMAGE_PATH, + }; + + expect(() => { + validateJobOptions(inputJobOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputJobOptions = { + pagePath: VALID_PAGE_PATH, + imagePath: VALID_IMAGE_PATH, + component: 42, + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateJobOptions(inputJobOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for empty ${PROPERTY_NAME} string`, + async () => { + const inputJobOptions = { + pagePath: VALID_PAGE_PATH, + imagePath: VALID_IMAGE_PATH, + component: '', + }; + + expect(() => { + validateJobOptions(inputJobOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + }); + + describe('context validation', () => { + const PROPERTY_NAME = 'context'; + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputJobOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + context: 'invalid', + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateJobOptions(inputJobOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should not throw an error for valid ${PROPERTY_NAME}`, + async () => { + const inputJobOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + context: VALID_CONTEXT, + }; + + expect(() => { + const validatedOptions = validateJobOptions( + inputJobOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual( + inputJobOptions[PROPERTY_NAME], + ); + }).not.toThrowError(); + }, + ); + }); + + describe('size validation', () => { + const PROPERTY_NAME = 'size'; + + it.concurrent( + `should throw an error for missing ${PROPERTY_NAME}`, + async () => { + expect(() => { + // @ts-expect-error: Testing invalid type + validateJobOptions(VALID_REQUIRED_JOB_OPTIONS, { + ...VALID_REQUIRED_JOB_OPTIONS, + type: VALID_TYPE, + quality: VALID_QUALITY, + optimizeForSpeed: VALID_OPTIMIZE_FOR_SPEED, + }); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + [PROPERTY_NAME]: 'invalid' as const, + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should not throw an error for valid ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + [PROPERTY_NAME]: { + width: 1200, + height: 630, + }, + }; + + expect(() => { + const validatedOptions = validateJobOptions( + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual( + inputDefaultOptions[PROPERTY_NAME], + ); + }).not.toThrowError(); + }, + ); + + describe('width validation', () => { + const PROPERTY_NAME = 'width'; + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + size: { + width: 'bruh', + height: 630, + }, + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for non-integer ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + size: { + width: Math.PI, + height: 630, + }, + }; + + expect(() => { + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} below the minimum size`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + size: { + width: 0, + height: 630, + }, + }; + + expect(() => { + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} above the maximum size`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + size: { + width: 20000, + height: 630, + }, + }; + + expect(() => { + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should convert string ${PROPERTY_NAME} to number`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + size: { + width: '1337', + height: 630, + }, + }; + + expect(() => { + const validatedOptions = validateJobOptions( + // @ts-expect-error: Testing invalid type + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions.size[PROPERTY_NAME]).toEqual(1337); + }).not.toThrowError(); + }, + ); + }); + + describe('height validation', () => { + const PROPERTY_NAME = 'height'; + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + size: { + width: 1200, + height: 'bruh', + }, + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for non-integer ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + size: { + width: 1200, + height: Math.PI, + }, + }; + + expect(() => { + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} below the minimum size`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + size: { + width: 1200, + height: 0, + }, + }; + + expect(() => { + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} above the maximum size`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + size: { + width: 1200, + height: 20000, + }, + }; + + expect(() => { + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should convert string ${PROPERTY_NAME} to number`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + size: { + width: 1200, + height: '1337', + }, + }; + + expect(() => { + const validatedOptions = validateJobOptions( + // @ts-expect-error: Testing invalid type + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions.size[PROPERTY_NAME]).toEqual(1337); + }).not.toThrowError(); + }, + ); + }); + }); + + describe('type validation', () => { + const PROPERTY_NAME = 'type'; + + it.concurrent( + `should throw an error for missing ${PROPERTY_NAME}`, + async () => { + expect(() => { + // @ts-expect-error: Testing invalid type + validateJobOptions(VALID_REQUIRED_JOB_OPTIONS, { + ...VALID_REQUIRED_JOB_OPTIONS, + size: VALID_SIZE, + quality: VALID_QUALITY, + optimizeForSpeed: VALID_OPTIMIZE_FOR_SPEED, + }); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + [PROPERTY_NAME]: 42, + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for invalid ${PROPERTY_NAME} option`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + [PROPERTY_NAME]: 'invalid' as const, + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should convert string ${PROPERTY_NAME} to lowercase`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + [PROPERTY_NAME]: 'PNG' as const, + }; + + expect(() => { + const validatedOptions = validateJobOptions( + // @ts-expect-error: Testing invalid type + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual('png'); + }).not.toThrowError(); + }, + ); + + it.concurrent( + `should not throw an error for valid ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + [PROPERTY_NAME]: 'png' as const, + }; + + expect(() => { + const validatedOptions = validateJobOptions( + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual( + inputDefaultOptions[PROPERTY_NAME], + ); + }).not.toThrowError(); + }, + ); + }); + + describe('quality validation', () => { + const PROPERTY_NAME = 'quality'; + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + [PROPERTY_NAME]: 'bruh', + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for non-integer ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + [PROPERTY_NAME]: Math.PI, + }; + + expect(() => { + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} below the minimum quality`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + [PROPERTY_NAME]: -1, + }; + + expect(() => { + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} above the maximum quality`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + [PROPERTY_NAME]: 101, + }; + + expect(() => { + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should convert string ${PROPERTY_NAME} to number`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + [PROPERTY_NAME]: '95', + }; + + expect(() => { + const validatedOptions = validateJobOptions( + // @ts-expect-error: Testing invalid type + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual(95); + }).not.toThrowError(); + }, + ); + + it.concurrent( + `should not throw an error for valid ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + [PROPERTY_NAME]: 50, + }; + + expect(() => { + const validatedOptions = validateJobOptions( + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual( + inputDefaultOptions[PROPERTY_NAME], + ); + }).not.toThrowError(); + }, + ); + }); + + describe('optimizeForSpeed validation', () => { + const PROPERTY_NAME = 'optimizeForSpeed'; + + it.concurrent( + `should throw an error for missing ${PROPERTY_NAME}`, + async () => { + expect(() => { + // @ts-expect-error: Testing invalid type + validateJobOptions(VALID_REQUIRED_JOB_OPTIONS, { + ...VALID_REQUIRED_JOB_OPTIONS, + size: VALID_SIZE, + type: VALID_TYPE, + quality: VALID_QUALITY, + }); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should throw an error for ${PROPERTY_NAME} of invalid type`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + [PROPERTY_NAME]: 'bruh', + }; + + expect(() => { + // @ts-expect-error: Testing invalid type + validateJobOptions(inputDefaultOptions, DEFAULT_OPTIONS); + }).toThrowError(PROPERTY_NAME); + }, + ); + + it.concurrent( + `should convert string ${PROPERTY_NAME} to boolean`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + [PROPERTY_NAME]: 'true', + }; + + expect(() => { + const validatedOptions = validateJobOptions( + // @ts-expect-error: Testing invalid type + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual(true); + }).not.toThrowError(); + }, + ); + + it.concurrent( + `should not throw an error for boolean ${PROPERTY_NAME}`, + async () => { + const inputDefaultOptions = { + ...VALID_REQUIRED_JOB_OPTIONS, + [PROPERTY_NAME]: true, + }; + + expect(() => { + const validatedOptions = validateJobOptions( + inputDefaultOptions, + DEFAULT_OPTIONS, + ); + expect(validatedOptions[PROPERTY_NAME]).toEqual( + inputDefaultOptions[PROPERTY_NAME], + ); + }).not.toThrowError(); + }, + ); + }); + }); }); From d7dcc04129860e0e1e314528e5e24ae921298f7f Mon Sep 17 00:00:00 2001 From: John Goodliff Date: Mon, 3 Jun 2024 21:57:53 -0600 Subject: [PATCH 13/15] Replace unknown cast in validator.test.ts with ts-expect-error directive --- src/validator.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/validator.test.ts b/src/validator.test.ts index efb7a8a..24fa9da 100644 --- a/src/validator.test.ts +++ b/src/validator.test.ts @@ -44,8 +44,8 @@ const DEFAULT_OPTIONS: DefaultOptions = { // otherwise it will not work as expected. beforeAll(() => { // Set up the joi object - // Gatsby's PluginOptionsSchemaJoi type has an additional `subPlugins` property that we don't need - setJoi(Joi as unknown as PluginOptionsSchemaJoi); + // @ts-expect-error: Gatsby's PluginOptionsSchemaJoi type has an additional `subPlugins` property that we don't need + setJoi(Joi); }); describe('Validator', () => { From a711b12c90a5a5ed85f127da3a6ccdbb1cdbacfa Mon Sep 17 00:00:00 2001 From: John Goodliff Date: Mon, 3 Jun 2024 21:58:52 -0600 Subject: [PATCH 14/15] Add unit tests for info(), success(), warn(), error(), and panic() --- src/logger.test.ts | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/logger.test.ts diff --git a/src/logger.test.ts b/src/logger.test.ts new file mode 100644 index 0000000..5d748db --- /dev/null +++ b/src/logger.test.ts @@ -0,0 +1,95 @@ +import { beforeEach, describe, expect, it, jest } from '@jest/globals'; +import type { Reporter } from 'gatsby'; +import Joi from 'joi'; +import { setDefaultOptions } from './config'; +import { error, info, panic, setReporter, success, warn } from './logger'; +import { setJoi } from './validator'; + +describe('info', () => { + let reporter: Reporter; + + beforeEach(() => { + // @ts-expect-error: Reporter is intentially not fully mocked + reporter = { + info: jest.fn(), + }; + // @ts-expect-error: Gatsby's PluginOptionsSchemaJoi type has an additional `subPlugins` property that we don't need + setJoi(Joi); + setDefaultOptions({ verbose: false }); + setReporter(reporter); + }); + + it('should log an info message when verbose is true', () => { + setDefaultOptions({ verbose: true }); + info('This is an info message'); + expect(reporter.info).toHaveBeenCalledWith( + 'gatsby-plugin-component-to-image: This is an info message', + ); + }); + + it('should not log an info message when verbose is false', () => { + setDefaultOptions({ verbose: false }); + info('This is an info message'); + expect(reporter.info).not.toHaveBeenCalled(); + }); +}); + +describe('success', () => { + it('should log a success message', () => { + const reporter = { + success: jest.fn(), + }; + + // @ts-expect-error: Reporter is intentially not fully mocked + setReporter(reporter); + success('This is a success message'); + expect(reporter.success).toHaveBeenCalledWith( + 'gatsby-plugin-component-to-image: This is a success message', + ); + }); +}); + +describe('warn', () => { + it('should log a warning message', () => { + const reporter = { + warn: jest.fn(), + }; + + // @ts-expect-error: Reporter is intentially not fully mocked + setReporter(reporter); + warn('This is a warning message'); + expect(reporter.warn).toHaveBeenCalledWith( + 'gatsby-plugin-component-to-image: This is a warning message', + ); + }); +}); + +describe('error', () => { + it('should log an error message', () => { + const reporter = { + error: jest.fn(), + }; + + // @ts-expect-error: Reporter is intentially not fully mocked + setReporter(reporter); + error('This is an error message'); + expect(reporter.error).toHaveBeenCalledWith( + 'gatsby-plugin-component-to-image: This is an error message', + ); + }); +}); + +describe('panic', () => { + it('should log a panic message', () => { + const reporter = { + panic: jest.fn(), + }; + + // @ts-expect-error: Reporter is intentially not fully mocked + setReporter(reporter); + panic('This is a panic message'); + expect(reporter.panic).toHaveBeenCalledWith( + 'gatsby-plugin-component-to-image: This is a panic message', + ); + }); +}); From 7e1a30f2a5325c9428d5ebf78e707e37e80c5bdd Mon Sep 17 00:00:00 2001 From: John Goodliff Date: Mon, 3 Jun 2024 22:07:47 -0600 Subject: [PATCH 15/15] Add unit tests for startActivity(), updateActivity(), and endActivity() --- src/logger.test.ts | 58 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/src/logger.test.ts b/src/logger.test.ts index 5d748db..cf31b36 100644 --- a/src/logger.test.ts +++ b/src/logger.test.ts @@ -1,8 +1,25 @@ -import { beforeEach, describe, expect, it, jest } from '@jest/globals'; +import { + beforeAll, + beforeEach, + describe, + expect, + it, + jest, +} from '@jest/globals'; import type { Reporter } from 'gatsby'; import Joi from 'joi'; import { setDefaultOptions } from './config'; -import { error, info, panic, setReporter, success, warn } from './logger'; +import { + endActivity, + error, + info, + panic, + setReporter, + startActivity, + success, + updateActivity, + warn, +} from './logger'; import { setJoi } from './validator'; describe('info', () => { @@ -93,3 +110,40 @@ describe('panic', () => { ); }); }); + +describe('startActivity, updateActivity, and endActivity', () => { + const reporter = { + activityTimer: jest.fn(), + }; + const activity = { + start: jest.fn(), + setStatus: jest.fn(), + end: jest.fn(), + }; + + beforeAll(() => { + reporter.activityTimer.mockReturnValue(activity); + + // @ts-expect-error: Reporter is intentially not fully mocked + setReporter(reporter); + }); + + it('startActivity should start an activity', () => { + startActivity('Timer'); + expect(reporter.activityTimer).toHaveBeenCalledWith( + 'gatsby-plugin-component-to-image: Timer', + ); + expect(activity.start).toHaveBeenCalled(); + }); + + it('updateActivity should update the status of an activity', () => { + updateActivity('Status'); + expect(activity.setStatus).toHaveBeenCalledWith('Status'); + }); + + it('endActivity should end an activity', () => { + endActivity(); + expect(activity.setStatus).toHaveBeenCalledWith(''); + expect(activity.end).toHaveBeenCalled(); + }); +});