From c7d9a691f225a99f3ecc3c0879c2be8216d01645 Mon Sep 17 00:00:00 2001 From: Alex Nguyen <150945400+nguyenalex836@users.noreply.github.com> Date: Tue, 16 Apr 2024 09:48:40 -0700 Subject: [PATCH 1/3] Update generating-a-json-web-token-jwt-for-a-github-app.md (#50162) Co-authored-by: Sarah Edwards --- .../generating-a-json-web-token-jwt-for-a-github-app.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app.md b/content/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app.md index 841ab4b6de..af2b5bdf27 100644 --- a/content/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app.md +++ b/content/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app.md @@ -20,7 +20,7 @@ Your JWT must be signed using the `RS256` algorithm and must contain the followi |---|---|---| |`iat`| Issued At | The time that the JWT was created. To protect against clock drift, we recommend that you set this 60 seconds in the past and ensure that your server's date and time is set accurately (for example, by using the Network Time Protocol). | |`exp`| Expires At | The expiration time of the JWT, after which it can't be used to request an installation token. The time must be no more than 10 minutes into the future. | -|`iss`| Issuer | The ID of your {% data variables.product.prodname_github_app %}. This value is used to find the right public key to verify the signature of the JWT. You can find your app's ID on the settings page for your {% data variables.product.prodname_github_app %}. For more information about navigating to the settings page for your {% data variables.product.prodname_github_app %}, see "[AUTOTITLE](https://github.com/github/docs/blob/main/content/apps/maintaining-github-apps/modifying-a-github-app-registration#navigating-to-your-github-app-settings)." For more information, see "[Apps](/rest/apps/apps)" in the REST API documentation.| +|`iss`| Issuer | The ID of your {% data variables.product.prodname_github_app %}. This value is used to find the right public key to verify the signature of the JWT. You can find your app's ID on the settings page for your {% data variables.product.prodname_github_app %}. For more information about navigating to the settings page for your {% data variables.product.prodname_github_app %}, see "[AUTOTITLE](/apps/maintaining-github-apps/modifying-a-github-app-registration#navigating-to-your-github-app-settings)."| |`alg`| Message authentication code algorithm | This should be `RS256` since your JWT must be signed using the `RS256` algorithm. | To use a JWT, pass it in the `Authorization` header of an API request. For example: From e0c8c80982485c06ce7716f0ed8106af533a1fd9 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 16 Apr 2024 13:07:22 -0400 Subject: [PATCH 2/3] Use vitest instead of jest (#50150) --- .github/workflows/headless-tests.yml | 2 +- .github/workflows/test.yml | 2 +- package-lock.json | 1330 ++++++++++++++++- package.json | 49 +- .../tests/deprecated-enterprise-versions.js | 4 +- src/assets/tests/dynamic-assets.js | 5 +- src/assets/tests/static-assets-1.js | 4 +- src/assets/tests/static-assets.js | 4 +- src/audit-logs/tests/rendering.js | 2 +- src/audit-logs/tests/unit/filter-events.js | 2 + .../tests/frontmatter-versions.js | 2 +- src/automated-pipelines/tests/rendering.js | 4 +- .../tests/update-markdown.js | 5 +- src/changelogs/tests/get-rss-feeds.js | 1 + src/color-schemes/tests/use-theme.js | 3 +- src/content-linter/tests/category-pages.js | 15 +- .../tests/learning-track-liquid.js | 2 + src/content-linter/tests/lint-files.js | 292 ++-- .../tests/lint-frontmatter-links.js | 2 + .../tests/site-data-references.js | 4 +- .../tests/unit/code-annotations.js | 2 + .../tests/unit/code-fence-line-length.js | 2 + .../tests/unit/early-access-references.js | 2 + .../tests/unit/expired-content.js | 2 + .../tests/unit/frontmatter-hidden-docs.js | 2 +- .../tests/unit/frontmatter-schema.js | 2 + .../unit/frontmatter-video-transcripts.js | 2 +- .../unit/github-owned-action-references.js | 2 + .../tests/unit/hardcoded-data-variable.js | 2 + .../unit/image-alt-text-end-punctuation.js | 2 + .../image-alt-text-exclude-start-words.js | 2 + .../tests/unit/image-alt-text-length.js | 2 + .../tests/unit/image-file-kebab-case.js | 2 + src/content-linter/tests/unit/image-no-gif.js | 2 + .../tests/unit/internal-links-no-lang.js | 2 + .../tests/unit/internal-links-old-version.js | 2 + .../tests/unit/internal-links-slash.js | 2 + .../tests/unit/link-punctuation.js | 2 + .../tests/unit/liquid-data-tags.js | 2 + .../tests/unit/liquid-ifversion-versions.js | 2 + .../unit/liquid-quoted-conditional-args.js | 2 + .../tests/unit/liquid-syntax.js | 2 + .../tests/unit/liquid-versioning.js | 2 + .../unit/list-first-word-captitalization.js | 2 + .../tests/unit/rai-resuable-usage.js | 2 + .../tests/unit/search-replace.js | 1 + .../tests/unit/yaml-scheduled-jobs.js | 2 + .../tests/__snapshots__/annotate.js.snap | 25 +- src/content-render/tests/annotate.js | 2 + src/content-render/tests/data.js | 2 +- src/content-render/tests/liquid-helpers.js | 5 +- src/content-render/tests/liquid.js | 4 +- src/content-render/tests/octicon.js | 2 + .../tests/render-changed-and-deleted-files.js | 4 +- src/content-render/tests/render-content.js | 2 + src/data-directory/tests/data-schemas.js | 5 +- src/data-directory/tests/filename-to-key.js | 2 + src/data-directory/tests/get-data.js | 4 +- src/data-directory/tests/index.js | 4 + .../tests/early-access-rendering.js | 2 +- src/early-access/tests/early-access-unit.js | 4 +- src/events/tests/hydro.js | 3 +- src/events/tests/middleware-errors.js | 21 +- src/events/tests/middleware.js | 5 +- src/events/tests/user-agent.js | 2 + src/fixtures/PLAYWRIGHT.md | 6 +- src/fixtures/tests/annotations.js | 2 + src/fixtures/tests/bad-urls.js | 2 + src/fixtures/tests/breadcrumbs.js | 2 + .../tests/categories-and-map-topic.js | 2 + src/fixtures/tests/footer.js | 2 + src/fixtures/tests/glossary.js | 2 + src/fixtures/tests/guides.js | 2 + src/fixtures/tests/head.js | 2 + src/fixtures/tests/homepage.js | 2 +- src/fixtures/tests/images.js | 1 + src/fixtures/tests/internal-links.js | 2 + src/fixtures/tests/landing-hero.js | 2 + src/fixtures/tests/liquid.js | 2 + src/fixtures/tests/markdown.js | 2 + src/fixtures/tests/minitoc.js | 2 +- src/fixtures/tests/page-titles.js | 2 + src/fixtures/tests/permissions-callout.js | 2 + src/fixtures/tests/sidebar.js | 2 + src/fixtures/tests/translations.js | 2 +- src/fixtures/tests/versioning.js | 2 + src/fixtures/tests/video-transcripts.js | 2 +- src/frame/tests/api.js | 4 +- src/frame/tests/block-robots.js | 2 + src/frame/tests/content.js | 1 + src/frame/tests/favicons.js | 4 +- src/frame/tests/find-page-middleware.js | 2 +- src/frame/tests/find-page.js | 7 +- src/frame/tests/get-remote-json.js | 3 +- src/frame/tests/gitignore.js | 3 + src/frame/tests/manifest.js | 1 + src/frame/tests/mini-toc-items.js | 3 +- src/frame/tests/next.js | 4 +- src/frame/tests/page.js | 3 +- src/frame/tests/pages.js | 13 +- src/frame/tests/permalink.js | 2 + src/frame/tests/product-icons.js | 4 +- src/frame/tests/read-frontmatter.js | 2 + src/frame/tests/remote-ip.js | 5 +- src/frame/tests/robots-txt.js | 4 +- src/frame/tests/secure-files.js | 1 + src/frame/tests/server.js | 7 +- src/frame/tests/site-tree.js | 4 +- src/frame/tests/toc-links.js | 5 +- .../tests/remove-liquid-statements.js | 5 +- src/github-apps/tests/rendering.js | 7 +- src/graphql/tests/build-changelog.js | 4 +- src/graphql/tests/get-schema-files.js | 3 +- src/graphql/tests/server-rendering.js | 2 + src/graphql/tests/validate-schema.js | 4 +- src/landings/tests/curated-homepage-links.js | 5 +- src/landings/tests/featured-links.js | 4 +- src/landings/tests/homepage.js | 4 +- src/languages/tests/api-search.js | 4 +- src/languages/tests/files.js | 4 +- src/languages/tests/frame.js | 5 +- src/languages/tests/glossary.js | 2 + src/languages/tests/redirects.js | 2 + src/languages/tests/search.js | 2 + src/learning-track/tests/lint-data.js | 2 + src/observability/tests/failbot.js | 4 +- src/pageinfo/tests/pageinfo.js | 2 +- src/products/tests/product-names.js | 2 + src/products/tests/products.js | 2 + .../tests/content/redirect-orphans.js | 4 +- src/redirects/tests/ghae.js | 2 + src/redirects/tests/redirects.js | 5 +- .../tests/routing/developer-site-redirects.js | 6 +- .../tests/routing/redirect-exceptions.js | 5 +- .../top-developer-site-path-redirects.js | 4 +- .../tests/routing/versionless-redirects.js | 4 +- src/redirects/tests/unit/get-redirect.js | 2 +- src/release-notes/tests/release-notes-1.js | 4 +- src/release-notes/tests/release-notes.js | 4 +- src/release-notes/tests/yaml.js | 4 +- src/rest/tests/api.js | 2 +- src/rest/tests/create-rest-examples.js | 3 +- src/rest/tests/get-schema-files.js | 2 +- src/rest/tests/openapi-schema.js | 2 +- src/rest/tests/rendering.js | 4 +- src/search/tests/api-search.js | 6 +- .../tests/parse-page-sections-into-records.js | 2 +- src/search/tests/rendering.js | 4 +- src/search/tests/search.js | 4 +- src/search/tests/topics.js | 5 +- src/shielding/tests/invalid-headers.js | 2 + .../tests/invalid-querystring-values.js | 2 + src/shielding/tests/invalid-querystrings.js | 2 + src/shielding/tests/shielding.js | 2 + src/tests/helpers/caching-headers.js | 2 + src/tests/helpers/conditional-runs.js | 2 + src/tests/vitest.setup.ts | 17 + src/tracking/tests/handle-query-string.js | 3 +- src/versions/tests/enterprise-versions.js | 2 + src/versions/tests/get-applicable-versions.js | 3 +- src/versions/tests/ghes-versioning.js | 2 + src/versions/tests/versions.js | 2 + src/webhooks/tests/api.js | 3 +- src/webhooks/tests/get-schema-files.js | 2 +- src/webhooks/tests/rendering.js | 5 +- src/workflows/tests/actions-workflows.js | 2 + vitest.config.ts | 11 + 167 files changed, 1876 insertions(+), 351 deletions(-) create mode 100644 src/tests/vitest.setup.ts create mode 100644 vitest.config.ts diff --git a/.github/workflows/headless-tests.yml b/.github/workflows/headless-tests.yml index ccb5b5d2c9..29ac7cefe8 100644 --- a/.github/workflows/headless-tests.yml +++ b/.github/workflows/headless-tests.yml @@ -2,7 +2,7 @@ name: Headless Tests # **What it does**: This runs our browser tests to test things that depend # on client-side JavaScript. -# **Why we have it**: Because most automated jest tests only test static +# **Why we have it**: Because most automated vitest tests only test static # input and outputs. # **Who does it impact**: Docs engineering, open-source engineering contributors. diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index add116b530..e15ab0dec1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,7 +19,7 @@ concurrency: cancel-in-progress: true env: - # Setting this will activate the jest tests that depend on actually + # Setting this will activate the vitest tests that depend on actually # sending real search queries to Elasticsearch ELASTICSEARCH_URL: http://localhost:9200/ diff --git a/package-lock.json b/package-lock.json index 9b6301e5df..a6a4800d04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -158,6 +158,7 @@ "typescript": "^5.4.4", "unist-util-remove": "^4.0.0", "unist-util-visit-parents": "6.0.1", + "vitest": "1.5.0", "website-scraper": "^5.3.1" }, "engines": { @@ -3234,6 +3235,214 @@ "@primer/behaviors": "^1.3.4" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.3.tgz", + "integrity": "sha512-X9alQ3XM6I9IlSlmC8ddAvMSyG1WuHk5oUnXGw+yUBs3BFoTizmG1La/Gr8fVJvDWAq+zlYTZ9DBgrlKRVY06g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.3.tgz", + "integrity": "sha512-eQK5JIi+POhFpzk+LnjKIy4Ks+pwJ+NXmPxOCSvOKSNRPONzKuUvWE+P9JxGZVxrtzm6BAYMaL50FFuPe0oWMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.3.tgz", + "integrity": "sha512-Od4vE6f6CTT53yM1jgcLqNfItTsLt5zE46fdPaEmeFHvPs5SjZYlLpHrSiHEKR1+HdRfxuzXHjDOIxQyC3ptBA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.3.tgz", + "integrity": "sha512-0IMAO21axJeNIrvS9lSe/PGthc8ZUS+zC53O0VhF5gMxfmcKAP4ESkKOCwEi6u2asUrt4mQv2rjY8QseIEb1aw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.3.tgz", + "integrity": "sha512-ge2DC7tHRHa3caVEoSbPRJpq7azhG+xYsd6u2MEnJ6XzPSzQsTKyXvh6iWjXRf7Rt9ykIUWHtl0Uz3T6yXPpKw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.14.3.tgz", + "integrity": "sha512-ljcuiDI4V3ySuc7eSk4lQ9wU8J8r8KrOUvB2U+TtK0TiW6OFDmJ+DdIjjwZHIw9CNxzbmXY39wwpzYuFDwNXuw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.3.tgz", + "integrity": "sha512-Eci2us9VTHm1eSyn5/eEpaC7eP/mp5n46gTRB3Aar3BgSvDQGJZuicyq6TsH4HngNBgVqC5sDYxOzTExSU+NjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.3.tgz", + "integrity": "sha512-UrBoMLCq4E92/LCqlh+blpqMz5h1tJttPIniwUgOFJyjWI1qrtrDhhpHPuFxULlUmjFHfloWdixtDhSxJt5iKw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.3.tgz", + "integrity": "sha512-5aRjvsS8q1nWN8AoRfrq5+9IflC3P1leMoy4r2WjXyFqf3qcqsxRCfxtZIV58tCxd+Yv7WELPcO9mY9aeQyAmw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.3.tgz", + "integrity": "sha512-sk/Qh1j2/RJSX7FhEpJn8n0ndxy/uf0kI/9Zc4b1ELhqULVdTfN6HL31CDaTChiBAOgLcsJ1sgVZjWv8XNEsAQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.3.tgz", + "integrity": "sha512-jOO/PEaDitOmY9TgkxF/TQIjXySQe5KVYB57H/8LRP/ux0ZoO8cSHCX17asMSv3ruwslXW/TLBcxyaUzGRHcqg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.3.tgz", + "integrity": "sha512-8ybV4Xjy59xLMyWo3GCfEGqtKV5M5gCSrZlxkPGvEPCGDLNla7v48S662HSGwRd6/2cSneMQWiv+QzcttLrrOA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.3.tgz", + "integrity": "sha512-s+xf1I46trOY10OqAtZ5Rm6lzHre/UiLA1J2uOhCFXWkbZrJRkYBPO6FhvGfHmdtQ3Bx793MNa7LvoWFAm93bg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.3.tgz", + "integrity": "sha512-+4h2WrGOYsOumDQ5S2sYNyhVfrue+9tc9XcLWLh+Kw3UOxAvrfOrSMFon60KspcDdytkNDh7K2Vs6eMaYImAZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.3.tgz", + "integrity": "sha512-T1l7y/bCeL/kUwh9OD4PQT4aM7Bq43vX05htPJJ46RTI4r5KNt6qJRzAfNfM+OYMNEVBWQzR2Gyk+FXLZfogGw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.3.tgz", + "integrity": "sha512-/BypzV0H1y1HzgYpxqRaXGBRqfodgoBBCcsrujT6QRcakDQdfU+Lq9PENPh5jB4I44YWq+0C2eHsHya+nZY1sA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@sideway/address": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", @@ -3501,6 +3710,12 @@ "@types/ms": "*" } }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, "node_modules/@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", @@ -3910,6 +4125,102 @@ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, + "node_modules/@vitest/expect": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.5.0.tgz", + "integrity": "sha512-0pzuCI6KYi2SIC3LQezmxujU9RK/vwC1U9R0rLuGlNGcOuDWxqWKu6nUdFsX9tH1WU0SXtAxToOsEjeUn1s3hA==", + "dev": true, + "dependencies": { + "@vitest/spy": "1.5.0", + "@vitest/utils": "1.5.0", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.5.0.tgz", + "integrity": "sha512-7HWwdxXP5yDoe7DTpbif9l6ZmDwCzcSIK38kTSIt6CFEpMjX4EpCgT6wUmS0xTXqMI6E/ONmfgRKmaujpabjZQ==", + "dev": true, + "dependencies": { + "@vitest/utils": "1.5.0", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/runner/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/snapshot": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.5.0.tgz", + "integrity": "sha512-qpv3fSEuNrhAO3FpH6YYRdaECnnRjg9VxbhdtPwPRnzSfHVXnNzzrpX4cJxqiwgRMo7uRMWDFBlsBq4Cr+rO3A==", + "dev": true, + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.5.0.tgz", + "integrity": "sha512-vu6vi6ew5N5MMHJjD5PoakMRKYdmIrNJmyfkhRpQt5d9Ewhw9nZ5Aqynbi3N61bvk9UvZ5UysMT6ayIrZ8GA9w==", + "dev": true, + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.5.0.tgz", + "integrity": "sha512-BDU0GNL8MWkRkSRdNFvCUCAVOeHaUlVJ9Tx0TYBZyXaaOTmGtUFObzchCivIBrIwKzvZA7A9sCejVhXM2aY98A==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/abbrev": { "version": "1.1.1", "dev": true, @@ -3956,8 +4267,6 @@ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true, - "optional": true, - "peer": true, "engines": { "node": ">=0.4.0" } @@ -4193,6 +4502,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/ast-types-flow": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", @@ -4691,6 +5009,15 @@ "node": ">= 0.8" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/cacheable-lookup": { "version": "7.0.0", "license": "MIT", @@ -4776,6 +5103,24 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/chalk": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", @@ -4828,6 +5173,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, "node_modules/check-more-types": { "version": "2.24.0", "dev": true, @@ -5466,6 +5823,18 @@ "babel-plugin-macros": "^3.1.0" } }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/deep-is": { "version": "0.1.4", "license": "MIT" @@ -6791,6 +7160,15 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "dev": true, @@ -7415,6 +7793,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", @@ -10073,6 +10460,12 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "dev": true + }, "node_modules/jsonfile": { "version": "6.1.0", "dev": true, @@ -10469,6 +10862,22 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/local-pkg": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", + "dev": true, + "dependencies": { + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -10670,6 +11079,15 @@ "loose-envify": "cli.js" } }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, "node_modules/lowdb": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-7.0.1.tgz", @@ -10726,6 +11144,24 @@ "node": ">=10" } }, + "node_modules/magic-string": { + "version": "0.30.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.9.tgz", + "integrity": "sha512-S1+hd+dIrC8EZqKyT9DstTH/0Z+f76kmmvZnkfQVmOpDEF9iVgdYif3Q/pIWHmCoo59bQVGW0kVL3e2nl+9+Sw==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/magic-string/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -11867,6 +12303,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/mlly": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.6.1.tgz", + "integrity": "sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.0.3", + "ufo": "^1.3.2" + } + }, "node_modules/mockdate": { "version": "3.0.5", "dev": true, @@ -11910,9 +12358,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -12579,6 +13027,21 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/pause-stream": { "version": "0.0.11", "dev": true, @@ -12647,6 +13110,17 @@ "node": ">=8" } }, + "node_modules/pkg-types": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", + "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.2.0", + "mlly": "^1.2.0", + "pathe": "^1.1.0" + } + }, "node_modules/playwright": { "version": "1.43.0", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.0.tgz", @@ -14160,6 +14634,41 @@ "node": ">=0.10" } }, + "node_modules/rollup": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.3.tgz", + "integrity": "sha512-ag5tTQKYsj1bhrFC9+OEWqb5O6VYgtQDO9hPDBMmIbePwhfSr+ExlcU741t8Dhw5DkPCQf6noz0jb36D6W9/hw==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.14.3", + "@rollup/rollup-android-arm64": "4.14.3", + "@rollup/rollup-darwin-arm64": "4.14.3", + "@rollup/rollup-darwin-x64": "4.14.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.14.3", + "@rollup/rollup-linux-arm-musleabihf": "4.14.3", + "@rollup/rollup-linux-arm64-gnu": "4.14.3", + "@rollup/rollup-linux-arm64-musl": "4.14.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.14.3", + "@rollup/rollup-linux-riscv64-gnu": "4.14.3", + "@rollup/rollup-linux-s390x-gnu": "4.14.3", + "@rollup/rollup-linux-x64-gnu": "4.14.3", + "@rollup/rollup-linux-x64-musl": "4.14.3", + "@rollup/rollup-win32-arm64-msvc": "4.14.3", + "@rollup/rollup-win32-ia32-msvc": "4.14.3", + "@rollup/rollup-win32-x64-msvc": "4.14.3", + "fsevents": "~2.3.2" + } + }, "node_modules/rss-parser": { "version": "3.13.0", "license": "MIT", @@ -14493,6 +15002,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, "node_modules/signal-exit": { "version": "3.0.7", "license": "ISC" @@ -14586,8 +15101,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "license": "BSD-3-Clause", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "engines": { "node": ">=0.10.0" } @@ -14657,6 +15173,12 @@ "node": ">=8" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, "node_modules/start-server-and-test": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-2.0.3.tgz", @@ -14689,6 +15211,12 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true + }, "node_modules/stdin-discarder": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.1.tgz", @@ -14934,6 +15462,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz", + "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==", + "dev": true, + "dependencies": { + "js-tokens": "^9.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", + "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", + "dev": true + }, "node_modules/strnum": { "version": "1.0.5", "license": "MIT" @@ -15180,6 +15726,30 @@ "dev": true, "license": "MIT" }, + "node_modules/tinybench": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.7.0.tgz", + "integrity": "sha512-Qgayeb106x2o4hNzNjsZEfFziw8IbKqtbXBjVh7VIZfBxfD5M4gWtpyx5+YTae2gJ6Y6Dz/KLepiv16RFeQWNA==", + "dev": true + }, + "node_modules/tinypool": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", + "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -15587,6 +16157,12 @@ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", "dev": true }, + "node_modules/ufo": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", + "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", + "dev": true + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -16120,6 +16696,730 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/vite": { + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.8.tgz", + "integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==", + "dev": true, + "dependencies": { + "esbuild": "^0.20.1", + "postcss": "^8.4.38", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.5.0.tgz", + "integrity": "sha512-tV8h6gMj6vPzVCa7l+VGq9lwoJjW8Y79vst8QZZGiuRAfijU+EEWuc0kFpmndQrWhMMhet1jdSF+40KSZUqIIw==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/vite/node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/vitest": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.5.0.tgz", + "integrity": "sha512-d8UKgR0m2kjdxDWX6911uwxout6GHS0XaGH1cksSIVVG8kRlE7G7aBw7myKQCvDI5dT4j7ZMa+l706BIORMDLw==", + "dev": true, + "dependencies": { + "@vitest/expect": "1.5.0", + "@vitest/runner": "1.5.0", + "@vitest/snapshot": "1.5.0", + "@vitest/spy": "1.5.0", + "@vitest/utils": "1.5.0", + "acorn-walk": "^8.3.2", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.3", + "vite": "^5.0.0", + "vite-node": "1.5.0", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "1.5.0", + "@vitest/ui": "1.5.0", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/vitest/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/vitest/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vitest/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/vitest/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/wait-on": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.2.0.tgz", @@ -16332,6 +17632,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/widest-line": { "version": "4.0.1", "license": "MIT", diff --git a/package.json b/package.json index ccfedfd200..f5c5698c5a 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "index-test-fixtures": "npm run index-elasticsearch -- -l en -l ja -V ghec -V dotcom --index-prefix tests -- src/search/tests/fixtures/search-indexes", "lint": "eslint '**/*.{js,mjs,ts,tsx}'", "lint-content": "node src/content-linter/scripts/lint-content.js", - "lint-translation": "cross-env NODE_OPTIONS=--experimental-vm-modules jest src/content-linter/tests/lint-files.js", + "lint-translation": "cross-env NODE_OPTIONS=--experimental-vm-modules vitest src/content-linter/tests/lint-files.js", "generate-code-scanning-query-list": "tsx src/code-scanning/scripts/generate-code-scanning-query-list.ts", "generate-content-linter-docs": "tsx src/content-linter/scripts/generate-docs.ts", "move-content": "node src/content-render/scripts/move-content.js", @@ -63,10 +63,9 @@ "sync-search-indices": "node src/search/scripts/sync-search-indices.js", "sync-search-server": "cross-env NODE_ENV=production PORT=4002 MINIMAL_RENDER=true CHANGELOG_DISABLED=true tsx src/frame/server.ts", "sync-webhooks": "src/rest/scripts/update-files.js -o webhooks", - "test": "cross-env NODE_OPTIONS='--max_old_space_size=4096 --experimental-vm-modules' jest --logHeapUsage", + "test": "cross-env NODE_OPTIONS='--max_old_space_size=4096 --experimental-vm-modules' vitest", "test-local-dev": "node src/workflows/test-local-dev.js", "test-moved-content": "tsx src/content-render/scripts/test-moved-content.ts", - "test-watch": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --watch --notify --notifyMode=change --coverage", "tsc": "tsc --noEmit", "unallowed-contributions": "node src/workflows/unallowed-contributions.js", "update-data-and-image-paths": "node src/early-access/scripts/update-data-and-image-paths.js", @@ -153,14 +152,6 @@ ] }, "overrides": [ - { - "files": [ - "**/tests/**/*.js" - ], - "env": { - "jest": true - } - }, { "files": [ "**/*.tsx", @@ -197,41 +188,6 @@ "src/code-scanning/scripts/generate-code-scanning-query-list.ts" ] }, - "jest": { - "testTimeout": 30000, - "coverageThreshold": { - "global": { - "branches": 95, - "functions": 95, - "lines": 95, - "statements": -5 - } - }, - "globalSetup": "./src/tests/scripts/start-server-for-jest.js", - "globalTeardown": "./src/tests/scripts/kill-server-for-jest.js", - "moduleNameMapper": { - "@primer/behaviors": "/node_modules/@primer/behaviors/dist/cjs/index.js" - }, - "preset": "ts-jest", - "reporters": [ - "default", - "github-actions" - ], - "setupFilesAfterEnv": [ - "./src/tests/jest.setup.js", - "jest-expect-message" - ], - "testEnvironment": "node", - "testMatch": [ - "**/tests/**/*.js" - ], - "testPathIgnorePatterns": [ - "node_modules/", - "vendor/", - "src/fixtures/fixtures/", - "src/tests/helpers/" - ] - }, "dependencies": { "@elastic/elasticsearch": "8.11.0", "@github/failbot": "0.8.3", @@ -383,6 +339,7 @@ "typescript": "^5.4.4", "unist-util-remove": "^4.0.0", "unist-util-visit-parents": "6.0.1", + "vitest": "1.5.0", "website-scraper": "^5.3.1" }, "overrides": { diff --git a/src/archives/tests/deprecated-enterprise-versions.js b/src/archives/tests/deprecated-enterprise-versions.js index e4c82f1ac3..5a864f0710 100644 --- a/src/archives/tests/deprecated-enterprise-versions.js +++ b/src/archives/tests/deprecated-enterprise-versions.js @@ -1,11 +1,11 @@ -import { describe, jest, test } from '@jest/globals' +import { describe, expect, test, vi } from 'vitest' import enterpriseServerReleases from '#src/versions/lib/enterprise-server-releases.js' import { get, getDOM } from '#src/tests/helpers/e2etest.js' import { SURROGATE_ENUMS } from '#src/frame/middleware/set-fastly-surrogate-key.js' describe('enterprise deprecation', () => { - jest.setTimeout(60 * 1000) + vi.setConfig({ testTimeout: 60 * 1000 }) test('redirects language-prefixed requests for deprecated enterprise content', async () => { const res = await get('/en/enterprise/2.12') diff --git a/src/assets/tests/dynamic-assets.js b/src/assets/tests/dynamic-assets.js index 907c5eacf0..7c6b0c4094 100644 --- a/src/assets/tests/dynamic-assets.js +++ b/src/assets/tests/dynamic-assets.js @@ -1,4 +1,5 @@ -import { jest } from '@jest/globals' +import { describe, expect, test, vi } from 'vitest' + import sharp from 'sharp' import { fileTypeFromBuffer } from 'file-type' @@ -6,7 +7,7 @@ import { SURROGATE_ENUMS } from '#src/frame/middleware/set-fastly-surrogate-key. import { get, head } from '#src/tests/helpers/e2etest.js' describe('dynamic assets', () => { - jest.setTimeout(3 * 60 * 1000) + vi.setConfig({ testTimeout: 3 * 60 * 1000 }) test('GET PNG as a WebP', async () => { const res = await get('/assets/images/_fixtures/screenshot.webp', { diff --git a/src/assets/tests/static-assets-1.js b/src/assets/tests/static-assets-1.js index b28989700c..ee15444850 100644 --- a/src/assets/tests/static-assets-1.js +++ b/src/assets/tests/static-assets-1.js @@ -1,5 +1,5 @@ +import { afterAll, beforeAll, describe, expect, test, vi } from 'vitest' import nock from 'nock' -import { expect, jest } from '@jest/globals' import { checkCachingHeaders } from '#src/tests/helpers/caching-headers.js' import { setDefaultFastlySurrogateKey } from '#src/frame/middleware/set-fastly-surrogate-key.js' @@ -57,7 +57,7 @@ describe('archived enterprise static assets', () => { // Sometimes static assets are proxied. The URL for the static asset // might not indicate it's based on archived enterprise version. - jest.setTimeout(60 * 1000) + vi.setConfig({ testTimeout: 60 * 1000 }) beforeAll(async () => { // The first page load takes a long time so let's get it out of the way in diff --git a/src/assets/tests/static-assets.js b/src/assets/tests/static-assets.js index 437cfe7834..1c46bfa078 100644 --- a/src/assets/tests/static-assets.js +++ b/src/assets/tests/static-assets.js @@ -1,7 +1,7 @@ import fs from 'fs' import path from 'path' -import { jest, expect } from '@jest/globals' +import { describe, expect, test, vi } from 'vitest' import { get } from '#src/tests/helpers/e2etest.js' import { checkCachingHeaders } from '#src/tests/helpers/caching-headers.js' @@ -14,7 +14,7 @@ function getNextStaticAsset(directory) { } describe('static assets', () => { - jest.setTimeout(60 * 1000) + vi.setConfig({ testTimeout: 60 * 1000 }) test('should serve /assets/cb-* with optimal headers', async () => { const res = await get('/assets/cb-1234/images/site/logo.png') diff --git a/src/audit-logs/tests/rendering.js b/src/audit-logs/tests/rendering.js index ddc9434ecf..23240b7f79 100644 --- a/src/audit-logs/tests/rendering.js +++ b/src/audit-logs/tests/rendering.js @@ -1,4 +1,4 @@ -import { expect } from '@jest/globals' +import { describe, expect, test } from 'vitest' import { getDOM } from '#src/tests/helpers/e2etest.js' import { allVersions } from '#src/versions/lib/all-versions.js' diff --git a/src/audit-logs/tests/unit/filter-events.js b/src/audit-logs/tests/unit/filter-events.js index c0b69aacbe..8131c63c01 100644 --- a/src/audit-logs/tests/unit/filter-events.js +++ b/src/audit-logs/tests/unit/filter-events.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { filterByAllowlistValues, filterAndUpdateGhesDataByAllowlistValues, diff --git a/src/automated-pipelines/tests/frontmatter-versions.js b/src/automated-pipelines/tests/frontmatter-versions.js index ff451e1f5f..5735debce8 100644 --- a/src/automated-pipelines/tests/frontmatter-versions.js +++ b/src/automated-pipelines/tests/frontmatter-versions.js @@ -1,4 +1,4 @@ -import { describe, expect } from '@jest/globals' +import { describe, expect, test } from 'vitest' import { supported } from '#src/versions/lib/enterprise-server-releases.js' import { allVersionKeys, allVersions } from '#src/versions/lib/all-versions.js' diff --git a/src/automated-pipelines/tests/rendering.js b/src/automated-pipelines/tests/rendering.js index 89f5ffbd02..1f287fa1fe 100644 --- a/src/automated-pipelines/tests/rendering.js +++ b/src/automated-pipelines/tests/rendering.js @@ -1,7 +1,7 @@ import { readFileSync } from 'fs' import cheerio from 'cheerio' -import { jest, test } from '@jest/globals' +import { describe, expect, test, vi } from 'vitest' import { loadPages } from '#src/frame/lib/page-data.js' import { get } from '#src/tests/helpers/e2etest.js' @@ -10,7 +10,7 @@ import { get } from '#src/tests/helpers/e2etest.js' const pageList = await loadPages(undefined, ['en']) describe('autogenerated docs render', () => { - jest.setTimeout(3 * 60 * 1000) + vi.setConfig({ testTimeout: 3 * 60 * 1000 }) const autogeneratedPages = pageList.filter((page) => page.autogenerated) diff --git a/src/automated-pipelines/tests/update-markdown.js b/src/automated-pipelines/tests/update-markdown.js index 213fbd4bfb..a77feb5ae6 100644 --- a/src/automated-pipelines/tests/update-markdown.js +++ b/src/automated-pipelines/tests/update-markdown.js @@ -1,9 +1,10 @@ -import { expect } from '@jest/globals' import { tmpdir } from 'os' -import { mkdirp } from 'mkdirp' import { cp, rm, readFile } from 'fs/promises' import { existsSync } from 'fs' import path from 'path' + +import { afterAll, beforeAll, describe, expect, test } from 'vitest' +import { mkdirp } from 'mkdirp' import matter from 'gray-matter' import { updateContentDirectory } from '../lib/update-markdown.js' diff --git a/src/changelogs/tests/get-rss-feeds.js b/src/changelogs/tests/get-rss-feeds.js index d491cbc220..6001149fd0 100644 --- a/src/changelogs/tests/get-rss-feeds.js +++ b/src/changelogs/tests/get-rss-feeds.js @@ -2,6 +2,7 @@ import fs from 'fs/promises' import path from 'path' import nock from 'nock' +import { afterAll, beforeAll, describe, expect, test } from 'vitest' import { getChangelogItems } from '#src/changelogs/lib/changelog.js' diff --git a/src/color-schemes/tests/use-theme.js b/src/color-schemes/tests/use-theme.js index ce757d1a27..307da9fe4d 100644 --- a/src/color-schemes/tests/use-theme.js +++ b/src/color-schemes/tests/use-theme.js @@ -1,4 +1,5 @@ -import { describe, expect, test } from '@jest/globals' +import { describe, expect, test } from 'vitest' + import { getComponentTheme, getCssTheme, diff --git a/src/content-linter/tests/category-pages.js b/src/content-linter/tests/category-pages.js index 03505601d8..a76c4bf2ef 100644 --- a/src/content-linter/tests/category-pages.js +++ b/src/content-linter/tests/category-pages.js @@ -1,9 +1,11 @@ import path from 'path' import fs from 'fs' + import walk from 'walk-sync' import { zip, difference } from 'lodash-es' import GithubSlugger from 'github-slugger' import { decode } from 'html-entities' +import { beforeAll, describe, expect, test } from 'vitest' import matter from '#src/frame/lib/read-frontmatter.js' import { renderContent } from '#src/content-render/index.js' @@ -33,10 +35,13 @@ describe('category pages', () => { const productIndices = walk(contentDir, walkOptions) const productNames = productIndices.map((index) => path.basename(path.dirname(index))) - // Combine those to fit Jest's `.each` usage + // Combine those to fit vitest's `.each` usage const productTuples = zip(productNames, productIndices) - describe.each(productTuples)('product "%s"', (productName, productIndex) => { + // Use a regular forEach loop to generate the `describe(...)` blocks + // otherwise, if one of them has no categories, the tests will fail. + productTuples.forEach((tuple) => { + const [, productIndex] = tuple // Get links included in product index page. // Each link corresponds to a product subdirectory (category). // Example: "getting-started-with-github" @@ -48,7 +53,7 @@ describe('category pages', () => { const categoryLinks = data.children // Only include category directories, not standalone category files like content/actions/quickstart.md .filter((link) => fs.existsSync(getPath(productDir, link, 'index'))) - // TODO this should move to async, but you can't asynchronously define tests with Jest... + // TODO this should move to async, but you can't asynchronously define tests with vitest... // Map those to the Markdown file paths that represent that category page index const categoryPaths = categoryLinks.map((link) => getPath(productDir, link, 'index')) @@ -56,11 +61,9 @@ describe('category pages', () => { // Make them relative for nicer display in test names const categoryRelativePaths = categoryPaths.map((p) => path.relative(contentDir, p)) - // Combine those to fit Jest's `.each` usage + // Combine those to fit vitests's `.each` usage const categoryTuples = zip(categoryRelativePaths, categoryPaths, categoryLinks) - if (!categoryTuples.length) return - describe.each(categoryTuples)( 'category index "%s"', (indexRelPath, indexAbsPath, indexLink) => { diff --git a/src/content-linter/tests/learning-track-liquid.js b/src/content-linter/tests/learning-track-liquid.js index d913d17629..efdfc27b6e 100644 --- a/src/content-linter/tests/learning-track-liquid.js +++ b/src/content-linter/tests/learning-track-liquid.js @@ -1,6 +1,8 @@ import yaml from 'js-yaml' import { readFile } from 'fs/promises' + import walk from 'walk-sync' +import { beforeAll, describe, expect, test } from 'vitest' import { liquid } from '#src/content-render/index.js' diff --git a/src/content-linter/tests/lint-files.js b/src/content-linter/tests/lint-files.js index 5bb2a7fb53..7755be1fa3 100755 --- a/src/content-linter/tests/lint-files.js +++ b/src/content-linter/tests/lint-files.js @@ -1,10 +1,12 @@ import { fileURLToPath } from 'url' import path from 'path' +import yaml from 'js-yaml' +import fs from 'fs/promises' + import slash from 'slash' import walk from 'walk-sync' import { zip } from 'lodash-es' -import yaml from 'js-yaml' -import fs from 'fs/promises' +import { beforeAll, describe, expect, test } from 'vitest' import languages from '#src/languages/lib/languages.js' import { getDiffFiles } from '../lib/diff-files.js' @@ -235,198 +237,198 @@ if (ymlToLint.length === 0) { describe('deliberately do nothing', () => { test('void', () => {}) }) -} +} else { + describe('lint yaml content', () => { + if (ymlToLint.length < 1) return + describe.each(ymlToLint)('%s', (yamlRelPath, yamlAbsPath) => { + let dictionary, isEarlyAccess, fileContents + // This variable is used to determine if the file was parsed successfully. + // When `yaml.load()` fails to parse the file, it is overwritten with the error message. + // `false` is intentionally chosen since `null` and `undefined` are valid return values. + let dictionaryError = false -describe('lint yaml content', () => { - if (ymlToLint.length < 1) return - describe.each(ymlToLint)('%s', (yamlRelPath, yamlAbsPath) => { - let dictionary, isEarlyAccess, fileContents - // This variable is used to determine if the file was parsed successfully. - // When `yaml.load()` fails to parse the file, it is overwritten with the error message. - // `false` is intentionally chosen since `null` and `undefined` are valid return values. - let dictionaryError = false + beforeAll(async () => { + fileContents = await fs.readFile(yamlAbsPath, 'utf8') + try { + dictionary = yaml.load(fileContents, { filename: yamlRelPath }) + } catch (error) { + dictionaryError = error + } - beforeAll(async () => { - fileContents = await fs.readFile(yamlAbsPath, 'utf8') - try { - dictionary = yaml.load(fileContents, { filename: yamlRelPath }) - } catch (error) { - dictionaryError = error - } + isEarlyAccess = yamlRelPath.split('/').includes('early-access') + }) - isEarlyAccess = yamlRelPath.split('/').includes('early-access') - }) + test('it can be parsed as a single yaml document', () => { + expect(dictionaryError).toBe(false) + }) - test('it can be parsed as a single yaml document', () => { - expect(dictionaryError).toBe(false) - }) - - test('placeholder string is not present in any yaml files', () => { - const matches = fileContents.match(placeholderRegex) || [] - const errorMessage = ` + test('placeholder string is not present in any yaml files', () => { + const matches = fileContents.match(placeholderRegex) || [] + const errorMessage = ` Found ${matches.length} placeholder string '${placeholder}'! Please update all placeholders. ` - expect(matches.length, errorMessage).toBe(0) - }) + expect(matches.length, errorMessage).toBe(0) + }) - test('relative URLs must start with "/"', async () => { - const matches = [] - - for (const [key, content] of Object.entries(dictionary)) { - const contentStr = getContent(content) - if (!contentStr) continue - const valMatches = contentStr.match(relativeArticleLinkRegex) || [] - if (valMatches.length > 0) { - matches.push(...valMatches.map((match) => `Key "${key}": ${match}`)) - } - } - - const errorMessage = formatLinkError(relativeArticleLinkErrorText, matches) - expect(matches.length, errorMessage).toBe(0) - }) - - test('must not leak Early Access doc URLs', async () => { - // Only execute for docs that are NOT Early Access - if (!isEarlyAccess) { + test('relative URLs must start with "/"', async () => { const matches = [] for (const [key, content] of Object.entries(dictionary)) { const contentStr = getContent(content) if (!contentStr) continue - const valMatches = contentStr.match(earlyAccessLinkRegex) || [] + const valMatches = contentStr.match(relativeArticleLinkRegex) || [] if (valMatches.length > 0) { matches.push(...valMatches.map((match) => `Key "${key}": ${match}`)) } } - const errorMessage = formatLinkError(earlyAccessLinkErrorText, matches) + const errorMessage = formatLinkError(relativeArticleLinkErrorText, matches) expect(matches.length, errorMessage).toBe(0) - } - }) + }) - test('must not leak Early Access image URLs', async () => { - // Only execute for docs that are NOT Early Access - if (!isEarlyAccess) { + test('must not leak Early Access doc URLs', async () => { + // Only execute for docs that are NOT Early Access + if (!isEarlyAccess) { + const matches = [] + + for (const [key, content] of Object.entries(dictionary)) { + const contentStr = getContent(content) + if (!contentStr) continue + const valMatches = contentStr.match(earlyAccessLinkRegex) || [] + if (valMatches.length > 0) { + matches.push(...valMatches.map((match) => `Key "${key}": ${match}`)) + } + } + + const errorMessage = formatLinkError(earlyAccessLinkErrorText, matches) + expect(matches.length, errorMessage).toBe(0) + } + }) + + test('must not leak Early Access image URLs', async () => { + // Only execute for docs that are NOT Early Access + if (!isEarlyAccess) { + const matches = [] + + for (const [key, content] of Object.entries(dictionary)) { + const contentStr = getContent(content) + if (!contentStr) continue + const valMatches = contentStr.match(earlyAccessImageRegex) || [] + if (valMatches.length > 0) { + matches.push(...valMatches.map((match) => `Key "${key}": ${match}`)) + } + } + + const errorMessage = formatLinkError(earlyAccessImageErrorText, matches) + expect(matches.length, errorMessage).toBe(0) + } + }) + + test('must have correctly formatted Early Access image URLs', async () => { + // Execute for ALL docs (not just Early Access) to ensure non-EA docs + // are not leaking incorrectly formatted EA image URLs const matches = [] for (const [key, content] of Object.entries(dictionary)) { const contentStr = getContent(content) if (!contentStr) continue - const valMatches = contentStr.match(earlyAccessImageRegex) || [] + const valMatches = contentStr.match(badEarlyAccessImageRegex) || [] if (valMatches.length > 0) { matches.push(...valMatches.map((match) => `Key "${key}": ${match}`)) } } - const errorMessage = formatLinkError(earlyAccessImageErrorText, matches) + const errorMessage = formatLinkError(badEarlyAccessImageErrorText, matches) expect(matches.length, errorMessage).toBe(0) - } - }) + }) - test('must have correctly formatted Early Access image URLs', async () => { - // Execute for ALL docs (not just Early Access) to ensure non-EA docs - // are not leaking incorrectly formatted EA image URLs - const matches = [] + test('URLs must not contain a hard-coded language code', async () => { + const matches = [] - for (const [key, content] of Object.entries(dictionary)) { - const contentStr = getContent(content) - if (!contentStr) continue - const valMatches = contentStr.match(badEarlyAccessImageRegex) || [] - if (valMatches.length > 0) { - matches.push(...valMatches.map((match) => `Key "${key}": ${match}`)) + for (const [key, content] of Object.entries(dictionary)) { + const contentStr = getContent(content) + if (!contentStr) continue + const valMatches = contentStr.match(languageLinkRegex) || [] + if (valMatches.length > 0) { + matches.push(...valMatches.map((match) => `Key "${key}": ${match}`)) + } } - } - const errorMessage = formatLinkError(badEarlyAccessImageErrorText, matches) - expect(matches.length, errorMessage).toBe(0) - }) + const errorMessage = formatLinkError(languageLinkErrorText, matches) + expect(matches.length, errorMessage).toBe(0) + }) - test('URLs must not contain a hard-coded language code', async () => { - const matches = [] + test('URLs must not contain a hard-coded version number', async () => { + const matches = [] - for (const [key, content] of Object.entries(dictionary)) { - const contentStr = getContent(content) - if (!contentStr) continue - const valMatches = contentStr.match(languageLinkRegex) || [] - if (valMatches.length > 0) { - matches.push(...valMatches.map((match) => `Key "${key}": ${match}`)) + for (const [key, content] of Object.entries(dictionary)) { + const contentStr = getContent(content) + if (!contentStr) continue + const valMatches = contentStr.match(versionLinkRegEx) || [] + if (valMatches.length > 0) { + matches.push(...valMatches.map((match) => `Key "${key}": ${match}`)) + } } - } - const errorMessage = formatLinkError(languageLinkErrorText, matches) - expect(matches.length, errorMessage).toBe(0) - }) + const errorMessage = formatLinkError(versionLinkErrorText, matches) + expect(matches.length, errorMessage).toBe(0) + }) - test('URLs must not contain a hard-coded version number', async () => { - const matches = [] + test('URLs must not contain a hard-coded domain name', async () => { + const matches = [] - for (const [key, content] of Object.entries(dictionary)) { - const contentStr = getContent(content) - if (!contentStr) continue - const valMatches = contentStr.match(versionLinkRegEx) || [] - if (valMatches.length > 0) { - matches.push(...valMatches.map((match) => `Key "${key}": ${match}`)) + for (const [key, content] of Object.entries(dictionary)) { + const contentStr = getContent(content) + if (!contentStr) continue + const valMatches = contentStr.match(domainLinkRegex) || [] + if (valMatches.length > 0) { + matches.push(...valMatches.map((match) => `Key "${key}": ${match}`)) + } } - } - const errorMessage = formatLinkError(versionLinkErrorText, matches) - expect(matches.length, errorMessage).toBe(0) - }) + const errorMessage = formatLinkError(domainLinkErrorText, matches) + expect(matches.length, errorMessage).toBe(0) + }) - test('URLs must not contain a hard-coded domain name', async () => { - const matches = [] + test('does not use old site.data variable syntax', async () => { + const matches = [] - for (const [key, content] of Object.entries(dictionary)) { - const contentStr = getContent(content) - if (!contentStr) continue - const valMatches = contentStr.match(domainLinkRegex) || [] - if (valMatches.length > 0) { - matches.push(...valMatches.map((match) => `Key "${key}": ${match}`)) + for (const [key, content] of Object.entries(dictionary)) { + const contentStr = getContent(content) + if (!contentStr) continue + const valMatches = contentStr.match(oldVariableRegex) || [] + if (valMatches.length > 0) { + matches.push( + ...valMatches.map((match) => { + const example = match.replace( + /{{\s*?site\.data\.([a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]+)+)\s*?}}/g, + '{% data $1 %}', + ) + return `Key "${key}": ${match} => ${example}` + }), + ) + } } - } - const errorMessage = formatLinkError(domainLinkErrorText, matches) - expect(matches.length, errorMessage).toBe(0) - }) + const errorMessage = formatLinkError(oldVariableErrorText, matches) + expect(matches.length, errorMessage).toBe(0) + }) - test('does not use old site.data variable syntax', async () => { - const matches = [] + test('does not use old octicon variable syntax', async () => { + const matches = [] - for (const [key, content] of Object.entries(dictionary)) { - const contentStr = getContent(content) - if (!contentStr) continue - const valMatches = contentStr.match(oldVariableRegex) || [] - if (valMatches.length > 0) { - matches.push( - ...valMatches.map((match) => { - const example = match.replace( - /{{\s*?site\.data\.([a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]+)+)\s*?}}/g, - '{% data $1 %}', - ) - return `Key "${key}": ${match} => ${example}` - }), - ) + for (const [key, content] of Object.entries(dictionary)) { + const contentStr = getContent(content) + if (!contentStr) continue + const valMatches = contentStr.match(oldOcticonRegex) || [] + if (valMatches.length > 0) { + matches.push(...valMatches.map((match) => `Key "${key}": ${match}`)) + } } - } - const errorMessage = formatLinkError(oldVariableErrorText, matches) - expect(matches.length, errorMessage).toBe(0) - }) - - test('does not use old octicon variable syntax', async () => { - const matches = [] - - for (const [key, content] of Object.entries(dictionary)) { - const contentStr = getContent(content) - if (!contentStr) continue - const valMatches = contentStr.match(oldOcticonRegex) || [] - if (valMatches.length > 0) { - matches.push(...valMatches.map((match) => `Key "${key}": ${match}`)) - } - } - - const errorMessage = formatLinkError(oldOcticonErrorText, matches) - expect(matches.length, errorMessage).toBe(0) + const errorMessage = formatLinkError(oldOcticonErrorText, matches) + expect(matches.length, errorMessage).toBe(0) + }) }) }) -}) +} diff --git a/src/content-linter/tests/lint-frontmatter-links.js b/src/content-linter/tests/lint-frontmatter-links.js index 968788ffab..39f7daa74c 100644 --- a/src/content-linter/tests/lint-frontmatter-links.js +++ b/src/content-linter/tests/lint-frontmatter-links.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { loadPages, loadPageMap } from '#src/frame/lib/page-data.js' import loadRedirects from '#src/redirects/lib/precompile.js' import { checkURL } from '#src/tests/helpers/check-url.js' diff --git a/src/content-linter/tests/site-data-references.js b/src/content-linter/tests/site-data-references.js index 2b8de958ae..8e040b0940 100644 --- a/src/content-linter/tests/site-data-references.js +++ b/src/content-linter/tests/site-data-references.js @@ -1,6 +1,6 @@ import path from 'path' import { isEqual, uniqWith } from 'lodash-es' -import { jest } from '@jest/globals' +import { describe, expect, test, vi } from 'vitest' import patterns from '#src/frame/lib/patterns.js' import { getDataByLanguage, getDeepDataByLanguage } from '#src/data-directory/lib/get-data.js' @@ -30,7 +30,7 @@ const getDataReferences = (content) => { } describe('data references', () => { - jest.setTimeout(60 * 1000) + vi.setConfig({ testTimeout: 60 * 1000 }) test('every data reference found in English variable files is defined and has a value', async () => { let errors = [] diff --git a/src/content-linter/tests/unit/code-annotations.js b/src/content-linter/tests/unit/code-annotations.js index a5e0301340..44bca5ca14 100644 --- a/src/content-linter/tests/unit/code-annotations.js +++ b/src/content-linter/tests/unit/code-annotations.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { codeAnnotations } from '../../lib/linting-rules/code-annotations.js' diff --git a/src/content-linter/tests/unit/code-fence-line-length.js b/src/content-linter/tests/unit/code-fence-line-length.js index f923d7e259..4790d49a57 100644 --- a/src/content-linter/tests/unit/code-fence-line-length.js +++ b/src/content-linter/tests/unit/code-fence-line-length.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { codeFenceLineLength } from '../../lib/linting-rules/code-fence-line-length.js' diff --git a/src/content-linter/tests/unit/early-access-references.js b/src/content-linter/tests/unit/early-access-references.js index f6f76fff8a..437b03fbeb 100644 --- a/src/content-linter/tests/unit/early-access-references.js +++ b/src/content-linter/tests/unit/early-access-references.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { earlyAccessReferences, diff --git a/src/content-linter/tests/unit/expired-content.js b/src/content-linter/tests/unit/expired-content.js index 93fd105737..72808f3759 100644 --- a/src/content-linter/tests/unit/expired-content.js +++ b/src/content-linter/tests/unit/expired-content.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { expiredContent, diff --git a/src/content-linter/tests/unit/frontmatter-hidden-docs.js b/src/content-linter/tests/unit/frontmatter-hidden-docs.js index 3860b15be7..659f13c12e 100644 --- a/src/content-linter/tests/unit/frontmatter-hidden-docs.js +++ b/src/content-linter/tests/unit/frontmatter-hidden-docs.js @@ -1,4 +1,4 @@ -import { expect } from '@jest/globals' +import { describe, expect, test } from 'vitest' import { runRule } from '../../lib/init-test.js' import { frontmatterHiddenDocs } from '../../lib/linting-rules/frontmatter-hidden-docs.js' diff --git a/src/content-linter/tests/unit/frontmatter-schema.js b/src/content-linter/tests/unit/frontmatter-schema.js index 7925d1490c..f909ae8950 100644 --- a/src/content-linter/tests/unit/frontmatter-schema.js +++ b/src/content-linter/tests/unit/frontmatter-schema.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { frontmatterSchema } from '../../lib/linting-rules/frontmatter-schema.js' diff --git a/src/content-linter/tests/unit/frontmatter-video-transcripts.js b/src/content-linter/tests/unit/frontmatter-video-transcripts.js index a5158da1a4..5b22da8968 100644 --- a/src/content-linter/tests/unit/frontmatter-video-transcripts.js +++ b/src/content-linter/tests/unit/frontmatter-video-transcripts.js @@ -1,4 +1,4 @@ -import { expect } from '@jest/globals' +import { describe, expect, test } from 'vitest' import { runRule } from '../../lib/init-test.js' import { frontmatterVideoTranscripts } from '../../lib/linting-rules/frontmatter-video-transcripts.js' diff --git a/src/content-linter/tests/unit/github-owned-action-references.js b/src/content-linter/tests/unit/github-owned-action-references.js index 9a98d83a7a..44680913f6 100644 --- a/src/content-linter/tests/unit/github-owned-action-references.js +++ b/src/content-linter/tests/unit/github-owned-action-references.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { githubOwnedActionReferences } from '../../lib/linting-rules/github-owned-action-references.js' diff --git a/src/content-linter/tests/unit/hardcoded-data-variable.js b/src/content-linter/tests/unit/hardcoded-data-variable.js index 2f539afdb6..7703ae3974 100644 --- a/src/content-linter/tests/unit/hardcoded-data-variable.js +++ b/src/content-linter/tests/unit/hardcoded-data-variable.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { hardcodedDataVariable } from '../../lib/linting-rules/hardcoded-data-variable.js' diff --git a/src/content-linter/tests/unit/image-alt-text-end-punctuation.js b/src/content-linter/tests/unit/image-alt-text-end-punctuation.js index f7d73052a8..04a50f614a 100644 --- a/src/content-linter/tests/unit/image-alt-text-end-punctuation.js +++ b/src/content-linter/tests/unit/image-alt-text-end-punctuation.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { imageAltTextEndPunctuation } from '../../lib/linting-rules/image-alt-text-end-punctuation.js' diff --git a/src/content-linter/tests/unit/image-alt-text-exclude-start-words.js b/src/content-linter/tests/unit/image-alt-text-exclude-start-words.js index eb1f00b128..819290f981 100644 --- a/src/content-linter/tests/unit/image-alt-text-exclude-start-words.js +++ b/src/content-linter/tests/unit/image-alt-text-exclude-start-words.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { imageAltTextExcludeStartWords } from '../../lib/linting-rules/image-alt-text-exclude-start-words.js' diff --git a/src/content-linter/tests/unit/image-alt-text-length.js b/src/content-linter/tests/unit/image-alt-text-length.js index 5bfcba844b..6e2c010a65 100644 --- a/src/content-linter/tests/unit/image-alt-text-length.js +++ b/src/content-linter/tests/unit/image-alt-text-length.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { incorrectAltTextLength } from '../../lib/linting-rules/image-alt-text-length.js' diff --git a/src/content-linter/tests/unit/image-file-kebab-case.js b/src/content-linter/tests/unit/image-file-kebab-case.js index e1ecb5754d..d724925a19 100644 --- a/src/content-linter/tests/unit/image-file-kebab-case.js +++ b/src/content-linter/tests/unit/image-file-kebab-case.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { imageFileKebabCase } from '../../lib/linting-rules/image-file-kebab-case.js' diff --git a/src/content-linter/tests/unit/image-no-gif.js b/src/content-linter/tests/unit/image-no-gif.js index 45595be29f..90d23a2814 100644 --- a/src/content-linter/tests/unit/image-no-gif.js +++ b/src/content-linter/tests/unit/image-no-gif.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { imageNoGif } from '../../lib/linting-rules/image-no-gif.js' diff --git a/src/content-linter/tests/unit/internal-links-no-lang.js b/src/content-linter/tests/unit/internal-links-no-lang.js index 89c51143b6..5553ed68ca 100644 --- a/src/content-linter/tests/unit/internal-links-no-lang.js +++ b/src/content-linter/tests/unit/internal-links-no-lang.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { internalLinksNoLang } from '../../lib/linting-rules/internal-links-no-lang.js' diff --git a/src/content-linter/tests/unit/internal-links-old-version.js b/src/content-linter/tests/unit/internal-links-old-version.js index 0174e5d178..bbbb317787 100644 --- a/src/content-linter/tests/unit/internal-links-old-version.js +++ b/src/content-linter/tests/unit/internal-links-old-version.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { internalLinksOldVersion } from '../../lib/linting-rules/internal-links-old-version.js' diff --git a/src/content-linter/tests/unit/internal-links-slash.js b/src/content-linter/tests/unit/internal-links-slash.js index 9947da9477..c96c152836 100755 --- a/src/content-linter/tests/unit/internal-links-slash.js +++ b/src/content-linter/tests/unit/internal-links-slash.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { internalLinksSlash } from '../../lib/linting-rules/internal-links-slash.js' diff --git a/src/content-linter/tests/unit/link-punctuation.js b/src/content-linter/tests/unit/link-punctuation.js index 3184d66cac..676124ba88 100644 --- a/src/content-linter/tests/unit/link-punctuation.js +++ b/src/content-linter/tests/unit/link-punctuation.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { linkPunctuation } from '../../lib/linting-rules/link-punctuation.js' diff --git a/src/content-linter/tests/unit/liquid-data-tags.js b/src/content-linter/tests/unit/liquid-data-tags.js index f427df805c..68dceab5af 100644 --- a/src/content-linter/tests/unit/liquid-data-tags.js +++ b/src/content-linter/tests/unit/liquid-data-tags.js @@ -1,5 +1,7 @@ import path from 'path' +import { afterAll, beforeAll, describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { liquidDataReferencesDefined, diff --git a/src/content-linter/tests/unit/liquid-ifversion-versions.js b/src/content-linter/tests/unit/liquid-ifversion-versions.js index 4250c5f918..5961f367f2 100644 --- a/src/content-linter/tests/unit/liquid-ifversion-versions.js +++ b/src/content-linter/tests/unit/liquid-ifversion-versions.js @@ -1,3 +1,5 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { liquidIfVersionVersions, diff --git a/src/content-linter/tests/unit/liquid-quoted-conditional-args.js b/src/content-linter/tests/unit/liquid-quoted-conditional-args.js index 793a6972ef..f265accdc9 100644 --- a/src/content-linter/tests/unit/liquid-quoted-conditional-args.js +++ b/src/content-linter/tests/unit/liquid-quoted-conditional-args.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { liquidQuotedConditionalArg } from '../../lib/linting-rules/liquid-quoted-conditional-arg.js' diff --git a/src/content-linter/tests/unit/liquid-syntax.js b/src/content-linter/tests/unit/liquid-syntax.js index f1e4109ab6..eb054f2d7a 100644 --- a/src/content-linter/tests/unit/liquid-syntax.js +++ b/src/content-linter/tests/unit/liquid-syntax.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { frontmatterLiquidSyntax, liquidSyntax } from '../../lib/linting-rules/liquid-syntax.js' diff --git a/src/content-linter/tests/unit/liquid-versioning.js b/src/content-linter/tests/unit/liquid-versioning.js index e93b0cbfd4..890209c783 100644 --- a/src/content-linter/tests/unit/liquid-versioning.js +++ b/src/content-linter/tests/unit/liquid-versioning.js @@ -1,5 +1,7 @@ import path from 'path' +import { afterAll, beforeAll, describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { liquidIfTags, liquidIfVersionTags } from '../../lib/linting-rules/liquid-versioning.js' import { nextNext } from '#src/versions/lib/enterprise-server-releases.js' diff --git a/src/content-linter/tests/unit/list-first-word-captitalization.js b/src/content-linter/tests/unit/list-first-word-captitalization.js index 89e7d3e915..780bac0919 100644 --- a/src/content-linter/tests/unit/list-first-word-captitalization.js +++ b/src/content-linter/tests/unit/list-first-word-captitalization.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { listFirstWordCapitalization } from '../../lib/linting-rules/list-first-word-capitalization.js' diff --git a/src/content-linter/tests/unit/rai-resuable-usage.js b/src/content-linter/tests/unit/rai-resuable-usage.js index dfd7f132b0..7668cb4f74 100644 --- a/src/content-linter/tests/unit/rai-resuable-usage.js +++ b/src/content-linter/tests/unit/rai-resuable-usage.js @@ -1,3 +1,5 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { raiReusableUsage } from '../../lib/linting-rules/rai-reusable-usage.js' diff --git a/src/content-linter/tests/unit/search-replace.js b/src/content-linter/tests/unit/search-replace.js index 952eca2aa0..71d3a917ff 100644 --- a/src/content-linter/tests/unit/search-replace.js +++ b/src/content-linter/tests/unit/search-replace.js @@ -1,3 +1,4 @@ +import { describe, expect, test } from 'vitest' import searchReplace from 'markdownlint-rule-search-replace' import { runRule } from '../../lib/init-test.js' diff --git a/src/content-linter/tests/unit/yaml-scheduled-jobs.js b/src/content-linter/tests/unit/yaml-scheduled-jobs.js index 0c2b62c5da..97dde53fc4 100644 --- a/src/content-linter/tests/unit/yaml-scheduled-jobs.js +++ b/src/content-linter/tests/unit/yaml-scheduled-jobs.js @@ -1,3 +1,5 @@ +import { describe, expect, test } from 'vitest' + import { runRule } from '../../lib/init-test.js' import { yamlScheduledJobs } from '../../lib/linting-rules/yaml-scheduled-jobs.js' diff --git a/src/content-render/tests/__snapshots__/annotate.js.snap b/src/content-render/tests/__snapshots__/annotate.js.snap index b80b9564e6..6cae4edfc7 100644 --- a/src/content-render/tests/__snapshots__/annotate.js.snap +++ b/src/content-render/tests/__snapshots__/annotate.js.snap @@ -1,4 +1,27 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`annotate > renders annotations 1`] = ` +"
YAML
name: Post welcome comment

The name of the workflow as it will appear in the "Actions" tab of the GitHub repository.

on:
+  pull_request:
+    types: [opened]

Add the pull_request event, so that the workflow runs automatically +every time a pull request is created.

# The name of the workflow as it will appear in the "Actions" tab of the GitHub repository.
+name: Post welcome comment
+
+# Add the \`pull_request\` event, so that the workflow runs automatically
+# every time a pull request is created.
+on:
+  pull_request:
+    types: [opened]
+
" +`; exports[`annotate renders annotations 1`] = ` "
YAML