From 8b06636e7a784a14a309f89cce7eb9c628e2ee22 Mon Sep 17 00:00:00 2001 From: Roberto Mosca Date: Mon, 26 Jun 2023 18:29:23 +0200 Subject: [PATCH 1/5] Add Jest tests --- .github/workflows/build-and-test.yml | 27 + jest.config.cjs | 9 + jest.setup.js | 4 + package.json | 11 +- pnpm-lock.yaml | 1665 ++++++++++++++++++++++++- src/api/js-api.domainsElement.test.js | 43 + src/api/js-api.imo.test.js | 44 + src/api/js-api.test.js | 15 + 8 files changed, 1798 insertions(+), 20 deletions(-) create mode 100644 .github/workflows/build-and-test.yml create mode 100644 jest.config.cjs create mode 100644 jest.setup.js create mode 100644 src/api/js-api.domainsElement.test.js create mode 100644 src/api/js-api.imo.test.js create mode 100644 src/api/js-api.test.js diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 0000000..8c97659 --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,27 @@ +name: Build and Test + +on: + push: + branches: main + pull_request: + branches: "*" + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - uses: actions/setup-node@v2 + with: + node-version: "16" + - uses: pnpm/action-setup@v2.0.1 + with: + version: 8.4.0 + - run: git checkout main && git checkout $GITHUB_SHA + - run: pnpm install --frozen-lockfile + - run: pnpm run build + - run: pnpm run lint + - run: pnpm run test-jest diff --git a/jest.config.cjs b/jest.config.cjs new file mode 100644 index 0000000..a0d8ccb --- /dev/null +++ b/jest.config.cjs @@ -0,0 +1,9 @@ +/** @type {import('jest').Config} */ +const config = { + testEnvironment: "jsdom", + resetMocks: true, + restoreMocks: true, + setupFilesAfterEnv: ["/jest.setup.js"], +}; + +module.exports = config; diff --git a/jest.setup.js b/jest.setup.js new file mode 100644 index 0000000..7bdb500 --- /dev/null +++ b/jest.setup.js @@ -0,0 +1,4 @@ +import { TextEncoder, TextDecoder } from "util"; + +global.TextEncoder = TextEncoder; +global.TextDecoder = TextDecoder; diff --git a/package.json b/package.json index 359a717..f2ac72a 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "check-format": "prettier --check src", "watch": "cross-env NODE_ENV=development rollup -c --watch", "copy-test-files": "copyfiles test/**/* dist -f", + "test-jest": "jest", "test-serve": "serve .", "test-embed-serve": "serve . -l 3333", "test": "concurrently pnpm:watch pnpm:copy-test-files pnpm:test-serve pnpm:test-embed-serve", @@ -44,16 +45,20 @@ "@rollup/plugin-babel": "^5.3.0", "@rollup/plugin-node-resolve": "^13.0.2", "concurrently": "^6.2.0", - "copyfiles": "^2.3.0", - "cross-env": "^7.0.2", + "copyfiles": "^2.4.1", + "cross-env": "^7.0.3", "eslint": "^7.31.0", "eslint-config-important-stuff": "^1.1.0", "eslint-plugin-es5": "^1.5.0", - "husky": "^7.0.0", + "husky": "^7.0.1", + "jest": "^29.5.0", + "jest-cli": "^29.5.0", + "jest-environment-jsdom": "^29.5.0", "postcss": "^8.3.5", "preact": "^10.5.14", "prettier": "^2.3.2", "pretty-quick": "^3.1.1", + "regenerator-runtime": "^0.13.11", "rimraf": "^3.0.2", "rollup": "^2.53.2", "rollup-plugin-postcss": "^4.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 440752a..9716d71 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,10 +35,10 @@ devDependencies: specifier: ^6.2.0 version: 6.2.0 copyfiles: - specifier: ^2.3.0 + specifier: ^2.4.1 version: 2.4.1 cross-env: - specifier: ^7.0.2 + specifier: ^7.0.3 version: 7.0.3 eslint: specifier: ^7.31.0 @@ -50,8 +50,17 @@ devDependencies: specifier: ^1.5.0 version: 1.5.0(eslint@7.31.0) husky: - specifier: ^7.0.0 + specifier: ^7.0.1 version: 7.0.1 + jest: + specifier: ^29.5.0 + version: 29.5.0 + jest-cli: + specifier: ^29.5.0 + version: 29.5.0 + jest-environment-jsdom: + specifier: ^29.5.0 + version: 29.5.0 postcss: specifier: ^8.3.5 version: 8.3.5 @@ -64,6 +73,9 @@ devDependencies: pretty-quick: specifier: ^3.1.1 version: 3.1.1(prettier@2.3.2) + regenerator-runtime: + specifier: ^0.13.11 + version: 0.13.11 rimraf: specifier: ^3.0.2 version: 3.0.2 @@ -597,6 +609,15 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true + /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.14.8): + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.14.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.14.8): resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} peerDependencies: @@ -634,6 +655,15 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true + /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.14.8): + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.14.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.14.8): resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} peerDependencies: @@ -727,6 +757,16 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true + /@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.14.8): + resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.14.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + /@babel/plugin-transform-arrow-functions@7.22.5(@babel/core@7.14.8): resolution: {integrity: sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==} engines: {node: '>=6.9.0'} @@ -1258,6 +1298,10 @@ packages: to-fast-properties: 2.0.0 dev: true + /@bcoe/v8-coverage@0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true + /@eslint/eslintrc@0.4.3: resolution: {integrity: sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==} engines: {node: ^10.12.0 || >=12.0.0} @@ -1290,6 +1334,235 @@ packages: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: true + /@istanbuljs/load-nyc-config@1.1.0: + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + dev: true + + /@istanbuljs/schema@0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: true + + /@jest/console@29.6.1: + resolution: {integrity: sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.1 + '@types/node': 20.3.1 + chalk: 4.1.2 + jest-message-util: 29.6.1 + jest-util: 29.6.1 + slash: 3.0.0 + dev: true + + /@jest/core@29.6.1: + resolution: {integrity: sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/console': 29.6.1 + '@jest/reporters': 29.6.1 + '@jest/test-result': 29.6.1 + '@jest/transform': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.3.1 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.8.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.5.0 + jest-config: 29.6.1(@types/node@20.3.1) + jest-haste-map: 29.6.1 + jest-message-util: 29.6.1 + jest-regex-util: 29.4.3 + jest-resolve: 29.6.1 + jest-resolve-dependencies: 29.6.1 + jest-runner: 29.6.1 + jest-runtime: 29.6.1 + jest-snapshot: 29.6.1 + jest-util: 29.6.1 + jest-validate: 29.6.1 + jest-watcher: 29.6.1 + micromatch: 4.0.5 + pretty-format: 29.6.1 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - supports-color + - ts-node + dev: true + + /@jest/environment@29.6.1: + resolution: {integrity: sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/fake-timers': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.3.1 + jest-mock: 29.6.1 + dev: true + + /@jest/expect-utils@29.6.1: + resolution: {integrity: sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.4.3 + dev: true + + /@jest/expect@29.6.1: + resolution: {integrity: sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + expect: 29.6.1 + jest-snapshot: 29.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/fake-timers@29.6.1: + resolution: {integrity: sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.1 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 20.3.1 + jest-message-util: 29.6.1 + jest-mock: 29.6.1 + jest-util: 29.6.1 + dev: true + + /@jest/globals@29.6.1: + resolution: {integrity: sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.6.1 + '@jest/expect': 29.6.1 + '@jest/types': 29.6.1 + jest-mock: 29.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/reporters@29.6.1: + resolution: {integrity: sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.6.1 + '@jest/test-result': 29.6.1 + '@jest/transform': 29.6.1 + '@jest/types': 29.6.1 + '@jridgewell/trace-mapping': 0.3.18 + '@types/node': 20.3.1 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.0 + istanbul-lib-instrument: 5.2.1 + istanbul-lib-report: 3.0.0 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.5 + jest-message-util: 29.6.1 + jest-util: 29.6.1 + jest-worker: 29.6.1 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.1.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/schemas@29.6.0: + resolution: {integrity: sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@sinclair/typebox': 0.27.8 + dev: true + + /@jest/source-map@29.6.0: + resolution: {integrity: sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jridgewell/trace-mapping': 0.3.18 + callsites: 3.1.0 + graceful-fs: 4.2.11 + dev: true + + /@jest/test-result@29.6.1: + resolution: {integrity: sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/console': 29.6.1 + '@jest/types': 29.6.1 + '@types/istanbul-lib-coverage': 2.0.4 + collect-v8-coverage: 1.0.2 + dev: true + + /@jest/test-sequencer@29.6.1: + resolution: {integrity: sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/test-result': 29.6.1 + graceful-fs: 4.2.11 + jest-haste-map: 29.6.1 + slash: 3.0.0 + dev: true + + /@jest/transform@29.6.1: + resolution: {integrity: sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/core': 7.14.8 + '@jest/types': 29.6.1 + '@jridgewell/trace-mapping': 0.3.18 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.6.1 + jest-regex-util: 29.4.3 + jest-util: 29.6.1 + micromatch: 4.0.5 + pirates: 4.0.6 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/types@29.6.1: + resolution: {integrity: sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.0 + '@types/istanbul-lib-coverage': 2.0.4 + '@types/istanbul-reports': 3.0.1 + '@types/node': 20.3.1 + '@types/yargs': 17.0.24 + chalk: 4.1.2 + dev: true + /@jridgewell/gen-mapping@0.3.3: resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} engines: {node: '>=6.0.0'} @@ -1375,10 +1648,90 @@ packages: rollup: 2.53.2 dev: true + /@sinclair/typebox@0.27.8: + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + dev: true + + /@sinonjs/commons@3.0.0: + resolution: {integrity: sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==} + dependencies: + type-detect: 4.0.8 + dev: true + + /@sinonjs/fake-timers@10.3.0: + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + dependencies: + '@sinonjs/commons': 3.0.0 + dev: true + + /@tootallnate/once@2.0.0: + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + dev: true + + /@types/babel__core@7.20.1: + resolution: {integrity: sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==} + dependencies: + '@babel/parser': 7.22.5 + '@babel/types': 7.22.5 + '@types/babel__generator': 7.6.4 + '@types/babel__template': 7.4.1 + '@types/babel__traverse': 7.20.1 + dev: true + + /@types/babel__generator@7.6.4: + resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==} + dependencies: + '@babel/types': 7.22.5 + dev: true + + /@types/babel__template@7.4.1: + resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} + dependencies: + '@babel/parser': 7.22.5 + '@babel/types': 7.22.5 + dev: true + + /@types/babel__traverse@7.20.1: + resolution: {integrity: sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==} + dependencies: + '@babel/types': 7.22.5 + dev: true + /@types/estree@0.0.39: resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} dev: true + /@types/graceful-fs@4.1.6: + resolution: {integrity: sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==} + dependencies: + '@types/node': 20.3.1 + dev: true + + /@types/istanbul-lib-coverage@2.0.4: + resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} + dev: true + + /@types/istanbul-lib-report@3.0.0: + resolution: {integrity: sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==} + dependencies: + '@types/istanbul-lib-coverage': 2.0.4 + dev: true + + /@types/istanbul-reports@3.0.1: + resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==} + dependencies: + '@types/istanbul-lib-report': 3.0.0 + dev: true + + /@types/jsdom@20.0.1: + resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} + dependencies: + '@types/node': 20.3.1 + '@types/tough-cookie': 4.0.2 + parse5: 7.1.2 + dev: true + /@types/minimatch@3.0.5: resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} dev: true @@ -1391,6 +1744,10 @@ packages: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} dev: true + /@types/prettier@2.7.3: + resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} + dev: true + /@types/q@1.5.5: resolution: {integrity: sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==} dev: true @@ -1401,10 +1758,32 @@ packages: '@types/node': 20.3.1 dev: true + /@types/stack-utils@2.0.1: + resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} + dev: true + + /@types/tough-cookie@4.0.2: + resolution: {integrity: sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==} + dev: true + + /@types/yargs-parser@21.0.0: + resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} + dev: true + + /@types/yargs@17.0.24: + resolution: {integrity: sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==} + dependencies: + '@types/yargs-parser': 21.0.0 + dev: true + /@zeit/schemas@2.6.0: resolution: {integrity: sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg==} dev: true + /abab@2.0.6: + resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} + dev: true + /accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} @@ -1413,6 +1792,13 @@ packages: negotiator: 0.6.3 dev: true + /acorn-globals@7.0.1: + resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} + dependencies: + acorn: 8.9.0 + acorn-walk: 8.2.0 + dev: true + /acorn-jsx@5.3.2(acorn@7.4.1): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1421,6 +1807,11 @@ packages: acorn: 7.4.1 dev: true + /acorn-walk@8.2.0: + resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + engines: {node: '>=0.4.0'} + dev: true + /acorn@7.4.1: resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} engines: {node: '>=0.4.0'} @@ -1433,6 +1824,15 @@ packages: hasBin: true dev: true + /agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: @@ -1466,6 +1866,13 @@ packages: engines: {node: '>=6'} dev: true + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + /ansi-regex@3.0.1: resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} engines: {node: '>=4'} @@ -1490,6 +1897,19 @@ packages: color-convert: 2.0.1 dev: true + /ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: true + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + /arch@2.2.0: resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} dev: true @@ -1542,11 +1962,56 @@ packages: engines: {node: '>=8'} dev: true + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: true + /available-typed-arrays@1.0.5: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} dev: true + /babel-jest@29.6.1(@babel/core@7.14.8): + resolution: {integrity: sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + dependencies: + '@babel/core': 7.14.8 + '@jest/transform': 29.6.1 + '@types/babel__core': 7.20.1 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.5.0(@babel/core@7.14.8) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + dependencies: + '@babel/helper-plugin-utils': 7.22.5 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-jest-hoist@29.5.0: + resolution: {integrity: sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/template': 7.22.5 + '@babel/types': 7.22.5 + '@types/babel__core': 7.20.1 + '@types/babel__traverse': 7.20.1 + dev: true + /babel-plugin-polyfill-corejs2@0.2.3(@babel/core@7.14.8): resolution: {integrity: sha512-NDZ0auNRzmAfE1oDDPW2JhzIMXUk+FFe2ICejmt5T4ocKgiQx3e0VCRx9NCAidcMtL2RUZaWtXnmjTCkx0tcbA==} peerDependencies: @@ -1583,6 +2048,37 @@ packages: - supports-color dev: true + /babel-preset-current-node-syntax@1.0.1(@babel/core@7.14.8): + resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.14.8 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.14.8) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.14.8) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.14.8) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.14.8) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.14.8) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.14.8) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.14.8) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.14.8) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.14.8) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.14.8) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.14.8) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.14.8) + dev: true + + /babel-preset-jest@29.5.0(@babel/core@7.14.8): + resolution: {integrity: sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.14.8 + babel-plugin-jest-hoist: 29.5.0 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.14.8) + dev: true + /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true @@ -1597,7 +2093,7 @@ packages: dependencies: ansi-align: 2.0.0 camelcase: 4.1.0 - chalk: 2.4.1 + chalk: 2.4.2 cli-boxes: 1.0.0 string-width: 2.1.1 term-size: 1.2.0 @@ -1611,6 +2107,13 @@ packages: concat-map: 0.0.1 dev: true + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + /browserslist@4.21.9: resolution: {integrity: sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -1622,6 +2125,12 @@ packages: update-browserslist-db: 1.0.11(browserslist@4.21.9) dev: true + /bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + dependencies: + node-int64: 0.4.0 + dev: true + /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true @@ -1672,6 +2181,16 @@ packages: engines: {node: '>=4'} dev: true + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: true + /caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} dependencies: @@ -1719,6 +2238,20 @@ packages: supports-color: 7.2.0 dev: true + /char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + dev: true + + /ci-info@3.8.0: + resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==} + engines: {node: '>=8'} + dev: true + + /cjs-module-lexer@1.2.3: + resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} + dev: true + /cli-boxes@1.0.0: resolution: {integrity: sha512-3Fo5wu8Ytle8q9iCzS4D2MWVL2X7JVWRiS1BnXbTFDhS9c/REkM9vd1AmabsoZoY5/dGi5TT9iKL8Kb6DeBRQg==} engines: {node: '>=0.10.0'} @@ -1741,6 +2274,20 @@ packages: wrap-ansi: 7.0.0 dev: true + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + dev: true + /coa@2.0.2: resolution: {integrity: sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==} engines: {node: '>= 4.0'} @@ -1750,6 +2297,10 @@ packages: q: 1.5.1 dev: true + /collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + dev: true + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -1789,6 +2340,13 @@ packages: resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} dev: true + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: true + /commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} dev: true @@ -1850,6 +2408,10 @@ packages: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} dev: true + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true + /cookie@0.4.1: resolution: {integrity: sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==} engines: {node: '>= 0.6'} @@ -2051,6 +2613,30 @@ packages: css-tree: 1.1.3 dev: true + /cssom@0.3.8: + resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} + dev: true + + /cssom@0.5.0: + resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} + dev: true + + /cssstyle@2.3.0: + resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} + engines: {node: '>=8'} + dependencies: + cssom: 0.3.8 + dev: true + + /data-urls@3.0.2: + resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} + engines: {node: '>=12'} + dependencies: + abab: 2.0.6 + whatwg-mimetype: 3.0.0 + whatwg-url: 11.0.0 + dev: true + /date-fns@2.30.0: resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} engines: {node: '>=0.11'} @@ -2081,6 +2667,14 @@ packages: ms: 2.1.2 dev: true + /decimal.js@10.4.3: + resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + dev: true + + /dedent@0.7.0: + resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} + dev: true + /deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -2103,6 +2697,21 @@ packages: object-keys: 1.1.1 dev: true + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: true + + /detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + dev: true + + /diff-sequences@29.4.3: + resolution: {integrity: sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + /doctrine@3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} @@ -2125,6 +2734,13 @@ packages: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} dev: true + /domexception@4.0.0: + resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} + engines: {node: '>=12'} + dependencies: + webidl-conversions: 7.0.0 + dev: true + /domutils@1.7.0: resolution: {integrity: sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==} dependencies: @@ -2143,6 +2759,11 @@ packages: resolution: {integrity: sha512-MGO1k0w1RgrfdbLVwmXcDhHHuxCn2qRgR7dYsJvWFKDttvYPx6FNzCGG0c/fBBvzK2LDh3UV7Tt9awnHnvAAUQ==} dev: true + /emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + dev: true + /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: true @@ -2164,6 +2785,11 @@ packages: resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} dev: true + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + dev: true + /error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} dependencies: @@ -2242,11 +2868,28 @@ packages: engines: {node: '>=0.8.0'} dev: true + /escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + dev: true + /escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} dev: true + /escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + dev: true + /eslint-config-important-stuff@1.1.0: resolution: {integrity: sha512-CsV6QFsjNDTZTDEgE1XxhTKph4YJUh5XFMdsWv3p+9DuMyvfy40fsnZiwqXZHBVEUNMHf+zfPGk6s6b4fS9Erw==} dev: true @@ -2430,6 +3073,38 @@ packages: strip-final-newline: 2.0.0 dev: true + /execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + dev: true + + /expect@29.6.1: + resolution: {integrity: sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/expect-utils': 29.6.1 + '@types/node': 20.3.1 + jest-get-type: 29.4.3 + jest-matcher-utils: 29.6.1 + jest-message-util: 29.6.1 + jest-util: 29.6.1 + dev: true + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true @@ -2448,6 +3123,12 @@ packages: punycode: 1.4.1 dev: true + /fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + dependencies: + bser: 2.1.1 + dev: true + /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -2455,6 +3136,13 @@ packages: flat-cache: 3.0.4 dev: true + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + /find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -2481,6 +3169,15 @@ packages: is-callable: 1.2.7 dev: true + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true @@ -2540,6 +3237,11 @@ packages: has-symbols: 1.0.3 dev: true + /get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + dev: true + /get-stream@3.0.0: resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} engines: {node: '>=4'} @@ -2559,6 +3261,11 @@ packages: pump: 3.0.0 dev: true + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + /get-symbol-description@1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} @@ -2610,6 +3317,10 @@ packages: get-intrinsic: 1.2.1 dev: true + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} dev: true @@ -2670,17 +3381,61 @@ packages: resolution: {integrity: sha512-7Wn5GMLuHBjZCb2bTmnDOycho0p/7UVaAeqXZGbHrBCl6Yd/xDhQJAXe6Ga9AXJH2I5zY1dEdYw2u1UptnSBJA==} dev: true + /html-encoding-sniffer@3.0.0: + resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} + engines: {node: '>=12'} + dependencies: + whatwg-encoding: 2.0.0 + dev: true + + /html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true + + /http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + dependencies: + '@tootallnate/once': 2.0.0 + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + /human-signals@1.1.1: resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} engines: {node: '>=8.12.0'} dev: true + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + /husky@7.0.1: resolution: {integrity: sha512-gceRaITVZ+cJH9sNHqx5tFwbzlLCVxtVZcusME8JYQ8Edy5mpGDOqD8QBCdMhpyo9a+JXddnujQ4rpY2Ff9SJA==} engines: {node: '>=12'} hasBin: true dev: true + /iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + /icss-replace-symbols@1.1.0: resolution: {integrity: sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==} dev: true @@ -2734,6 +3489,15 @@ packages: resolve-from: 5.0.0 dev: true + /import-local@3.1.0: + resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + engines: {node: '>=8'} + hasBin: true + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + dev: true + /imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -2857,6 +3621,11 @@ packages: engines: {node: '>=8'} dev: true + /is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + dev: true + /is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -2880,11 +3649,20 @@ packages: has-tostringtag: 1.0.0 dev: true + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + /is-obj@2.0.0: resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} engines: {node: '>=8'} dev: true + /is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + dev: true + /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -2941,30 +3719,476 @@ packages: /is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.2 + dev: true + + /is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + dependencies: + is-docker: 2.2.1 + dev: true + + /isarray@0.0.1: + resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} + dev: true + + /isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: true + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /istanbul-lib-coverage@3.2.0: + resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.14.8 + '@babel/parser': 7.22.5 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-report@3.0.0: + resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} + engines: {node: '>=8'} + dependencies: + istanbul-lib-coverage: 3.2.0 + make-dir: 3.1.0 + supports-color: 7.2.0 + dev: true + + /istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + dependencies: + debug: 4.3.4 + istanbul-lib-coverage: 3.2.0 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-reports@3.1.5: + resolution: {integrity: sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.0 + dev: true + + /jest-changed-files@29.5.0: + resolution: {integrity: sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + execa: 5.1.1 + p-limit: 3.1.0 + dev: true + + /jest-circus@29.6.1: + resolution: {integrity: sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.6.1 + '@jest/expect': 29.6.1 + '@jest/test-result': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.3.1 + chalk: 4.1.2 + co: 4.6.0 + dedent: 0.7.0 + is-generator-fn: 2.1.0 + jest-each: 29.6.1 + jest-matcher-utils: 29.6.1 + jest-message-util: 29.6.1 + jest-runtime: 29.6.1 + jest-snapshot: 29.6.1 + jest-util: 29.6.1 + p-limit: 3.1.0 + pretty-format: 29.6.1 + pure-rand: 6.0.2 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-cli@29.5.0: + resolution: {integrity: sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.6.1 + '@jest/test-result': 29.6.1 + '@jest/types': 29.6.1 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + import-local: 3.1.0 + jest-config: 29.6.1(@types/node@20.3.1) + jest-util: 29.6.1 + jest-validate: 29.6.1 + prompts: 2.4.2 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - supports-color + - ts-node + dev: true + + /jest-config@29.6.1(@types/node@20.3.1): + resolution: {integrity: sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.14.8 + '@jest/test-sequencer': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.3.1 + babel-jest: 29.6.1(@babel/core@7.14.8) + chalk: 4.1.2 + ci-info: 3.8.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.6.1 + jest-environment-node: 29.6.1 + jest-get-type: 29.4.3 + jest-regex-util: 29.4.3 + jest-resolve: 29.6.1 + jest-runner: 29.6.1 + jest-util: 29.6.1 + jest-validate: 29.6.1 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.6.1 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-diff@29.6.1: + resolution: {integrity: sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 29.4.3 + jest-get-type: 29.4.3 + pretty-format: 29.6.1 + dev: true + + /jest-docblock@29.4.3: + resolution: {integrity: sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + detect-newline: 3.1.0 + dev: true + + /jest-each@29.6.1: + resolution: {integrity: sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.1 + chalk: 4.1.2 + jest-get-type: 29.4.3 + jest-util: 29.6.1 + pretty-format: 29.6.1 + dev: true + + /jest-environment-jsdom@29.5.0: + resolution: {integrity: sha512-/KG8yEK4aN8ak56yFVdqFDzKNHgF4BAymCx2LbPNPsUshUlfAl0eX402Xm1pt+eoG9SLZEUVifqXtX8SK74KCw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + dependencies: + '@jest/environment': 29.6.1 + '@jest/fake-timers': 29.6.1 + '@jest/types': 29.6.1 + '@types/jsdom': 20.0.1 + '@types/node': 20.3.1 + jest-mock: 29.6.1 + jest-util: 29.6.1 + jsdom: 20.0.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /jest-environment-node@29.6.1: + resolution: {integrity: sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.6.1 + '@jest/fake-timers': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.3.1 + jest-mock: 29.6.1 + jest-util: 29.6.1 + dev: true + + /jest-get-type@29.4.3: + resolution: {integrity: sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + + /jest-haste-map@29.6.1: + resolution: {integrity: sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.1 + '@types/graceful-fs': 4.1.6 + '@types/node': 20.3.1 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.4.3 + jest-util: 29.6.1 + jest-worker: 29.6.1 + micromatch: 4.0.5 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /jest-leak-detector@29.6.1: + resolution: {integrity: sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.4.3 + pretty-format: 29.6.1 + dev: true + + /jest-matcher-utils@29.6.1: + resolution: {integrity: sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + jest-diff: 29.6.1 + jest-get-type: 29.4.3 + pretty-format: 29.6.1 + dev: true + + /jest-message-util@29.6.1: + resolution: {integrity: sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/code-frame': 7.22.5 + '@jest/types': 29.6.1 + '@types/stack-utils': 2.0.1 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.5 + pretty-format: 29.6.1 + slash: 3.0.0 + stack-utils: 2.0.6 + dev: true + + /jest-mock@29.6.1: + resolution: {integrity: sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.1 + '@types/node': 20.3.1 + jest-util: 29.6.1 + dev: true + + /jest-pnp-resolver@1.2.3(jest-resolve@29.6.1): + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + dependencies: + jest-resolve: 29.6.1 + dev: true + + /jest-regex-util@29.4.3: + resolution: {integrity: sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + + /jest-resolve-dependencies@29.6.1: + resolution: {integrity: sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-regex-util: 29.4.3 + jest-snapshot: 29.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-resolve@29.6.1: + resolution: {integrity: sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.6.1 + jest-pnp-resolver: 1.2.3(jest-resolve@29.6.1) + jest-util: 29.6.1 + jest-validate: 29.6.1 + resolve: 1.22.2 + resolve.exports: 2.0.2 + slash: 3.0.0 + dev: true + + /jest-runner@29.6.1: + resolution: {integrity: sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/console': 29.6.1 + '@jest/environment': 29.6.1 + '@jest/test-result': 29.6.1 + '@jest/transform': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.3.1 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.4.3 + jest-environment-node: 29.6.1 + jest-haste-map: 29.6.1 + jest-leak-detector: 29.6.1 + jest-message-util: 29.6.1 + jest-resolve: 29.6.1 + jest-runtime: 29.6.1 + jest-util: 29.6.1 + jest-watcher: 29.6.1 + jest-worker: 29.6.1 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color dev: true - /is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} + /jest-runtime@29.6.1: + resolution: {integrity: sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - is-docker: 2.2.1 + '@jest/environment': 29.6.1 + '@jest/fake-timers': 29.6.1 + '@jest/globals': 29.6.1 + '@jest/source-map': 29.6.0 + '@jest/test-result': 29.6.1 + '@jest/transform': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.3.1 + chalk: 4.1.2 + cjs-module-lexer: 1.2.3 + collect-v8-coverage: 1.0.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 29.6.1 + jest-message-util: 29.6.1 + jest-mock: 29.6.1 + jest-regex-util: 29.4.3 + jest-resolve: 29.6.1 + jest-snapshot: 29.6.1 + jest-util: 29.6.1 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color dev: true - /isarray@0.0.1: - resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} + /jest-snapshot@29.6.1: + resolution: {integrity: sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/core': 7.14.8 + '@babel/generator': 7.22.5 + '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.14.8) + '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.14.8) + '@babel/types': 7.22.5 + '@jest/expect-utils': 29.6.1 + '@jest/transform': 29.6.1 + '@jest/types': 29.6.1 + '@types/prettier': 2.7.3 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.14.8) + chalk: 4.1.2 + expect: 29.6.1 + graceful-fs: 4.2.11 + jest-diff: 29.6.1 + jest-get-type: 29.4.3 + jest-matcher-utils: 29.6.1 + jest-message-util: 29.6.1 + jest-util: 29.6.1 + natural-compare: 1.4.0 + pretty-format: 29.6.1 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color dev: true - /isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + /jest-util@29.6.1: + resolution: {integrity: sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.1 + '@types/node': 20.3.1 + chalk: 4.1.2 + ci-info: 3.8.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 dev: true - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + /jest-validate@29.6.1: + resolution: {integrity: sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.1 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.4.3 + leven: 3.1.0 + pretty-format: 29.6.1 dev: true - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + /jest-watcher@29.6.1: + resolution: {integrity: sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/test-result': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.3.1 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.6.1 + string-length: 4.0.2 dev: true /jest-worker@26.6.2: @@ -2976,6 +4200,36 @@ packages: supports-color: 7.2.0 dev: true + /jest-worker@29.6.1: + resolution: {integrity: sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@types/node': 20.3.1 + jest-util: 29.6.1 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true + + /jest@29.5.0: + resolution: {integrity: sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.6.1 + '@jest/types': 29.6.1 + import-local: 3.1.0 + jest-cli: 29.5.0 + transitivePeerDependencies: + - '@types/node' + - supports-color + - ts-node + dev: true + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} dev: true @@ -2988,6 +4242,47 @@ packages: esprima: 4.0.1 dev: true + /jsdom@20.0.3: + resolution: {integrity: sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==} + engines: {node: '>=14'} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + dependencies: + abab: 2.0.6 + acorn: 8.9.0 + acorn-globals: 7.0.1 + cssom: 0.5.0 + cssstyle: 2.3.0 + data-urls: 3.0.2 + decimal.js: 10.4.3 + domexception: 4.0.0 + escodegen: 2.1.0 + form-data: 4.0.0 + html-encoding-sniffer: 3.0.0 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.7 + parse5: 7.1.2 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.3 + w3c-xmlserializer: 4.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 2.0.0 + whatwg-mimetype: 3.0.0 + whatwg-url: 11.0.0 + ws: 8.13.0 + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + /jsesc@0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true @@ -3025,6 +4320,16 @@ packages: hasBin: true dev: true + /kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + dev: true + + /leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + dev: true + /levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -3102,6 +4407,19 @@ packages: yallist: 4.0.0 dev: true + /make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.0 + dev: true + + /makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + dependencies: + tmpl: 1.0.5 + dev: true + /mdn-data@2.0.14: resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} dev: true @@ -3114,6 +4432,14 @@ packages: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + /mime-db@1.33.0: resolution: {integrity: sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==} engines: {node: '>= 0.6'} @@ -3215,6 +4541,10 @@ packages: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} dev: true + /node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + dev: true + /node-releases@2.0.12: resolution: {integrity: sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==} dev: true @@ -3235,6 +4565,11 @@ packages: validate-npm-package-license: 3.0.4 dev: true + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + /normalize-url@3.3.0: resolution: {integrity: sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==} engines: {node: '>=6'} @@ -3260,6 +4595,10 @@ packages: boolbase: 1.0.0 dev: true + /nwsapi@2.2.7: + resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} + dev: true + /object-inspect@1.12.3: resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} dev: true @@ -3341,6 +4680,13 @@ packages: p-try: 2.2.0 dev: true + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + /p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -3393,6 +4739,12 @@ packages: lines-and-columns: 1.2.4 dev: true + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.5.0 + dev: true + /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -3443,6 +4795,18 @@ packages: engines: {node: '>=10'} dev: true + /pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + dev: true + + /pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + dev: true + /postcss-calc@7.0.5: resolution: {integrity: sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==} dependencies: @@ -3819,6 +5183,15 @@ packages: hasBin: true dev: true + /pretty-format@29.6.1: + resolution: {integrity: sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.0 + ansi-styles: 5.2.0 + react-is: 18.2.0 + dev: true + /pretty-quick@3.1.1(prettier@2.3.2): resolution: {integrity: sha512-ZYLGiMoV2jcaas3vTJrLvKAYsxDoXQBUn8OSTxkl67Fyov9lyXivJTl0+2WVh+y6EovGcw7Lm5ThYpH+Sh3XxQ==} engines: {node: '>=10.13'} @@ -3849,10 +5222,22 @@ packages: engines: {node: '>=0.12'} dev: true + /prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + dev: true + /pseudomap@1.0.2: resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} dev: true + /psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + dev: true + /pump@3.0.0: resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} dependencies: @@ -3869,11 +5254,19 @@ packages: engines: {node: '>=6'} dev: true + /pure-rand@6.0.2: + resolution: {integrity: sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==} + dev: true + /q@1.5.1: resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} engines: {node: '>=0.6.0', teleport: '>=0.2.0'} dev: true + /querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + dev: true + /randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: @@ -3895,6 +5288,10 @@ packages: strip-json-comments: 2.0.1 dev: true + /react-is@18.2.0: + resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + dev: true + /read-pkg@5.2.0: resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} engines: {node: '>=8'} @@ -4004,6 +5401,17 @@ packages: engines: {node: '>=0.10.0'} dev: true + /requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + dev: true + + /resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + dependencies: + resolve-from: 5.0.0 + dev: true + /resolve-from@3.0.0: resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==} engines: {node: '>=4'} @@ -4019,6 +5427,11 @@ packages: engines: {node: '>=8'} dev: true + /resolve.exports@2.0.2: + resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} + engines: {node: '>=10'} + dev: true + /resolve@1.22.2: resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} hasBin: true @@ -4131,10 +5544,21 @@ packages: is-regex: 1.1.4 dev: true + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: true + /sax@1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} dev: true + /saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + dependencies: + xmlchars: 2.2.0 + dev: true + /semver@5.7.1: resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} hasBin: true @@ -4153,6 +5577,14 @@ packages: lru-cache: 6.0.0 dev: true + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + /serialize-javascript@4.0.0: resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} dependencies: @@ -4231,6 +5663,15 @@ packages: is-arrayish: 0.3.2 dev: true + /sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + /slice-ansi@4.0.0: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} @@ -4245,6 +5686,13 @@ packages: engines: {node: '>=0.10.0'} dev: true + /source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + /source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} dependencies: @@ -4297,10 +5745,25 @@ packages: deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' dev: true + /stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + dependencies: + escape-string-regexp: 2.0.0 + dev: true + /string-hash@1.1.3: resolution: {integrity: sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==} dev: true + /string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + dev: true + /string-width@2.1.1: resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} engines: {node: '>=4'} @@ -4367,6 +5830,11 @@ packages: ansi-regex: 5.0.1 dev: true + /strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + dev: true + /strip-eof@1.0.0: resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} engines: {node: '>=0.10.0'} @@ -4447,6 +5915,10 @@ packages: util.promisify: 1.0.1 dev: true + /symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + dev: true + /table@6.8.1: resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} engines: {node: '>=10.0.0'} @@ -4476,6 +5948,15 @@ packages: source-map-support: 0.5.21 dev: true + /test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + dev: true + /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true @@ -4491,11 +5972,39 @@ packages: resolution: {integrity: sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==} dev: true + /tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + dev: true + /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} dev: true + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /tough-cookie@4.1.3: + resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} + engines: {node: '>=6'} + dependencies: + psl: 1.9.0 + punycode: 2.3.0 + universalify: 0.2.0 + url-parse: 1.5.10 + dev: true + + /tr46@3.0.0: + resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} + engines: {node: '>=12'} + dependencies: + punycode: 2.3.0 + dev: true + /tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -4512,11 +6021,21 @@ packages: prelude-ls: 1.2.1 dev: true + /type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + /type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} dev: true + /type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true + /type-fest@0.6.0: resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} engines: {node: '>=8'} @@ -4570,6 +6089,11 @@ packages: resolution: {integrity: sha512-mZdDpf3vBV5Efh29kMw5tXoup/buMgxLzOt/XKFKcVmi+15ManNQWr6HfZ2aiZTYlYixbdNJ0KFmIZIv52tHSQ==} dev: true + /universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + dev: true + /unquote@1.1.1: resolution: {integrity: sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==} dev: true @@ -4603,6 +6127,13 @@ packages: punycode: 2.3.0 dev: true + /url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + dev: true + /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: true @@ -4620,6 +6151,15 @@ packages: resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} dev: true + /v8-to-istanbul@9.1.0: + resolution: {integrity: sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==} + engines: {node: '>=10.12.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.18 + '@types/istanbul-lib-coverage': 2.0.4 + convert-source-map: 1.9.0 + dev: true + /validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} dependencies: @@ -4636,6 +6176,44 @@ packages: resolution: {integrity: sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==} dev: true + /w3c-xmlserializer@4.0.0: + resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} + engines: {node: '>=14'} + dependencies: + xml-name-validator: 4.0.0 + dev: true + + /walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + dependencies: + makeerror: 1.0.12 + dev: true + + /webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + dev: true + + /whatwg-encoding@2.0.0: + resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} + engines: {node: '>=12'} + dependencies: + iconv-lite: 0.6.3 + dev: true + + /whatwg-mimetype@3.0.0: + resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} + engines: {node: '>=12'} + dev: true + + /whatwg-url@11.0.0: + resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} + engines: {node: '>=12'} + dependencies: + tr46: 3.0.0 + webidl-conversions: 7.0.0 + dev: true + /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} dependencies: @@ -4698,6 +6276,36 @@ packages: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} dev: true + /write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + dev: true + + /ws@8.13.0: + resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + + /xml-name-validator@4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + dev: true + + /xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + dev: true + /xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -4730,6 +6338,11 @@ packages: engines: {node: '>=10'} dev: true + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + /yargs@16.2.0: resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} engines: {node: '>=10'} @@ -4742,3 +6355,21 @@ packages: y18n: 5.0.8 yargs-parser: 20.2.9 dev: true + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/src/api/js-api.domainsElement.test.js b/src/api/js-api.domainsElement.test.js new file mode 100644 index 0000000..12dc681 --- /dev/null +++ b/src/api/js-api.domainsElement.test.js @@ -0,0 +1,43 @@ +describe("domainsElement", () => { + const getDocument = (domainsElementContent) => ` + + + + + + + + `; + beforeEach(() => { + window.importMapOverrides = undefined; + jest.resetModules(); + }); + + it("should not initialize if host is in denyList", () => { + document.body.innerHTML = getDocument("denylist:localhost"); + import("./js-api").then(() => { + expect(window.importMapOverrides).toBeUndefined(); + }); + }); + + it("should not initialize if host is not in allowList", () => { + document.body.innerHTML = getDocument("allowlist:randomhost"); + import("./js-api").then(() => { + expect(window.importMapOverrides).toBeUndefined(); + }); + }); + + it("should initialize if host is not in denyList", () => { + document.body.innerHTML = getDocument("denylist:randomhost"); + import("./js-api").then(() => { + expect(window.importMapOverrides).toBeDefined(); + }); + }); + + it("should initialize if host is in allowList", () => { + document.body.innerHTML = getDocument("allowlist:localhost"); + import("./js-api").then(() => { + expect(window.importMapOverrides).toBeDefined(); + }); + }); +}); diff --git a/src/api/js-api.imo.test.js b/src/api/js-api.imo.test.js new file mode 100644 index 0000000..7584294 --- /dev/null +++ b/src/api/js-api.imo.test.js @@ -0,0 +1,44 @@ +import "regenerator-runtime/runtime"; + +describe("window.importMapOverrides", () => { + const defaultMap = ``; + + beforeEach(jest.resetModules); + + const setDocumentAndLoadScript = (additionalContent) => { + document.body.innerHTML = ` + + + + ${defaultMap} + ${additionalContent || ""} + + + + `; + return import("./js-api"); + }; + + // Test getDefaultMap + it("should return the default inline map", async () => { + await setDocumentAndLoadScript(); + const map = await window.importMapOverrides.getDefaultMap(); + + expect(map).toEqual({ + imports: { + package1: "https://cdn.skypack.dev/package1", + package2: "https://cdn.skypack.dev/package2", + package3: "https://cdn.skypack.dev/package3", + }, + scopes: {}, + }); + }); +}); diff --git a/src/api/js-api.test.js b/src/api/js-api.test.js new file mode 100644 index 0000000..62f5879 --- /dev/null +++ b/src/api/js-api.test.js @@ -0,0 +1,15 @@ +import { isDisabled, queryParamOverridesName } from "./js-api"; + +describe("js-api", () => { + it("isDisabled should be false by default", () => { + expect(isDisabled).toBe(false); + }); + + it("queryParamOverridesName should be imo by default", () => { + expect(queryParamOverridesName).toBe("imo"); + }); + + it("should create a global object importMapOverrides", () => { + expect(window.importMapOverrides).toBeDefined(); + }); +}); From a3a530282c4230e5f2e7b3fa63deb745ef48d177 Mon Sep 17 00:00:00 2001 From: Roberto Mosca Date: Sat, 1 Jul 2023 19:44:56 +0200 Subject: [PATCH 2/5] Address comments by Joel Denning --- .github/workflows/build-and-test.yml | 3 ++- .gitignore | 2 +- jest.config.cjs | 1 - jest.setup.js | 4 ---- package.json | 8 ++++---- 5 files changed, 7 insertions(+), 11 deletions(-) delete mode 100644 jest.setup.js diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 8c97659..e549223 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -24,4 +24,5 @@ jobs: - run: pnpm install --frozen-lockfile - run: pnpm run build - run: pnpm run lint - - run: pnpm run test-jest + - run: pnpm run check-format + - run: pnpm run test diff --git a/.gitignore b/.gitignore index fbf633c..7a30dc7 100644 --- a/.gitignore +++ b/.gitignore @@ -65,4 +65,4 @@ dist /.idea # VSCode IDE files -.vscode +/.vscode diff --git a/jest.config.cjs b/jest.config.cjs index a0d8ccb..ad6f8af 100644 --- a/jest.config.cjs +++ b/jest.config.cjs @@ -3,7 +3,6 @@ const config = { testEnvironment: "jsdom", resetMocks: true, restoreMocks: true, - setupFilesAfterEnv: ["/jest.setup.js"], }; module.exports = config; diff --git a/jest.setup.js b/jest.setup.js deleted file mode 100644 index 7bdb500..0000000 --- a/jest.setup.js +++ /dev/null @@ -1,4 +0,0 @@ -import { TextEncoder, TextDecoder } from "util"; - -global.TextEncoder = TextEncoder; -global.TextDecoder = TextDecoder; diff --git a/package.json b/package.json index f2ac72a..2c6965e 100644 --- a/package.json +++ b/package.json @@ -9,14 +9,14 @@ "scripts": { "build": "pnpm run clean && cross-env NODE_ENV=production rollup -c", "build:dev": "pnpm run clean && cross-env NODE_ENV=development rollup -c", + "check-format": "prettier --check src", "clean": "rimraf dist", "check-format": "prettier --check src", "watch": "cross-env NODE_ENV=development rollup -c --watch", "copy-test-files": "copyfiles test/**/* dist -f", - "test-jest": "jest", - "test-serve": "serve .", - "test-embed-serve": "serve . -l 3333", - "test": "concurrently pnpm:watch pnpm:copy-test-files pnpm:test-serve pnpm:test-embed-serve", + "serve": "serve .", + "embed-serve": "serve . -l 3333", + "test": "jest", "lint": "eslint src", "prepublishOnly": "pnpm run build", "prepare": "husky install" From 5224753c9438be9951dc900efc9317f165669f2d Mon Sep 17 00:00:00 2001 From: Roberto Mosca Date: Sat, 8 Jul 2023 23:50:03 +0200 Subject: [PATCH 3/5] Add more tests --- jest.config.cjs | 3 +- jest.setup.js | 1 + package.json | 1 + pnpm-lock.yaml | 51 +++ src/api/js-api.imo.test.js | 545 ++++++++++++++++++++++++++++++++- src/api/js-api.js | 9 +- src/util/includes.test.js | 23 ++ src/util/string-regex.test.js | 11 + src/util/url-parameter.test.js | 18 ++ 9 files changed, 644 insertions(+), 18 deletions(-) create mode 100644 jest.setup.js create mode 100644 src/util/includes.test.js create mode 100644 src/util/string-regex.test.js create mode 100644 src/util/url-parameter.test.js diff --git a/jest.config.cjs b/jest.config.cjs index ad6f8af..aa3c615 100644 --- a/jest.config.cjs +++ b/jest.config.cjs @@ -1,8 +1,9 @@ /** @type {import('jest').Config} */ const config = { - testEnvironment: "jsdom", resetMocks: true, restoreMocks: true, + setupFiles: ["./jest.setup.js"], + testEnvironment: "jsdom", }; module.exports = config; diff --git a/jest.setup.js b/jest.setup.js new file mode 100644 index 0000000..96bccd4 --- /dev/null +++ b/jest.setup.js @@ -0,0 +1 @@ +require("jest-fetch-mock").enableMocks(); diff --git a/package.json b/package.json index 2c6965e..37a1f3d 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "jest": "^29.5.0", "jest-cli": "^29.5.0", "jest-environment-jsdom": "^29.5.0", + "jest-fetch-mock": "^3.0.3", "postcss": "^8.3.5", "preact": "^10.5.14", "prettier": "^2.3.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9716d71..0a73e16 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -61,6 +61,9 @@ devDependencies: jest-environment-jsdom: specifier: ^29.5.0 version: 29.5.0 + jest-fetch-mock: + specifier: ^3.0.3 + version: 3.0.3 postcss: specifier: ^8.3.5 version: 8.3.5 @@ -2458,6 +2461,14 @@ packages: cross-spawn: 7.0.3 dev: true + /cross-fetch@3.1.8: + resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} + dependencies: + node-fetch: 2.6.12 + transitivePeerDependencies: + - encoding + dev: true + /cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} dependencies: @@ -3957,6 +3968,15 @@ packages: jest-util: 29.6.1 dev: true + /jest-fetch-mock@3.0.3: + resolution: {integrity: sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==} + dependencies: + cross-fetch: 3.1.8 + promise-polyfill: 8.3.0 + transitivePeerDependencies: + - encoding + dev: true + /jest-get-type@29.4.3: resolution: {integrity: sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -4541,6 +4561,18 @@ packages: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} dev: true + /node-fetch@2.6.12: + resolution: {integrity: sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: true + /node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} dev: true @@ -5217,6 +5249,10 @@ packages: engines: {node: '>=0.4.0'} dev: true + /promise-polyfill@8.3.0: + resolution: {integrity: sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==} + dev: true + /promise.series@0.2.0: resolution: {integrity: sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ==} engines: {node: '>=0.12'} @@ -5998,6 +6034,10 @@ packages: url-parse: 1.5.10 dev: true + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: true + /tr46@3.0.0: resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} engines: {node: '>=12'} @@ -6189,6 +6229,10 @@ packages: makeerror: 1.0.12 dev: true + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: true + /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} @@ -6214,6 +6258,13 @@ packages: webidl-conversions: 7.0.0 dev: true + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: true + /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} dependencies: diff --git a/src/api/js-api.imo.test.js b/src/api/js-api.imo.test.js index 7584294..33a7211 100644 --- a/src/api/js-api.imo.test.js +++ b/src/api/js-api.imo.test.js @@ -1,6 +1,34 @@ import "regenerator-runtime/runtime"; +// Mocks for the localStorage +const localStorageMock = (function () { + let store = {}; + + return { + get length() { + return Object.keys(store).length; + }, + key(index) { + return Object.keys(store)[index] || null; + }, + getItem(key) { + return store[key] || null; + }, + setItem(key, value) { + store[key] = value.toString(); + }, + removeItem(key) { + delete store[key]; + }, + clear() { + store = {}; + }, + }; +})(); + describe("window.importMapOverrides", () => { + let localStorageBackup; + const defaultMap = ``; - beforeEach(jest.resetModules); + beforeEach(() => { + jest.resetModules(); + fetch.resetMocks(); + localStorageBackup = window.localStorage; + Object.defineProperty(window, "localStorage", { value: localStorageMock }); + window.localStorage.clear(); + }); + + afterEach(() => { + Object.defineProperty(window, "localStorage", { + value: localStorageBackup, + }); + }); - const setDocumentAndLoadScript = (additionalContent) => { + const setDocumentAndLoadScript = (maps = [defaultMap]) => { document.body.innerHTML = ` - ${defaultMap} - ${additionalContent || ""} + ${maps.map((map) => map || "").join("\n")} @@ -27,18 +66,492 @@ describe("window.importMapOverrides", () => { return import("./js-api"); }; - // Test getDefaultMap - it("should return the default inline map", async () => { - await setDocumentAndLoadScript(); - const map = await window.importMapOverrides.getDefaultMap(); - - expect(map).toEqual({ - imports: { - package1: "https://cdn.skypack.dev/package1", - package2: "https://cdn.skypack.dev/package2", - package3: "https://cdn.skypack.dev/package3", - }, - scopes: {}, + describe("getDefaultMap", () => { + // Test getDefaultMap + it("should return the default inline map", async () => { + await setDocumentAndLoadScript(); + const map = await window.importMapOverrides.getDefaultMap(); + + expect(map).toEqual({ + imports: { + package1: "https://cdn.skypack.dev/package1", + package2: "https://cdn.skypack.dev/package2", + package3: "https://cdn.skypack.dev/package3", + }, + scopes: {}, + }); + }); + + // Test getDefaultMap + // Test the case where there is no default map + it("should return an empty map when there is no default map", async () => { + await setDocumentAndLoadScript([""]); + const map = await window.importMapOverrides.getDefaultMap(); + + expect(map).toEqual({ + imports: {}, + scopes: {}, + }); + }); + + // Test the case where the map is empty + it("should return an empty map when the default map is empty", async () => { + await setDocumentAndLoadScript([""]); + const map = await window.importMapOverrides.getDefaultMap(); + + expect(map).toEqual({ + imports: {}, + scopes: {}, + }); + }); + + // Test the case where the map is malformed + it("should return an empty map when the default map is malformed", async () => { + await setDocumentAndLoadScript([ + "", + ]); + const map = await window.importMapOverrides.getDefaultMap(); + + expect(map).toEqual({ + imports: {}, + scopes: {}, + }); + }); + + // Test the case where there are multiple inline maps + it("should return the union of all maps when there are multiple inline maps", async () => { + await setDocumentAndLoadScript([ + defaultMap, + ``, + ]); + const map = await window.importMapOverrides.getDefaultMap(); + + expect(map).toEqual({ + imports: { + package1: "https://cdn.skypack.dev/package1", + package2: "https://cdn.skypack.dev/package2", + package3: "https://cdn.skypack.dev/package3", + package4: "https://cdn.skypack.dev/package4", + package5: "https://cdn.skypack.dev/package5", + package6: "https://cdn.skypack.dev/package6", + }, + scopes: {}, + }); + }); + + // Test the case where there are multiple maps and one has the attribute + // data-is-importmap-override + it("should return the union of all maps except the ones having the attribute data-is-importmap-override", async () => { + await setDocumentAndLoadScript([ + defaultMap, + ``, + ``, + ]); + const map = await window.importMapOverrides.getDefaultMap(); + + expect(map).toEqual({ + imports: { + package1: "https://cdn.skypack.dev/package1", + package2: "https://cdn.skypack.dev/package2", + package3: "https://cdn.skypack.dev/package3", + package6: "https://cdn.skypack.dev/package6", + package7: "https://cdn.skypack.dev/package7", + }, + scopes: {}, + }); + }); + + // Test the case where there are multiple maps and one is external + it("should return the union of all maps including the external ones", async () => { + await setDocumentAndLoadScript([ + defaultMap, + ``, + ]); + + fetch.mockResponseOnce( + JSON.stringify({ + imports: { + package4: "https://cdn.skypack.dev/package4", + package5: "https://cdn.skypack.dev/package5", + }, + }) + ); + + const map = await window.importMapOverrides.getDefaultMap(); + + expect(map).toEqual({ + imports: { + package1: "https://cdn.skypack.dev/package1", + package2: "https://cdn.skypack.dev/package2", + package3: "https://cdn.skypack.dev/package3", + package4: "https://cdn.skypack.dev/package4", + package5: "https://cdn.skypack.dev/package5", + }, + scopes: {}, + }); + }); + }); + + describe("getOverrideMap", () => { + it("should return an empty map when there is no override map", async () => { + await setDocumentAndLoadScript(); + const map = await window.importMapOverrides.getOverrideMap(); + + expect(map).toEqual({ + imports: {}, + scopes: {}, + }); + }); + + it("should return return an override map when overrides are stored in the local storage", async () => { + await setDocumentAndLoadScript(); + window.localStorage.setItem( + "import-map-override:package3", + "https://cdn.skypack.dev/package33" + ); + window.localStorage.setItem( + "import-map-override:package4", + "https://cdn.skypack.dev/package4" + ); + const map = await window.importMapOverrides.getOverrideMap(); + + expect(map).toEqual({ + imports: { + package3: "https://cdn.skypack.dev/package33", + package4: "https://cdn.skypack.dev/package4", + }, + scopes: {}, + }); + }); + }); + + describe("Add/Remove/Enable/Disable overrides", () => { + const changeEventListener = jest.fn(); + + beforeEach(() => { + window.addEventListener( + "import-map-overrides:change", + changeEventListener + ); + }); + + afterEach(() => { + window.removeEventListener( + "import-map-overrides:change", + changeEventListener + ); + }); + + async function assertChangeEventListenerIsCalled() { + // Verify that the event listener is called + await new Promise((resolve) => + changeEventListener.mockImplementation(() => { + resolve(); + }) + ); + } + + describe("getDisabledOverrides", () => { + it("should return an empty array when there is no override", async () => { + await setDocumentAndLoadScript(); + + expect(window.importMapOverrides.getDisabledOverrides()).toEqual([]); + }); + + it("should return an array of disabled overrides", async () => { + await setDocumentAndLoadScript(); + window.localStorage.setItem( + "import-map-overrides-disabled", + JSON.stringify(["package3", "package4"]) + ); + + expect(window.importMapOverrides.getDisabledOverrides()).toEqual([ + "package3", + "package4", + ]); + }); + }); + + describe("isDisabled", () => { + it("should return true if the override is disabled", async () => { + await setDocumentAndLoadScript(); + window.localStorage.setItem( + "import-map-overrides-disabled", + JSON.stringify(["package3"]) + ); + + expect(window.importMapOverrides.isDisabled("package3")).toEqual(true); + }); + + it("should return false if the override is not disabled", async () => { + await setDocumentAndLoadScript(); + window.localStorage.setItem( + "import-map-overrides-disabled", + JSON.stringify(["package3"]) + ); + + expect(window.importMapOverrides.isDisabled("package4")).toEqual(false); + }); + }); + + describe("disableOverride", () => { + it("should disable an override and return true if it wasn't disabled before", async () => { + await setDocumentAndLoadScript(); + const result = await window.importMapOverrides.disableOverride( + "package3" + ); + + expect(window.importMapOverrides.getDisabledOverrides()).toEqual([ + "package3", + ]); + expect(result).toEqual(true); + await assertChangeEventListenerIsCalled(); + }); + + it("should maintain override disabled and return false if it was already disabled before", async () => { + await setDocumentAndLoadScript(); + window.localStorage.setItem( + "import-map-overrides-disabled", + JSON.stringify(["package3"]) + ); + const result = await window.importMapOverrides.disableOverride( + "package3" + ); + + expect(window.importMapOverrides.getDisabledOverrides()).toEqual([ + "package3", + ]); + expect(result).toEqual(false); + }); + }); + + describe("enableOverride", () => { + it("should re-enable a disabled override and return true", async () => { + await setDocumentAndLoadScript(); + window.localStorage.setItem( + "import-map-overrides-disabled", + JSON.stringify(["package3"]) + ); + const result = await window.importMapOverrides.enableOverride( + "package3" + ); + + expect(window.importMapOverrides.getDisabledOverrides()).toEqual([]); + expect(result).toEqual(true); + await assertChangeEventListenerIsCalled(); + }); + + it("should return false if override was not disabled before", async () => { + await setDocumentAndLoadScript(); + const result = await window.importMapOverrides.enableOverride( + "package3" + ); + + expect(window.importMapOverrides.getDisabledOverrides()).toEqual([]); + expect(result).toEqual(false); + }); + }); + + describe("addOverride", () => { + it("should add an override", async () => { + await setDocumentAndLoadScript(); + const map = await window.importMapOverrides.addOverride( + "package3", + "https://cdn.skypack.dev/package33.js" + ); + + expect(localStorage.getItem("import-map-override:package3")).toEqual( + "https://cdn.skypack.dev/package33.js" + ); + expect(map).toEqual({ + imports: { + package3: "https://cdn.skypack.dev/package33.js", + }, + scopes: {}, + }); + await assertChangeEventListenerIsCalled(); + }); + + it("should add an override by specifying only the port number", async () => { + await setDocumentAndLoadScript(); + const map = await window.importMapOverrides.addOverride( + "@demo/package33", + "8080" + ); + + expect( + localStorage.getItem("import-map-override:@demo/package33") + ).toEqual("//localhost:8080/demo-package33.js"); + expect(map).toEqual({ + imports: { + "@demo/package33": "//localhost:8080/demo-package33.js", + }, + scopes: {}, + }); + await assertChangeEventListenerIsCalled(); + }); + }); + + describe("removeOverride", () => { + it("should remove an existing override", async () => { + await setDocumentAndLoadScript(); + window.localStorage.setItem( + "import-map-override:package3", + "https://cdn.skypack.dev/package33" + ); + const result = await window.importMapOverrides.removeOverride( + "package3" + ); + + expect(localStorage.getItem("import-map-override:package3")).toEqual( + null + ); + expect(result).toBe(true); + await assertChangeEventListenerIsCalled(); + }); + }); + + describe("resetOverrides", () => { + it("should remove all overrides", async () => { + await setDocumentAndLoadScript(); + window.localStorage.setItem( + "import-map-override:package3", + "https://cdn.skypack.dev/package33" + ); + window.localStorage.setItem( + "import-map-override:package4", + "https://cdn.skypack.dev/package4" + ); + const map = await window.importMapOverrides.resetOverrides(); + + expect(localStorage.getItem("import-map-override:package3")).toEqual( + null + ); + expect(localStorage.getItem("import-map-override:package4")).toEqual( + null + ); + expect(map).toEqual({ + imports: {}, + scopes: {}, + }); + await assertChangeEventListenerIsCalled(); + }); + }); + + describe("hasOverrides", () => { + it("should return true if there are overrides", async () => { + await setDocumentAndLoadScript(); + window.localStorage.setItem( + "import-map-override:package3", + "https://cdn.skypack.dev/package33" + ); + + expect(window.importMapOverrides.hasOverrides()).toEqual(true); + }); + + it("should return false if there are no overrides", async () => { + await setDocumentAndLoadScript(); + + expect(window.importMapOverrides.hasOverrides()).toEqual(false); + }); + }); + }); + + describe("enableUI", () => { + it("should enable the UI", async () => { + await setDocumentAndLoadScript(); + const customElement = document.createElement("import-map-overrides-full"); + customElement.setAttribute("show-when-local-storage", "true"); + customElement.renderWithPreact = jest.fn(); + customElement.setAttribute("show-when-local-storage", "swlsKey"); + document.body.appendChild(customElement); + + window.importMapOverrides.enableUI(); + + expect(window.localStorage.getItem("swlsKey")).toBe("true"); + expect(customElement.renderWithPreact).toHaveBeenCalledTimes(1); + }); + }); + + describe("mergeImportMap", () => { + it("should merge an import map", async () => { + await setDocumentAndLoadScript(); + const map = await window.importMapOverrides.mergeImportMap( + { + imports: { + package1: "https://cdn.skypack.dev/package10.js", + package3: "https://cdn.skypack.dev/package33.js", + }, + scopes: { + scope1: { + package5: "https://cdn.skypack.dev/package55.js", + package6: "https://cdn.skypack.dev/package66.js", + }, + scope3: { + package8: "https://cdn.skypack.dev/package89.js", + package3: "https://cdn.skypack.dev/package31.js", + }, + }, + }, + { + imports: { + package1: "https://cdn.skypack.dev/package11.js", + package2: "https://cdn.skypack.dev/package20.js", + }, + scopes: { + scope2: { + package7: "https://cdn.skypack.dev/package77.js", + }, + scope3: { + package3: "https://cdn.skypack.dev/package32.js", + package9: "https://cdn.skypack.dev/package99.js", + }, + }, + } + ); + + expect(map).toEqual({ + imports: { + package1: "https://cdn.skypack.dev/package11.js", + package2: "https://cdn.skypack.dev/package20.js", + package3: "https://cdn.skypack.dev/package33.js", + }, + scopes: { + scope1: { + package5: "https://cdn.skypack.dev/package55.js", + package6: "https://cdn.skypack.dev/package66.js", + }, + scope2: { + package7: "https://cdn.skypack.dev/package77.js", + }, + scope3: { + package3: "https://cdn.skypack.dev/package32.js", + package9: "https://cdn.skypack.dev/package99.js", + }, + }, + }); }); }); }); diff --git a/src/api/js-api.js b/src/api/js-api.js index ebf3e09..0d81bfd 100644 --- a/src/api/js-api.js +++ b/src/api/js-api.js @@ -207,7 +207,13 @@ function init() { if (scriptEl.src) { nextPromise = fetchExternalMap(scriptEl.src); } else { - nextPromise = Promise.resolve(JSON.parse(scriptEl.textContent)); + let parsedContent; + try { + parsedContent = JSON.parse(scriptEl.textContent); + } catch (e) { + parsedContent = createEmptyImportMap(); + } + nextPromise = Promise.resolve(parsedContent); } return Promise.all([promise, nextPromise]).then( @@ -367,6 +373,7 @@ function init() { function fireEvent(type) { // Set timeout so that event fires after the change has totally finished + setTimeout(() => { const eventType = `import-map-overrides:${type}`; const event = canFireCustomEvents diff --git a/src/util/includes.test.js b/src/util/includes.test.js new file mode 100644 index 0000000..5b4e03c --- /dev/null +++ b/src/util/includes.test.js @@ -0,0 +1,23 @@ +import { includes } from "./includes"; + +describe("includes", () => { + it("returns true if the item is in the array", () => { + expect(includes([1, 2, 3], 2)).toBe(true); + }); + + it("returns false if the item is not in the array", () => { + expect(includes([1, 2, 3], 4)).toBe(false); + }); + + it("throws an error if the first argument is not an array or string", () => { + expect(() => includes(123, 1)).toThrow(); + }); + + it("returns true if the string contains the substring", () => { + expect(includes("hello-world", "world")).toBe(true); + }); + + it("returns false if the string does not contain the substring", () => { + expect(includes("hello-world", "goodbye")).toBe(false); + }); +}); diff --git a/src/util/string-regex.test.js b/src/util/string-regex.test.js new file mode 100644 index 0000000..3445e98 --- /dev/null +++ b/src/util/string-regex.test.js @@ -0,0 +1,11 @@ +import { escapeStringRegexp } from "./string-regex"; + +describe("escapeStringRegexp", () => { + it("escapes a string for use in a regular expression", () => { + expect(escapeStringRegexp("hello-world")).toBe("hello\\x2dworld"); + }); + + it("throws an error if the argument is not a string", () => { + expect(() => escapeStringRegexp(123)).toThrow(); + }); +}); diff --git a/src/util/url-parameter.test.js b/src/util/url-parameter.test.js new file mode 100644 index 0000000..3de9ef3 --- /dev/null +++ b/src/util/url-parameter.test.js @@ -0,0 +1,18 @@ +import { getParameterByName } from "./url-parameter"; + +describe("getParameterByName", () => { + it("returns the value of the specified parameter", () => { + const url = "http://localhost:3000/?name=Brian"; + expect(getParameterByName("name", url)).toBe("Brian"); + }); + + it("returns null if the parameter is not present", () => { + const url = "http://localhost:3000/"; + expect(getParameterByName("name", url)).toBe(null); + }); + + it("decodes the value of the parameter", () => { + const url = "http://localhost:3000/?name=Brian%20Love"; + expect(getParameterByName("name", url)).toBe("Brian Love"); + }); +}); From 28d05d7f4cd8b5fd91de833eb94059b44a8cef17 Mon Sep 17 00:00:00 2001 From: Roberto Mosca Date: Sun, 16 Jul 2023 12:29:18 +0200 Subject: [PATCH 4/5] Fix setDocumentAndLoadScript --- src/api/js-api.imo.test.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/api/js-api.imo.test.js b/src/api/js-api.imo.test.js index 33a7211..69f80e9 100644 --- a/src/api/js-api.imo.test.js +++ b/src/api/js-api.imo.test.js @@ -54,15 +54,7 @@ describe("window.importMapOverrides", () => { }); const setDocumentAndLoadScript = (maps = [defaultMap]) => { - document.body.innerHTML = ` - - - - ${maps.map((map) => map || "").join("\n")} - - - - `; + document.head.innerHTML = `${maps.map((map) => map || "").join("\n")}`; return import("./js-api"); }; From 873baec5fbfa706661830af5d5a91ac22325e8a4 Mon Sep 17 00:00:00 2001 From: Roberto Mosca Date: Sun, 16 Jul 2023 12:36:54 +0200 Subject: [PATCH 5/5] Add tests for external maps --- jest.config.cjs | 1 + src/api/js-api.external.test.js | 460 ++++++++++++++++++++++++++++++++ src/api/js-api.imo.test.js | 62 ++--- src/api/js-api.js | 4 +- src/api/localStorageMock.js | 25 ++ 5 files changed, 503 insertions(+), 49 deletions(-) create mode 100644 src/api/js-api.external.test.js create mode 100644 src/api/localStorageMock.js diff --git a/jest.config.cjs b/jest.config.cjs index aa3c615..d80f718 100644 --- a/jest.config.cjs +++ b/jest.config.cjs @@ -4,6 +4,7 @@ const config = { restoreMocks: true, setupFiles: ["./jest.setup.js"], testEnvironment: "jsdom", + collectCoverageFrom: ["src/**/*.js", "!src/api/localStorageMock.js"], }; module.exports = config; diff --git a/src/api/js-api.external.test.js b/src/api/js-api.external.test.js new file mode 100644 index 0000000..2c153ca --- /dev/null +++ b/src/api/js-api.external.test.js @@ -0,0 +1,460 @@ +import { localStorageMock } from "./localStorageMock"; + +describe("window.importMapOverrides", () => { + const changeEventListener = jest.fn(); + let localStorageBackup; + + const defaultMap = { + imports: { + package1: "https://cdn.skypack.dev/package1", + package2: "https://cdn.skypack.dev/package2", + package3: "https://cdn.skypack.dev/package3", + }, + }; + const defaultMapScript = ``; + + beforeEach(() => { + jest.resetModules(); + fetch.resetMocks(); + localStorageBackup = window.localStorage; + Object.defineProperty(window, "localStorage", { value: localStorageMock }); + window.localStorage.clear(); + window.addEventListener("import-map-overrides:change", changeEventListener); + jest.spyOn(console, "warn").mockImplementation(() => {}); + }); + + afterEach(() => { + Object.defineProperty(window, "localStorage", { + value: localStorageBackup, + }); + window.removeEventListener( + "import-map-overrides:change", + changeEventListener + ); + }); + + const setDocumentAndLoadScript = (maps = [defaultMapScript]) => { + document.head.innerHTML = `${maps.map((map) => map || "").join("\n")}`; + return import("./js-api"); + }; + + async function assertChangeEventListenerIsCalled() { + // Verify that the event listener is called + await new Promise((resolve) => + changeEventListener.mockImplementation(() => { + resolve(); + }) + ); + } + + describe("getExternalOverrides", () => { + it("should return an empty object if no overrides are set", async () => { + await setDocumentAndLoadScript(); + expect(window.importMapOverrides.getExternalOverrides()).toEqual([]); + }); + + it("should return an object with the overrides", async () => { + const overrides = [ + "https://cdn.skypack.dev/importmap1.json", + "https://cdn.skypack.dev/importmap2.json", + ]; + localStorageMock.setItem( + "import-map-overrides-external-maps", + JSON.stringify(overrides) + ); + await setDocumentAndLoadScript(); + + expect(window.importMapOverrides.getExternalOverrides()).toEqual( + overrides + ); + }); + }); + + describe("addExternalOverride", () => { + it("should add an external override if not there already", async () => { + const overrides = [ + "https://cdn.skypack.dev/importmap1.json", + "https://cdn.skypack.dev/importmap2.json", + ]; + localStorageMock.setItem( + "import-map-overrides-external-maps", + JSON.stringify(overrides) + ); + await setDocumentAndLoadScript(); + + expect( + window.importMapOverrides.addExternalOverride( + "https://cdn.skypack.dev/importmap3.json" + ) + ).toEqual(true); + expect(window.importMapOverrides.getExternalOverrides()).toEqual( + overrides.concat("https://cdn.skypack.dev/importmap3.json") + ); + await assertChangeEventListenerIsCalled(); + }); + + it("should not add an external override if already there", async () => { + const overrides = [ + "https://cdn.skypack.dev/importmap1.json", + "https://cdn.skypack.dev/importmap2.json", + ]; + localStorageMock.setItem( + "import-map-overrides-external-maps", + JSON.stringify(overrides) + ); + await setDocumentAndLoadScript(); + + expect( + window.importMapOverrides.addExternalOverride( + "https://cdn.skypack.dev/importmap2.json" + ) + ).toEqual(false); + expect(window.importMapOverrides.getExternalOverrides()).toEqual( + overrides + ); + }); + }); + + describe("removeExternalOverride", () => { + it("should remove an external override if there", async () => { + const overrides = [ + "https://cdn.skypack.dev/importmap1.json", + "https://cdn.skypack.dev/importmap2.json", + ]; + localStorageMock.setItem( + "import-map-overrides-external-maps", + JSON.stringify(overrides) + ); + await setDocumentAndLoadScript(); + + expect( + window.importMapOverrides.removeExternalOverride( + "https://cdn.skypack.dev/importmap2.json" + ) + ).toEqual(true); + expect(window.importMapOverrides.getExternalOverrides()).toEqual([ + "https://cdn.skypack.dev/importmap1.json", + ]); + await assertChangeEventListenerIsCalled(); + }); + + it("should not remove an external override if not there", async () => { + const overrides = [ + "https://cdn.skypack.dev/importmap1.json", + "https://cdn.skypack.dev/importmap2.json", + ]; + localStorageMock.setItem( + "import-map-overrides-external-maps", + JSON.stringify(overrides) + ); + await setDocumentAndLoadScript(); + + expect( + window.importMapOverrides.removeExternalOverride( + "https://cdn.skypack.dev/importmap3.json" + ) + ).toEqual(false); + expect(window.importMapOverrides.getExternalOverrides()).toEqual( + overrides + ); + }); + }); + + describe("getExternalOverrideMap", () => { + it("should return an empty override map if no external overrides are set", async () => { + await setDocumentAndLoadScript(); + expect( + window.importMapOverrides.getExternalOverrideMap() + ).resolves.toEqual({ imports: {}, scopes: {} }); + }); + + it("should return an override map with the external overrides", async () => { + await setDocumentAndLoadScript(); + window.importMapOverrides.getExternalOverrides = jest + .fn() + .mockReturnValue([ + "https://cdn.skypack.dev/importmap1.json", + "https://cdn.skypack.dev/importmap2.json", + ]); + fetch.mockImplementation((url) => { + if (url === "https://cdn.skypack.dev/importmap1.json") { + return Promise.resolve({ + ok: true, + json: () => + Promise.resolve({ + imports: { + package1: "https://cdn.skypack.dev/package1", + package2: "https://cdn.skypack.dev/package2", + }, + }), + }); + } else if (url === "https://cdn.skypack.dev/importmap2.json") { + return Promise.resolve({ + ok: true, + json: () => + Promise.resolve({ + imports: { + package2: "https://cdn.skypack.dev/package22", + package3: "https://cdn.skypack.dev/package3", + }, + }), + }); + } + }); + + const result = await window.importMapOverrides.getExternalOverrideMap(); + + expect(result).toEqual({ + imports: { + package1: "https://cdn.skypack.dev/package1", + package2: "https://cdn.skypack.dev/package22", + package3: "https://cdn.skypack.dev/package3", + }, + scopes: {}, + }); + }); + }); + + describe("isExternalMapValid", () => { + it("should return true if the external map is valid", async () => { + await setDocumentAndLoadScript(); + window.importMapOverrides.getExternalOverrides = jest + .fn() + .mockReturnValue(["https://cdn.skypack.dev/importmap1.json"]); + + fetch.mockImplementation((url) => { + if (url === "https://cdn.skypack.dev/importmap1.json") { + return Promise.resolve({ + ok: true, + json: () => + Promise.resolve({ + imports: { + package1: "https://cdn.skypack.dev/package1", + package2: "https://cdn.skypack.dev/package2", + }, + }), + }); + } + }); + + const result = await window.importMapOverrides.isExternalMapValid( + "https://cdn.skypack.dev/importmap1.json" + ); + + expect(result).toEqual(true); + }); + + it("should return false if the external map contains non-valid JSON", async () => { + await setDocumentAndLoadScript(); + window.importMapOverrides.getExternalOverrides = jest + .fn() + .mockReturnValue(["https://cdn.skypack.dev/importmap1.json"]); + + fetch.mockImplementation((url) => { + if (url === "https://cdn.skypack.dev/importmap1.json") { + return Promise.resolve({ + ok: true, + json: () => Promise.reject(new Error("Invalid JSON")), + url: "https://cdn.skypack.dev/importmap1.json", + }); + } + }); + + const result = await window.importMapOverrides.isExternalMapValid( + "https://cdn.skypack.dev/importmap1.json" + ); + + expect(result).toEqual(false); + }); + + it("should return false if fetching the external map returns a not-OK response", async () => { + await setDocumentAndLoadScript(); + window.importMapOverrides.getExternalOverrides = jest + .fn() + .mockReturnValue(["https://cdn.skypack.dev/importmap1.json"]); + + fetch.mockImplementation((url) => { + if (url === "https://cdn.skypack.dev/importmap1.json") { + return Promise.resolve({ + ok: false, + url: "https://cdn.skypack.dev/importmap1.json", + }); + } + }); + + const result = await window.importMapOverrides.isExternalMapValid( + "https://cdn.skypack.dev/importmap1.json" + ); + + expect(result).toEqual(false); + }); + + it("should return false if fetching the external map fails", async () => { + await setDocumentAndLoadScript(); + window.importMapOverrides.getExternalOverrides = jest + .fn() + .mockReturnValue(["https://cdn.skypack.dev/importmap1.json"]); + + fetch.mockRejectedValue(new Error("Failed to fetch")); + + const result = await window.importMapOverrides.isExternalMapValid( + "https://cdn.skypack.dev/importmap1.json" + ); + + expect(result).toEqual(false); + }); + }); + + describe("getCurrentPageExternalOverrides", () => { + it("should return an empty array if no external overrides are set", async () => { + await setDocumentAndLoadScript(); + + const result = + await window.importMapOverrides.getCurrentPageExternalOverrides(); + + expect(result).toEqual([]); + }); + + it("should return an array of external overrides if they are set", async () => { + await setDocumentAndLoadScript([ + '', + '', + ]); + + const result = + await window.importMapOverrides.getCurrentPageExternalOverrides(); + + expect(result).toEqual([ + "https://cdn.skypack.dev/importmap1.json", + "https://cdn.skypack.dev/importmap2.json", + ]); + }); + }); + + describe("getCurrentPageMap", () => { + it("should return the default map if no overrides are set", async () => { + await setDocumentAndLoadScript(); + + const result = await window.importMapOverrides.getCurrentPageMap(); + + expect(result).toEqual({ ...defaultMap, scopes: {} }); + }); + + it("should return a merge of the default map and the overrides", async () => { + await setDocumentAndLoadScript([ + defaultMapScript, + '', + ]); + + fetch.mockImplementation((url) => { + if (url === "https://cdn.skypack.dev/importmap1.json") { + return Promise.resolve({ + ok: true, + json: () => + Promise.resolve({ + imports: { + package3: "https://cdn.skypack.dev/package33", + package4: "https://cdn.skypack.dev/package4", + }, + scopes: { + "/scope1": { + package1: "https://cdn.skypack.dev/scope1/package1", + package2: "https://cdn.skypack.dev/scope1/package2", + }, + }, + }), + }); + } + }); + + const result = await window.importMapOverrides.getCurrentPageMap(); + + expect(result).toEqual({ + imports: { + package1: "https://cdn.skypack.dev/package1", + package2: "https://cdn.skypack.dev/package2", + package3: "https://cdn.skypack.dev/package33", + package4: "https://cdn.skypack.dev/package4", + }, + scopes: { + "/scope1": { + package1: "https://cdn.skypack.dev/scope1/package1", + package2: "https://cdn.skypack.dev/scope1/package2", + }, + }, + }); + }); + }); + + describe("getNextPageMap", () => { + it("should return the default map if no overrides are set", async () => { + await setDocumentAndLoadScript(); + + const result = await window.importMapOverrides.getNextPageMap(); + + expect(result).toEqual({ ...defaultMap, scopes: {} }); + }); + + it("should return a merge of the default map and the overrides", async () => { + await setDocumentAndLoadScript(); + window.importMapOverrides.getExternalOverrides = jest + .fn() + .mockReturnValue([ + "https://cdn.skypack.dev/importmap1.json", + "https://cdn.skypack.dev/importmap2.json", + ]); + + fetch.mockImplementation((url) => { + if (url === "https://cdn.skypack.dev/importmap1.json") { + return Promise.resolve({ + ok: true, + json: () => + Promise.resolve({ + imports: { + package2: "https://cdn.skypack.dev/package22", + package4: "https://cdn.skypack.dev/package4", + }, + }), + }); + } else if (url === "https://cdn.skypack.dev/importmap2.json") { + return Promise.resolve({ + ok: true, + json: () => + Promise.resolve({ + imports: { + package3: "https://cdn.skypack.dev/package33", + package5: "https://cdn.skypack.dev/package5", + }, + scopes: { + "/scope1": { + package1: "https://cdn.skypack.dev/scope1/package1", + package2: "https://cdn.skypack.dev/scope1/package2", + }, + }, + }), + }); + } + }); + + const result = await window.importMapOverrides.getNextPageMap(); + + expect(result).toEqual({ + imports: { + package1: "https://cdn.skypack.dev/package1", + package2: "https://cdn.skypack.dev/package22", + package3: "https://cdn.skypack.dev/package33", + package4: "https://cdn.skypack.dev/package4", + package5: "https://cdn.skypack.dev/package5", + }, + scopes: { + "/scope1": { + package1: "https://cdn.skypack.dev/scope1/package1", + package2: "https://cdn.skypack.dev/scope1/package2", + }, + }, + }); + }); + }); +}); diff --git a/src/api/js-api.imo.test.js b/src/api/js-api.imo.test.js index 69f80e9..c4804ba 100644 --- a/src/api/js-api.imo.test.js +++ b/src/api/js-api.imo.test.js @@ -1,42 +1,17 @@ -import "regenerator-runtime/runtime"; - -// Mocks for the localStorage -const localStorageMock = (function () { - let store = {}; - - return { - get length() { - return Object.keys(store).length; - }, - key(index) { - return Object.keys(store)[index] || null; - }, - getItem(key) { - return store[key] || null; - }, - setItem(key, value) { - store[key] = value.toString(); - }, - removeItem(key) { - delete store[key]; - }, - clear() { - store = {}; - }, - }; -})(); +import { localStorageMock } from "./localStorageMock"; describe("window.importMapOverrides", () => { let localStorageBackup; - const defaultMap = ``; beforeEach(() => { @@ -53,7 +28,7 @@ describe("window.importMapOverrides", () => { }); }); - const setDocumentAndLoadScript = (maps = [defaultMap]) => { + const setDocumentAndLoadScript = (maps = [defaultMapScript]) => { document.head.innerHTML = `${maps.map((map) => map || "").join("\n")}`; return import("./js-api"); }; @@ -64,14 +39,7 @@ describe("window.importMapOverrides", () => { await setDocumentAndLoadScript(); const map = await window.importMapOverrides.getDefaultMap(); - expect(map).toEqual({ - imports: { - package1: "https://cdn.skypack.dev/package1", - package2: "https://cdn.skypack.dev/package2", - package3: "https://cdn.skypack.dev/package3", - }, - scopes: {}, - }); + expect(map).toEqual({ ...defaultMap, scopes: {} }); }); // Test getDefaultMap @@ -113,7 +81,7 @@ describe("window.importMapOverrides", () => { // Test the case where there are multiple inline maps it("should return the union of all maps when there are multiple inline maps", async () => { await setDocumentAndLoadScript([ - defaultMap, + defaultMapScript, ``, ]); diff --git a/src/api/js-api.js b/src/api/js-api.js index 0d81bfd..b3cd8ec 100644 --- a/src/api/js-api.js +++ b/src/api/js-api.js @@ -347,8 +347,8 @@ function init() { externalOverrideMapPromises[importMapUrl] || (externalOverrideMapPromises[importMapUrl] = fetchExternalMap(importMapUrl)); - return promise.then(() => - includes(imo.invalidExternalMaps, importMapUrl) + return promise.then( + () => !includes(imo.invalidExternalMaps, importMapUrl) ); }, invalidExternalMaps: [], diff --git a/src/api/localStorageMock.js b/src/api/localStorageMock.js new file mode 100644 index 0000000..42193fc --- /dev/null +++ b/src/api/localStorageMock.js @@ -0,0 +1,25 @@ +// Mocks for the localStorage +export const localStorageMock = (function () { + let store = {}; + + return { + get length() { + return Object.keys(store).length; + }, + key(index) { + return Object.keys(store)[index] || null; + }, + getItem(key) { + return store[key] || null; + }, + setItem(key, value) { + store[key] = value.toString(); + }, + removeItem(key) { + delete store[key]; + }, + clear() { + store = {}; + }, + }; +})();