mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-11 22:49:54 +00:00
Introduce Vitest (#478)
Export-Source-Commit: 6242977d8081c01f4f88446ea7e74101a89fb8cf
This commit is contained in:
@@ -252,6 +252,82 @@
|
||||
"jest-dom/prefer-to-have-value": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["**/*.vitest.{ts,tsx}"],
|
||||
"plugins": ["vitest"],
|
||||
"rules": {
|
||||
"vitest/expect-expect": "warn",
|
||||
"vitest/no-alias-methods": "error",
|
||||
"vitest/no-commented-out-tests": "warn",
|
||||
"vitest/no-conditional-expect": "error",
|
||||
"vitest/no-conditional-tests": "error",
|
||||
"vitest/no-focused-tests": "error",
|
||||
"vitest/no-identical-title": "error",
|
||||
"vitest/no-interpolation-in-snapshots": "error",
|
||||
"vitest/no-mocks-import": "error",
|
||||
"vitest/no-standalone-expect": "error",
|
||||
"vitest/no-test-prefixes": "error",
|
||||
"vitest/prefer-importing-vitest-globals": "error",
|
||||
"vitest/valid-describe-callback": "error",
|
||||
"vitest/valid-expect": "error",
|
||||
"vitest/valid-expect-in-promise": "error",
|
||||
"vitest/valid-title": "error",
|
||||
"vitest/no-large-snapshots": ["warn", { "maxSize": 200 }],
|
||||
|
||||
"vitest/prefer-comparison-matcher": "error",
|
||||
"vitest/prefer-each": "error",
|
||||
"vitest/prefer-expect-type-of": "error",
|
||||
"vitest/prefer-hooks-in-order": "error",
|
||||
"vitest/prefer-hooks-on-top": "error",
|
||||
"vitest/prefer-mock-promise-shorthand": "error",
|
||||
"vitest/prefer-to-be": "error",
|
||||
"vitest/prefer-to-be-object": "error",
|
||||
"vitest/prefer-to-contain": "error",
|
||||
"vitest/prefer-to-have-length": "error",
|
||||
"vitest/prefer-todo": "error",
|
||||
|
||||
"testing-library/await-async-events": [
|
||||
"error",
|
||||
{ "eventModule": "userEvent" }
|
||||
],
|
||||
"testing-library/await-async-queries": "error",
|
||||
"testing-library/await-async-utils": "error",
|
||||
"testing-library/no-await-sync-events": [
|
||||
"error",
|
||||
{ "eventModules": ["fire-event"] }
|
||||
],
|
||||
"testing-library/no-await-sync-queries": "error",
|
||||
"testing-library/no-container": "error",
|
||||
"testing-library/no-debugging-utils": "warn",
|
||||
"testing-library/no-dom-import": ["error", "react"],
|
||||
"testing-library/no-global-regexp-flag-in-query": "error",
|
||||
"testing-library/no-manual-cleanup": "error",
|
||||
"testing-library/no-node-access": "error",
|
||||
"testing-library/no-promise-in-fire-event": "error",
|
||||
"testing-library/no-render-in-lifecycle": "error",
|
||||
"testing-library/no-unnecessary-act": "error",
|
||||
"testing-library/no-wait-for-multiple-assertions": "error",
|
||||
"testing-library/no-wait-for-side-effects": "error",
|
||||
"testing-library/no-wait-for-snapshot": "error",
|
||||
"testing-library/prefer-find-by": "error",
|
||||
"testing-library/prefer-presence-queries": "error",
|
||||
"testing-library/prefer-query-by-disappearance": "error",
|
||||
"testing-library/prefer-screen-queries": "error",
|
||||
"testing-library/render-result-naming-convention": "error",
|
||||
|
||||
"jest-dom/prefer-checked": "error",
|
||||
"jest-dom/prefer-empty": "error",
|
||||
"jest-dom/prefer-enabled-disabled": "error",
|
||||
"jest-dom/prefer-focus": "error",
|
||||
"jest-dom/prefer-in-document": "error",
|
||||
"jest-dom/prefer-required": "error",
|
||||
"jest-dom/prefer-to-have-attribute": "error",
|
||||
"jest-dom/prefer-to-have-class": "error",
|
||||
"jest-dom/prefer-to-have-style": "error",
|
||||
"jest-dom/prefer-to-have-text-content": "error",
|
||||
"jest-dom/prefer-to-have-value": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"**/*.stories.@(ts|tsx|js|jsx|mjs|cjs)",
|
||||
|
||||
+9
-7
@@ -39,19 +39,21 @@
|
||||
"vite/**/*.{ts,mts,mjs}",
|
||||
"jest/**/*.{ts,js}",
|
||||
"storybook.ts",
|
||||
"**/*.test.{ts,tsx,js,jsx}"
|
||||
"**/*.{test,vitest}.{ts,tsx,js,jsx}"
|
||||
],
|
||||
// These are loaded by name through the SWC plugin config in vite/react.mjs.
|
||||
"ignoreDependencies": [
|
||||
"@gravitational/swc-plugin-jsx-marker",
|
||||
"@gravitational/swc-plugin-styled-components",
|
||||
"@swc/core"
|
||||
"@swc/core",
|
||||
// Named as a string by `environment` in vitest/config.mts, which Vitest resolves at run time.
|
||||
"happy-dom"
|
||||
]
|
||||
},
|
||||
"web/packages/design": {
|
||||
"entry": [
|
||||
"src/**/*.story.{ts,tsx,js,jsx}",
|
||||
"src/**/*.test.{ts,tsx,js,jsx}"
|
||||
"src/**/*.{test,vitest}.{ts,tsx,js,jsx}"
|
||||
],
|
||||
"project": ["src/**/*.{ts,tsx,js,jsx,mts,mjs}", "@types/*.d.ts"],
|
||||
"paths": {
|
||||
@@ -62,7 +64,7 @@
|
||||
"ignore": ["src/**/*.type-test.tsx"]
|
||||
},
|
||||
"web/packages/shared": {
|
||||
"entry": ["**/*.story.{ts,tsx,js,jsx}", "**/*.test.{ts,tsx,js,jsx}"],
|
||||
"entry": ["**/*.story.{ts,tsx,js,jsx}", "**/*.{test,vitest}.{ts,tsx,js,jsx}"],
|
||||
"project": ["**/*.{ts,tsx,js,jsx,mts,mjs}", "!libs/ironrdp/pkg/**"],
|
||||
"paths": {
|
||||
"design/*": ["../design/src/*"],
|
||||
@@ -82,7 +84,7 @@
|
||||
"babel.config.js",
|
||||
"index.html",
|
||||
"src/**/*.story.{ts,tsx,js,jsx}",
|
||||
"src/**/*.test.{ts,tsx,js,jsx}",
|
||||
"src/**/*.{test,vitest}.{ts,tsx,js,jsx}",
|
||||
"src/services/audit/gen-event-reference/index.ts"
|
||||
],
|
||||
"project": ["src/**/*.{ts,tsx,js,jsx,mts,mjs}"],
|
||||
@@ -119,7 +121,7 @@
|
||||
"src/sharedProcess/sharedProcess.ts",
|
||||
"src/agentCleanupDaemon/agentCleanupDaemon.js",
|
||||
"src/**/*.story.{ts,tsx,js,jsx}",
|
||||
"src/**/*.test.{ts,tsx,js,jsx}",
|
||||
"src/**/*.{test,vitest}.{ts,tsx,js,jsx}",
|
||||
"src/**/*Process.mjs"
|
||||
],
|
||||
"project": ["src/**/*.{ts,tsx,js,jsx,mts,mjs}", "csp.ts"],
|
||||
@@ -145,7 +147,7 @@
|
||||
"babel.config.js",
|
||||
"index.html",
|
||||
"src/**/*.story.{ts,tsx,js,jsx}",
|
||||
"src/**/*.test.{ts,tsx,js,jsx}",
|
||||
"src/**/*.{test,vitest}.{ts,tsx,js,jsx}",
|
||||
"src/SessionRecordings/summary/generate-mitre-lookup.ts"
|
||||
],
|
||||
"project": ["src/**/*.{ts,tsx,js,jsx,mts,mjs}"],
|
||||
|
||||
+4
-4
@@ -13,10 +13,8 @@
|
||||
"package-term": "pnpm --filter=@gravitational/teleterm package",
|
||||
"storybook": "./web/scripts/run-storybook.sh",
|
||||
"storybook-smoke-test": "storybook dev -p 9002 -c web/.storybook --ci --smoke-test",
|
||||
"test": "jest",
|
||||
"test": "node web/scripts/run-tests.mjs",
|
||||
"test-coverage": "jest --coverage && web/scripts/print-coverage-link.sh",
|
||||
"test-update-snapshot": "pnpm run test --updateSnapshot",
|
||||
"tdd": "jest --watch",
|
||||
"oxlint": "oxlint --quiet --report-unused-disable-directives-severity error web/ e/ e2e/",
|
||||
"lint": "pnpm oxlint && pnpm format-check && pnpm knip",
|
||||
"lint-fix": "pnpm oxlint --fix && pnpm format",
|
||||
@@ -46,6 +44,7 @@
|
||||
"@types/react-dom": "^19.2.4",
|
||||
"@types/react-transition-group": "^4.4.12",
|
||||
"@types/wicg-file-system-access": "^2023.10.7",
|
||||
"@vitest/coverage-v8": "^4.1.0",
|
||||
"eslint": "^10.8.1",
|
||||
"eslint-plugin-jest-dom": "^5.10.1",
|
||||
"eslint-plugin-storybook": "^10.5.7",
|
||||
@@ -62,7 +61,8 @@
|
||||
"storybook": "^10.5.7",
|
||||
"svgo": "^4.0.2",
|
||||
"typescript": "^7.0.2",
|
||||
"vite": "^8.2.1"
|
||||
"vite": "^8.2.1",
|
||||
"vitest": "^4.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.20.3",
|
||||
|
||||
Generated
+367
-10
@@ -29,13 +29,13 @@ importers:
|
||||
version: 5.3.0
|
||||
'@gravitational/design-system':
|
||||
specifier: https://github.com/gravitational/design-system/releases/download/v0.2.0/design-system.tgz
|
||||
version: https://github.com/gravitational/design-system/releases/download/v0.2.0/design-system.tgz(@emotion/[email protected](@types/[email protected])([email protected])([email protected]))(@fontsource/[email protected])(@sinclair/[email protected])(@tanstack/[email protected]([email protected]))([email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])([email protected])
|
||||
version: https://github.com/gravitational/design-system/releases/download/v0.2.0/design-system.tgz(@emotion/[email protected](@types/[email protected])([email protected])([email protected]))(@fontsource/[email protected])(@sinclair/[email protected])(@standard-schema/[email protected])(@tanstack/[email protected]([email protected]))([email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])([email protected])
|
||||
'@grpc/grpc-js':
|
||||
specifier: 1.14.4
|
||||
version: 1.14.4
|
||||
'@hookform/resolvers':
|
||||
specifier: ^5.7.1
|
||||
version: 5.7.1(@sinclair/[email protected])([email protected])([email protected]([email protected]))([email protected])
|
||||
version: 5.7.1(@sinclair/[email protected])(@standard-schema/[email protected])([email protected])([email protected]([email protected]))([email protected])
|
||||
'@lezer/highlight':
|
||||
specifier: ^1.2.3
|
||||
version: 1.2.3
|
||||
@@ -129,7 +129,7 @@ importers:
|
||||
version: link:web/packages/build
|
||||
'@storybook/addon-vitest':
|
||||
specifier: ^10.5.7
|
||||
version: 10.5.7([email protected])([email protected])
|
||||
version: 10.5.7(@vitest/[email protected])([email protected])([email protected])([email protected])
|
||||
'@storybook/react-vite':
|
||||
specifier: ^10.5.7
|
||||
version: 10.5.7(@types/[email protected](@types/[email protected]))(@types/[email protected])([email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
|
||||
@@ -163,6 +163,9 @@ importers:
|
||||
'@types/wicg-file-system-access':
|
||||
specifier: ^2023.10.7
|
||||
version: 2023.10.7
|
||||
'@vitest/coverage-v8':
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.10([email protected])
|
||||
eslint:
|
||||
specifier: ^10.8.1
|
||||
version: 10.8.1([email protected])([email protected])
|
||||
@@ -214,6 +217,9 @@ importers:
|
||||
vite:
|
||||
specifier: ^8.2.1
|
||||
version: 8.2.1(@types/[email protected])([email protected])([email protected])([email protected])([email protected])
|
||||
vitest:
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.10(@opentelemetry/[email protected])(@types/[email protected])(@vitest/[email protected])([email protected])([email protected]([email protected]))([email protected](@types/[email protected])([email protected]))([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
|
||||
|
||||
e/web/teleport: {}
|
||||
|
||||
@@ -261,12 +267,18 @@ importers:
|
||||
babel-plugin-styled-components:
|
||||
specifier: ^2.3.0
|
||||
version: 2.3.0(@babel/[email protected]([email protected]))([email protected]([email protected]([email protected]))([email protected]))([email protected])
|
||||
happy-dom:
|
||||
specifier: ^20.10.6
|
||||
version: 20.11.2
|
||||
jest-environment-jsdom:
|
||||
specifier: ^30.4.1
|
||||
version: 30.4.1([email protected])
|
||||
jest-fail-on-console:
|
||||
specifier: ^3.3.4
|
||||
version: 3.3.4(@jest/[email protected]([email protected]))
|
||||
jest-styled-components:
|
||||
specifier: ^7.4.0
|
||||
version: 7.4.0([email protected]([email protected]([email protected]))([email protected]))
|
||||
rollup-plugin-visualizer:
|
||||
specifier: ^7.0.1
|
||||
version: 7.0.1([email protected])
|
||||
@@ -276,6 +288,9 @@ importers:
|
||||
vite-plugin-wasm:
|
||||
specifier: ^3.6.0
|
||||
version: 3.6.0([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
|
||||
vitest-fail-on-console:
|
||||
specifier: ^0.10.1
|
||||
version: 0.10.1(@vitest/[email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))([email protected])
|
||||
|
||||
web/packages/design:
|
||||
dependencies:
|
||||
@@ -292,9 +307,6 @@ importers:
|
||||
'@types/styled-system':
|
||||
specifier: ^5.1.25
|
||||
version: 5.1.25
|
||||
jest-styled-components:
|
||||
specifier: ^7.4.0
|
||||
version: 7.4.0([email protected]([email protected]([email protected]))([email protected]))
|
||||
|
||||
web/packages/shared:
|
||||
dependencies:
|
||||
@@ -1142,6 +1154,10 @@ packages:
|
||||
'@bcoe/[email protected]':
|
||||
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
|
||||
|
||||
'@bcoe/[email protected]':
|
||||
resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@cbor-extract/[email protected]':
|
||||
resolution: {integrity: sha512-ZKZ/F8US7JR92J4DMct6cLW/Y66o2K576+zjlEN/MevH70bFIsB10wkZEQPLzl2oNh2SMGy55xpJ9JoBRl5DOA==}
|
||||
cpu: [arm64]
|
||||
@@ -3279,6 +3295,9 @@ packages:
|
||||
'@so-ric/[email protected]':
|
||||
resolution: {integrity: sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==}
|
||||
|
||||
'@standard-schema/[email protected]':
|
||||
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
||||
|
||||
'@standard-schema/[email protected]':
|
||||
resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==}
|
||||
|
||||
@@ -3731,12 +3750,18 @@ packages:
|
||||
'@types/[email protected]':
|
||||
resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==}
|
||||
|
||||
'@types/[email protected]':
|
||||
resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==}
|
||||
|
||||
'@types/[email protected]':
|
||||
resolution: {integrity: sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w==}
|
||||
|
||||
'@types/[email protected]':
|
||||
resolution: {integrity: sha512-g49ijasEJvCd7ifmAY2D0wdEtt1xRjBbA33PJTiv8mKBr7DoMsPeISoJ8oQOTopSRi+FBWPpPW5ouDj2QPKtGA==}
|
||||
|
||||
'@types/[email protected]':
|
||||
resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
|
||||
|
||||
'@types/[email protected]':
|
||||
resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
|
||||
|
||||
@@ -4052,18 +4077,56 @@ packages:
|
||||
peerDependencies:
|
||||
vite: ^4 || ^5 || ^6 || ^7 || ^8
|
||||
|
||||
'@vitest/[email protected]':
|
||||
resolution: {integrity: sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==}
|
||||
peerDependencies:
|
||||
'@vitest/browser': 4.1.10
|
||||
vitest: 4.1.10
|
||||
peerDependenciesMeta:
|
||||
'@vitest/browser':
|
||||
optional: true
|
||||
|
||||
'@vitest/[email protected]':
|
||||
resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==}
|
||||
|
||||
'@vitest/[email protected]':
|
||||
resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==}
|
||||
|
||||
'@vitest/[email protected]':
|
||||
resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==}
|
||||
peerDependencies:
|
||||
msw: ^2.4.9
|
||||
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
peerDependenciesMeta:
|
||||
msw:
|
||||
optional: true
|
||||
vite:
|
||||
optional: true
|
||||
|
||||
'@vitest/[email protected]':
|
||||
resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==}
|
||||
|
||||
'@vitest/[email protected]':
|
||||
resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==}
|
||||
|
||||
'@vitest/[email protected]':
|
||||
resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==}
|
||||
|
||||
'@vitest/[email protected]':
|
||||
resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==}
|
||||
|
||||
'@vitest/[email protected]':
|
||||
resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==}
|
||||
|
||||
'@vitest/[email protected]':
|
||||
resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==}
|
||||
|
||||
'@vitest/[email protected]':
|
||||
resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==}
|
||||
|
||||
'@vitest/[email protected]':
|
||||
resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==}
|
||||
|
||||
'@webcontainer/[email protected]':
|
||||
resolution: {integrity: sha512-6aN99yL695Hi9SuIk1oC88l9o0gmxL1nGWWQ/kNy81HigJ0FoaoTXpytCj6ItzgyCEwA9kF1wixsTuv5cjsgng==}
|
||||
|
||||
@@ -4645,6 +4708,9 @@ packages:
|
||||
resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==}
|
||||
engines: {node: '>=0.12.0'}
|
||||
@@ -4825,6 +4891,10 @@ packages:
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ==}
|
||||
engines: {node: '>=4.0'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-g/kR520giAFYkSXTzcmF3kqQq7wi8F6N6SzeDgZrqTBN+VHdmgWOyTdD1yD7AATDId/yXLvuP34CxW46/BwCdw==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
@@ -4886,10 +4956,18 @@ packages:
|
||||
resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==}
|
||||
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -5344,6 +5422,10 @@ packages:
|
||||
resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -5484,6 +5566,9 @@ packages:
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -5503,6 +5588,10 @@ packages:
|
||||
resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-PMARsyh/JtqC20HoGqlFcIlQAyqUtW4PlI1rup1uhYJtKuwAjbvWi3GQMAn+STdHum/dk8xrKfUM1+5SAwpolA==}
|
||||
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
|
||||
@@ -5727,6 +5816,10 @@ packages:
|
||||
resolution: {integrity: sha512-Chq1s4CY7jmh8gO2qvLIJyfCDIN+EHLFW/9iShnp1z8FjBQMoodWP1kDC36VAMXXIvAjj4ARa7ntfAV2BrjsbA==}
|
||||
engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-7MB+bJLkxu3SowAfBJbjW+c55kNz5tkR45gu2qzrxznezhLeN5YIlJbwUgSzlGc+qWoZ8Ykg71H5ezz69xixrw==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -6119,6 +6212,9 @@ packages:
|
||||
resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
|
||||
hasBin: true
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||
|
||||
@@ -6345,6 +6441,9 @@ packages:
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -6558,6 +6657,10 @@ packages:
|
||||
resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==}
|
||||
engines: {node: '>=12.20.0'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||
|
||||
@@ -6691,6 +6794,9 @@ packages:
|
||||
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==}
|
||||
engines: {node: '>= 14.16'}
|
||||
@@ -7128,6 +7234,9 @@ packages:
|
||||
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
||||
|
||||
@@ -7193,6 +7302,9 @@ packages:
|
||||
resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==}
|
||||
engines: {node: '>= 6'}
|
||||
@@ -7201,6 +7313,9 @@ packages:
|
||||
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-oiKvWIwIoOhFP1i6dASYyMXwPHKEtVZMshqSB7EvIVYjWRh0l9H7gHEt1z4Gh2rLGFMekWdsm4s94rvwpR7gkg==}
|
||||
hasBin: true
|
||||
@@ -7382,6 +7497,13 @@ packages:
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
@@ -7394,6 +7516,10 @@ packages:
|
||||
resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
@@ -7679,6 +7805,54 @@ packages:
|
||||
yaml:
|
||||
optional: true
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-Xjy2SpgND547qSy0s0zYVnh1G/WyGtdjAbi4PFV8mkYRmTq+6NzRUJYdc08BHrw7HJLpO2kMxHFB8PWn7FOVsg==}
|
||||
peerDependencies:
|
||||
'@vitest/utils': '>=0.26.2'
|
||||
vite: '>=4.5.2'
|
||||
vitest: '>=0.26.2'
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==}
|
||||
engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@edge-runtime/vm': '*'
|
||||
'@opentelemetry/api': ^1.9.0
|
||||
'@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0
|
||||
'@vitest/browser-playwright': 4.1.10
|
||||
'@vitest/browser-preview': 4.1.10
|
||||
'@vitest/browser-webdriverio': 4.1.10
|
||||
'@vitest/coverage-istanbul': 4.1.10
|
||||
'@vitest/coverage-v8': 4.1.10
|
||||
'@vitest/ui': 4.1.10
|
||||
happy-dom: '*'
|
||||
jsdom: '*'
|
||||
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
peerDependenciesMeta:
|
||||
'@edge-runtime/vm':
|
||||
optional: true
|
||||
'@opentelemetry/api':
|
||||
optional: true
|
||||
'@types/node':
|
||||
optional: true
|
||||
'@vitest/browser-playwright':
|
||||
optional: true
|
||||
'@vitest/browser-preview':
|
||||
optional: true
|
||||
'@vitest/browser-webdriverio':
|
||||
optional: true
|
||||
'@vitest/coverage-istanbul':
|
||||
optional: true
|
||||
'@vitest/coverage-v8':
|
||||
optional: true
|
||||
'@vitest/ui':
|
||||
optional: true
|
||||
happy-dom:
|
||||
optional: true
|
||||
jsdom:
|
||||
optional: true
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
|
||||
|
||||
@@ -7715,6 +7889,10 @@ packages:
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -7743,6 +7921,11 @@ packages:
|
||||
engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0}
|
||||
hasBin: true
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
|
||||
engines: {node: '>=8'}
|
||||
hasBin: true
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
@@ -8821,6 +9004,8 @@ snapshots:
|
||||
|
||||
'@bcoe/[email protected]': {}
|
||||
|
||||
'@bcoe/[email protected]': {}
|
||||
|
||||
'@cbor-extract/[email protected]':
|
||||
optional: true
|
||||
|
||||
@@ -9472,14 +9657,14 @@ snapshots:
|
||||
|
||||
'@fontsource/[email protected]': {}
|
||||
|
||||
'@gravitational/design-system@https://github.com/gravitational/design-system/releases/download/v0.2.0/design-system.tgz(@emotion/[email protected](@types/[email protected])([email protected])([email protected]))(@fontsource/[email protected])(@sinclair/[email protected])(@tanstack/[email protected]([email protected]))([email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])([email protected])':
|
||||
'@gravitational/design-system@https://github.com/gravitational/design-system/releases/download/v0.2.0/design-system.tgz(@emotion/[email protected](@types/[email protected])([email protected])([email protected]))(@fontsource/[email protected])(@sinclair/[email protected])(@standard-schema/[email protected])(@tanstack/[email protected]([email protected]))([email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])([email protected])':
|
||||
dependencies:
|
||||
'@ark-ui/react': 5.37.1([email protected]([email protected]))([email protected])
|
||||
'@chakra-ui/cli': 3.35.0(@chakra-ui/[email protected](@emotion/[email protected](@types/[email protected])([email protected])([email protected]))([email protected]([email protected]))([email protected]))([email protected])([email protected])
|
||||
'@chakra-ui/react': 3.35.0(@emotion/[email protected](@types/[email protected])([email protected])([email protected]))([email protected]([email protected]))([email protected])
|
||||
'@emotion/react': 11.14.0(@types/[email protected])([email protected])([email protected])
|
||||
'@fontsource/ubuntu': 5.3.0
|
||||
'@hookform/resolvers': 5.7.1(@sinclair/[email protected])([email protected])([email protected]([email protected]))([email protected])
|
||||
'@hookform/resolvers': 5.7.1(@sinclair/[email protected])(@standard-schema/[email protected])([email protected])([email protected]([email protected]))([email protected])
|
||||
'@phosphor-icons/core': 2.1.1
|
||||
'@phosphor-icons/react': 2.1.10([email protected]([email protected]))([email protected])
|
||||
'@tanstack/react-query': 5.101.4([email protected])
|
||||
@@ -9537,12 +9722,13 @@ snapshots:
|
||||
protobufjs: 7.6.5
|
||||
yargs: 17.7.3
|
||||
|
||||
'@hookform/[email protected](@sinclair/[email protected])([email protected])([email protected]([email protected]))([email protected])':
|
||||
'@hookform/[email protected](@sinclair/[email protected])(@standard-schema/[email protected])([email protected])([email protected]([email protected]))([email protected])':
|
||||
dependencies:
|
||||
'@standard-schema/utils': 0.3.0
|
||||
react-hook-form: 7.85.0([email protected])
|
||||
optionalDependencies:
|
||||
'@sinclair/typebox': 0.34.49
|
||||
'@standard-schema/spec': 1.1.0
|
||||
ajv: 8.20.0
|
||||
zod: 4.4.3
|
||||
|
||||
@@ -10690,13 +10876,18 @@ snapshots:
|
||||
color: 5.0.3
|
||||
text-hex: 1.0.0
|
||||
|
||||
'@standard-schema/[email protected]': {}
|
||||
|
||||
'@standard-schema/[email protected]': {}
|
||||
|
||||
'@storybook/[email protected]([email protected])([email protected])':
|
||||
'@storybook/[email protected](@vitest/[email protected])([email protected])([email protected])([email protected])':
|
||||
dependencies:
|
||||
'@storybook/global': 5.0.0
|
||||
'@storybook/icons': 2.1.0([email protected])
|
||||
storybook: 10.5.7(@storybook/[email protected])(@types/[email protected])([email protected])([email protected])
|
||||
optionalDependencies:
|
||||
'@vitest/runner': 4.1.10
|
||||
vitest: 4.1.10(@opentelemetry/[email protected])(@types/[email protected])(@vitest/[email protected])([email protected])([email protected]([email protected]))([email protected](@types/[email protected])([email protected]))([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
|
||||
transitivePeerDependencies:
|
||||
- react
|
||||
|
||||
@@ -11128,10 +11319,16 @@ snapshots:
|
||||
|
||||
'@types/[email protected]': {}
|
||||
|
||||
'@types/[email protected]': {}
|
||||
|
||||
'@types/[email protected]': {}
|
||||
|
||||
'@types/[email protected]': {}
|
||||
|
||||
'@types/[email protected]':
|
||||
dependencies:
|
||||
'@types/node': 24.13.3
|
||||
|
||||
'@types/[email protected]': {}
|
||||
|
||||
'@types/[email protected]':
|
||||
@@ -11361,6 +11558,20 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- '@swc/helpers'
|
||||
|
||||
'@vitest/[email protected]([email protected])':
|
||||
dependencies:
|
||||
'@bcoe/v8-coverage': 1.0.2
|
||||
'@vitest/utils': 4.1.10
|
||||
ast-v8-to-istanbul: 1.0.5
|
||||
istanbul-lib-coverage: 3.2.2
|
||||
istanbul-lib-report: 3.0.1
|
||||
istanbul-reports: 3.2.0
|
||||
magicast: 0.5.4
|
||||
obug: 2.1.4
|
||||
std-env: 4.2.0
|
||||
tinyrainbow: 3.1.1
|
||||
vitest: 4.1.10(@opentelemetry/[email protected])(@types/[email protected])(@vitest/[email protected])([email protected])([email protected]([email protected]))([email protected](@types/[email protected])([email protected]))([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
|
||||
|
||||
'@vitest/[email protected]':
|
||||
dependencies:
|
||||
'@types/chai': 5.2.3
|
||||
@@ -11369,20 +11580,62 @@ snapshots:
|
||||
chai: 5.3.3
|
||||
tinyrainbow: 2.0.0
|
||||
|
||||
'@vitest/[email protected]':
|
||||
dependencies:
|
||||
'@standard-schema/spec': 1.1.0
|
||||
'@types/chai': 5.2.3
|
||||
'@vitest/spy': 4.1.10
|
||||
'@vitest/utils': 4.1.10
|
||||
chai: 6.2.2
|
||||
tinyrainbow: 3.1.1
|
||||
|
||||
'@vitest/[email protected]([email protected](@types/[email protected])([email protected]))([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))':
|
||||
dependencies:
|
||||
'@vitest/spy': 4.1.10
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.21
|
||||
optionalDependencies:
|
||||
msw: 2.15.0(@types/[email protected])([email protected])
|
||||
vite: 8.2.1(@types/[email protected])([email protected])([email protected])([email protected])([email protected])
|
||||
|
||||
'@vitest/[email protected]':
|
||||
dependencies:
|
||||
tinyrainbow: 2.0.0
|
||||
|
||||
'@vitest/[email protected]':
|
||||
dependencies:
|
||||
tinyrainbow: 3.1.1
|
||||
|
||||
'@vitest/[email protected]':
|
||||
dependencies:
|
||||
'@vitest/utils': 4.1.10
|
||||
pathe: 2.0.3
|
||||
|
||||
'@vitest/[email protected]':
|
||||
dependencies:
|
||||
'@vitest/pretty-format': 4.1.10
|
||||
'@vitest/utils': 4.1.10
|
||||
magic-string: 0.30.21
|
||||
pathe: 2.0.3
|
||||
|
||||
'@vitest/[email protected]':
|
||||
dependencies:
|
||||
tinyspy: 4.0.4
|
||||
|
||||
'@vitest/[email protected]': {}
|
||||
|
||||
'@vitest/[email protected]':
|
||||
dependencies:
|
||||
'@vitest/pretty-format': 3.2.4
|
||||
loupe: 3.2.1
|
||||
tinyrainbow: 2.0.0
|
||||
|
||||
'@vitest/[email protected]':
|
||||
dependencies:
|
||||
'@vitest/pretty-format': 4.1.10
|
||||
convert-source-map: 2.0.0
|
||||
tinyrainbow: 3.1.1
|
||||
|
||||
'@webcontainer/[email protected]': {}
|
||||
|
||||
'@xmldom/[email protected]': {}
|
||||
@@ -12651,6 +12904,12 @@ snapshots:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
[email protected]:
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.31
|
||||
estree-walker: 3.0.3
|
||||
js-tokens: 10.0.0
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
@@ -12853,6 +13112,10 @@ snapshots:
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]:
|
||||
dependencies:
|
||||
'@types/node': 24.13.3
|
||||
|
||||
[email protected]([email protected]):
|
||||
dependencies:
|
||||
debug: 4.4.3([email protected])
|
||||
@@ -12938,11 +13201,15 @@ snapshots:
|
||||
loupe: 3.2.1
|
||||
pathval: 2.0.1
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]:
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
supports-color: 7.2.0
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
@@ -13400,6 +13667,8 @@ snapshots:
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
@@ -13621,6 +13890,10 @@ snapshots:
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.9
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]:
|
||||
@@ -13645,6 +13918,8 @@ snapshots:
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]:
|
||||
dependencies:
|
||||
'@jest/expect-utils': 30.4.1
|
||||
@@ -13909,6 +14184,19 @@ snapshots:
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]:
|
||||
dependencies:
|
||||
'@types/node': 24.13.3
|
||||
'@types/whatwg-mimetype': 3.0.2
|
||||
'@types/ws': 8.18.1
|
||||
buffer-image-size: 0.6.4
|
||||
entities: 7.0.1
|
||||
whatwg-mimetype: 3.0.0
|
||||
ws: 8.21.3
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]:
|
||||
@@ -14464,6 +14752,8 @@ snapshots:
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]:
|
||||
@@ -14675,6 +14965,12 @@ snapshots:
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
|
||||
[email protected]:
|
||||
dependencies:
|
||||
'@babel/parser': 7.29.8
|
||||
'@babel/types': 7.29.8
|
||||
source-map-js: 1.2.1
|
||||
|
||||
[email protected]:
|
||||
dependencies:
|
||||
semver: 7.8.5
|
||||
@@ -14863,6 +15159,8 @@ snapshots:
|
||||
[email protected]:
|
||||
optional: true
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]:
|
||||
dependencies:
|
||||
wrappy: 1.0.2
|
||||
@@ -15080,6 +15378,8 @@ snapshots:
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
@@ -15527,6 +15827,8 @@ snapshots:
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
@@ -15574,10 +15876,14 @@ snapshots:
|
||||
dependencies:
|
||||
escape-string-regexp: 2.0.0
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected](@storybook/[email protected])(@types/[email protected])([email protected])([email protected]):
|
||||
dependencies:
|
||||
'@storybook/global': 5.0.0
|
||||
@@ -15809,6 +16115,10 @@ snapshots:
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]:
|
||||
dependencies:
|
||||
fdir: 6.5.0([email protected])
|
||||
@@ -15818,6 +16128,8 @@ snapshots:
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
@@ -16074,6 +16386,44 @@ snapshots:
|
||||
tsx: 4.23.11
|
||||
yaml: 2.9.0
|
||||
|
||||
[email protected](@vitest/[email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))([email protected]):
|
||||
dependencies:
|
||||
'@vitest/utils': 4.1.10
|
||||
chalk: 5.6.2
|
||||
vite: 8.2.1(@types/[email protected])([email protected])([email protected])([email protected])([email protected])
|
||||
vitest: 4.1.10(@opentelemetry/[email protected])(@types/[email protected])(@vitest/[email protected])([email protected])([email protected]([email protected]))([email protected](@types/[email protected])([email protected]))([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
|
||||
|
||||
[email protected](@opentelemetry/[email protected])(@types/[email protected])(@vitest/[email protected])([email protected])([email protected]([email protected]))([email protected](@types/[email protected])([email protected]))([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected])):
|
||||
dependencies:
|
||||
'@vitest/expect': 4.1.10
|
||||
'@vitest/mocker': 4.1.10([email protected](@types/[email protected])([email protected]))([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
|
||||
'@vitest/pretty-format': 4.1.10
|
||||
'@vitest/runner': 4.1.10
|
||||
'@vitest/snapshot': 4.1.10
|
||||
'@vitest/spy': 4.1.10
|
||||
'@vitest/utils': 4.1.10
|
||||
es-module-lexer: 2.3.1
|
||||
expect-type: 1.4.0
|
||||
magic-string: 0.30.21
|
||||
obug: 2.1.4
|
||||
pathe: 2.0.3
|
||||
picomatch: 4.0.5
|
||||
std-env: 4.2.0
|
||||
tinybench: 2.9.0
|
||||
tinyexec: 1.3.0
|
||||
tinyglobby: 0.2.17
|
||||
tinyrainbow: 3.1.1
|
||||
vite: 8.2.1(@types/[email protected])([email protected])([email protected])([email protected])([email protected])
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
'@opentelemetry/api': 1.9.1
|
||||
'@types/node': 24.13.3
|
||||
'@vitest/coverage-v8': 4.1.10([email protected])
|
||||
happy-dom: 20.11.2
|
||||
jsdom: 26.1.0([email protected])
|
||||
transitivePeerDependencies:
|
||||
- msw
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]:
|
||||
@@ -16106,6 +16456,8 @@ snapshots:
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]:
|
||||
@@ -16129,6 +16481,11 @@ snapshots:
|
||||
dependencies:
|
||||
isexe: 4.0.0
|
||||
|
||||
[email protected]:
|
||||
dependencies:
|
||||
siginfo: 2.0.0
|
||||
stackback: 0.0.2
|
||||
|
||||
[email protected]:
|
||||
dependencies:
|
||||
logform: 2.7.0
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Teleport
|
||||
* Copyright (C) 2026 Gravitational, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import fs from 'node:fs';
|
||||
|
||||
import { createVitestConfig } from './web/packages/build/vitest/config.mts';
|
||||
|
||||
// Gradual migration: Vitest runs only *.vitest.{ts,tsx}; everything still on
|
||||
// *.test.{ts,tsx} keeps running under Jest.
|
||||
const include = ['web/**/*.vitest.{ts,tsx}'];
|
||||
|
||||
// Include enterprise tests when the e/ directory is present.
|
||||
if (fs.existsSync('e/web')) {
|
||||
include.push('e/web/**/*.vitest.{ts,tsx}');
|
||||
}
|
||||
|
||||
export default createVitestConfig(include);
|
||||
+8
-4
@@ -128,18 +128,22 @@ requests to the given target.
|
||||
|
||||
### Unit-Tests
|
||||
|
||||
We use [jest](https://jestjs.io/) as our testing framework.
|
||||
We are migrating from [jest](https://jestjs.io/) to [vitest](https://vitest.dev/). Vitest owns
|
||||
`*.vitest.{ts,tsx}` files. Everything still on `*.test.{ts,tsx}` runs under jest.
|
||||
|
||||
To run all jest unit-tests:
|
||||
To run all unit-tests under both runners:
|
||||
|
||||
```
|
||||
pnpm test
|
||||
```
|
||||
|
||||
To run jest in watch-mode
|
||||
`pnpm test` also takes paths and file names, routing each to the runner that owns it.
|
||||
|
||||
To drive a runner directly, including watch-mode:
|
||||
|
||||
```
|
||||
pnpm tdd
|
||||
pnpm jest --watch
|
||||
pnpm vitest
|
||||
```
|
||||
|
||||
### Interactive Testing
|
||||
|
||||
@@ -511,6 +511,30 @@ function installCanvasMock() {
|
||||
const blob = new window.Blob([new Uint8Array(length)], { type: mime });
|
||||
setTimeout(() => callback(blob), 0);
|
||||
};
|
||||
|
||||
// happy-dom's OffscreenCanvas.getContext returns null; patch in the mock 2d
|
||||
// context for renderers that draw offscreen (SessionRecordings timeline).
|
||||
const offscreenProto = (
|
||||
globalThis as { OffscreenCanvas?: { prototype: any } }
|
||||
).OffscreenCanvas?.prototype;
|
||||
if (offscreenProto) {
|
||||
Object.defineProperty(offscreenProto, 'getContext', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: function getContext(
|
||||
this: HTMLCanvasElement,
|
||||
type: string
|
||||
): MockCanvasRenderingContext2D | null {
|
||||
if (type !== '2d') return null;
|
||||
let ctx = contexts.get(this);
|
||||
if (!ctx) {
|
||||
ctx = new MockCanvasRenderingContext2D(this);
|
||||
contexts.set(this, ctx);
|
||||
}
|
||||
return ctx;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
installCanvasMock();
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
import crypto from 'node:crypto';
|
||||
import path from 'node:path';
|
||||
|
||||
import '@testing-library/jest-dom';
|
||||
import 'jest-styled-components';
|
||||
import { configure as configureTestingLibrary } from '@testing-library/react';
|
||||
import failOnConsole from 'jest-fail-on-console';
|
||||
import { configMocks } from 'jsdom-testing-mocks';
|
||||
|
||||
@@ -18,10 +18,13 @@
|
||||
"@swc/core": "^1.15.47",
|
||||
"@vitejs/plugin-react-swc": "^4.3.3",
|
||||
"babel-plugin-styled-components": "^2.3.0",
|
||||
"happy-dom": "^20.10.6",
|
||||
"jest-environment-jsdom": "^30.4.1",
|
||||
"jest-fail-on-console": "^3.3.4",
|
||||
"jest-styled-components": "^7.4.0",
|
||||
"rollup-plugin-visualizer": "^7.0.1",
|
||||
"vite-plugin-compression2": "^2.5.3",
|
||||
"vite-plugin-wasm": "^3.6.0"
|
||||
"vite-plugin-wasm": "^3.6.0",
|
||||
"vitest-fail-on-console": "^0.10.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Teleport
|
||||
* Copyright (C) 2026 Gravitational, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Must precede the imports: vmThreads VM contexts capture TZ at creation time.
|
||||
process.env.TZ = 'UTC';
|
||||
|
||||
import { type Plugin, type ViteUserConfig, defineConfig } from 'vitest/config';
|
||||
|
||||
import { reactPlugin } from '../vite/react.mjs';
|
||||
|
||||
// Stubs assets that aren't real modules under test (images, YAML, and the
|
||||
// ironrdp ?inline wasm, whose client is mocked by the tests that use it).
|
||||
function assetStubPlugin(): Plugin {
|
||||
return {
|
||||
name: 'vitest-asset-stub',
|
||||
transform(_code, id) {
|
||||
if (/\.wasm(\?.*)?$/.test(id)) {
|
||||
return { code: `export default new Uint8Array();`, map: null };
|
||||
}
|
||||
if (/\.(png|svg|yaml)(\?.*)?$/.test(id)) {
|
||||
return { code: `export default 'file_stub';`, map: null };
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const standardExclude = ['**/e2e/**', '**/node_modules/**', '**/dist/**'];
|
||||
|
||||
export function createVitestConfig(testInclude: string[]): ViteUserConfig {
|
||||
return defineConfig({
|
||||
plugins: [reactPlugin('test'), assetStubPlugin()],
|
||||
resolve: { tsconfigPaths: true },
|
||||
test: {
|
||||
include: testInclude,
|
||||
exclude: standardExclude,
|
||||
// happy-dom resolves the design system's modern CSS that jsdom's parser drops (breaking toHaveStyle).
|
||||
environment: 'happy-dom',
|
||||
environmentOptions: {
|
||||
happyDOM: { url: 'http://localhost' },
|
||||
},
|
||||
setupFiles: ['./web/packages/build/vitest/setup.ts'],
|
||||
css: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Teleport
|
||||
* Copyright (C) 2026 Gravitational, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// The '@testing-library/jest-dom/vitest' entry self-imports 'vitest', which
|
||||
// pnpm's isolated store can't resolve from inside the jest-dom package, so
|
||||
// extend expect with the matchers directly.
|
||||
import * as jestDomMatchers from '@testing-library/jest-dom/matchers';
|
||||
import { cleanup } from '@testing-library/react';
|
||||
|
||||
import '../jest/canvasMock';
|
||||
import { afterAll, afterEach, beforeAll, expect } from 'vitest';
|
||||
import failOnConsole from 'vitest-fail-on-console';
|
||||
|
||||
import { server } from 'design/utils/testing';
|
||||
|
||||
// happy-dom doesn't implement requestIdleCallback (SessionRecordings timeline).
|
||||
if (typeof globalThis.requestIdleCallback === 'undefined') {
|
||||
globalThis.requestIdleCallback = ((cb: IdleRequestCallback) =>
|
||||
setTimeout(
|
||||
() => cb({ didTimeout: false, timeRemaining: () => 50 } as IdleDeadline),
|
||||
0
|
||||
)) as unknown as typeof globalThis.requestIdleCallback;
|
||||
globalThis.cancelIdleCallback = ((id: number) =>
|
||||
clearTimeout(id)) as unknown as typeof globalThis.cancelIdleCallback;
|
||||
}
|
||||
|
||||
expect.extend(jestDomMatchers);
|
||||
|
||||
failOnConsole();
|
||||
|
||||
// @testing-library/react only self-registers this when a global afterEach exists.
|
||||
afterEach(cleanup);
|
||||
|
||||
// React reads this to decide whether act() is supported. RTL only sets it around its own act() calls, so without
|
||||
// it React warns on every state update and vitest-fail-on-console turns that into a failure.
|
||||
(
|
||||
globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }
|
||||
).IS_REACT_ACT_ENVIRONMENT = true;
|
||||
|
||||
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
|
||||
afterEach(() => server.resetHandlers());
|
||||
afterAll(() => server.close());
|
||||
@@ -14,7 +14,6 @@
|
||||
"styled-system": "^5.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/styled-system": "^5.1.25",
|
||||
"jest-styled-components": "^7.4.0"
|
||||
"@types/styled-system": "^5.1.25"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import '@testing-library/jest-dom';
|
||||
import {
|
||||
createThemeSystem,
|
||||
TELEPORT_THEME,
|
||||
@@ -33,7 +32,6 @@ import {
|
||||
waitForElementToBeRemoved,
|
||||
within,
|
||||
} from '@testing-library/react';
|
||||
import 'jest-styled-components';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { HttpResponse, JsonBodyType } from 'msw';
|
||||
import { setupServer } from 'msw/node';
|
||||
@@ -79,9 +77,7 @@ function render(
|
||||
updates / timeouts to finish.
|
||||
*/
|
||||
function tick() {
|
||||
return new Promise<void>(res =>
|
||||
jest.requireActual('timers').setImmediate(res)
|
||||
);
|
||||
return new Promise<void>(res => setTimeout(res, 0));
|
||||
}
|
||||
|
||||
screen.debug = () => {
|
||||
|
||||
+4
-6
@@ -18,10 +18,10 @@
|
||||
|
||||
import { http, HttpResponse } from 'msw';
|
||||
import { generatePath, MemoryRouter } from 'react-router';
|
||||
import { vi, test, afterEach, expect, beforeEach } from 'vitest';
|
||||
|
||||
import {
|
||||
createDeferredResponse,
|
||||
enableMswServer,
|
||||
render,
|
||||
screen,
|
||||
server,
|
||||
@@ -37,8 +37,6 @@ import { createTeleportContext } from 'teleport/mocks/contexts';
|
||||
import { ListSessionRecordingsRoute } from './ListSessionRecordingsRoute';
|
||||
import { getThumbnail, MOCK_EVENTS, MOCK_THUMBNAIL } from './mock';
|
||||
|
||||
enableMswServer();
|
||||
|
||||
beforeEach(() => {
|
||||
server.use(
|
||||
getThumbnail(MOCK_THUMBNAIL),
|
||||
@@ -98,7 +96,7 @@ test('displays loading indicator while fetching data', async () => {
|
||||
});
|
||||
|
||||
test('displays error message when request fails', async () => {
|
||||
jest.spyOn(console, 'error').mockImplementation();
|
||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const errorMessage = 'Failed to fetch recordings';
|
||||
|
||||
@@ -123,7 +121,7 @@ test('displays error message when request fails', async () => {
|
||||
});
|
||||
|
||||
test('retries the request on retry button click', async () => {
|
||||
jest.spyOn(console, 'error').mockImplementation();
|
||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const errorMessage = 'Failed to fetch recordings';
|
||||
|
||||
@@ -169,7 +167,7 @@ test('retries the request on retry button click', async () => {
|
||||
});
|
||||
|
||||
test('displays an error message on connection failure', async () => {
|
||||
jest.spyOn(console, 'error').mockImplementation();
|
||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
server.use(
|
||||
http.get(listRecordingsUrl, () => {
|
||||
+3
-5
@@ -19,9 +19,9 @@
|
||||
import { format } from 'date-fns';
|
||||
import { act } from 'react';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
import { vi, test, afterEach, expect, beforeEach } from 'vitest';
|
||||
|
||||
import {
|
||||
enableMswServer,
|
||||
render,
|
||||
screen,
|
||||
server,
|
||||
@@ -38,8 +38,6 @@ import { getThumbnail, MOCK_THUMBNAIL, thumbnailError } from './mock';
|
||||
import { RecordingItem, type RecordingItemProps } from './RecordingItem';
|
||||
import { Density, ViewMode } from './ViewSwitcher';
|
||||
|
||||
enableMswServer();
|
||||
|
||||
const mockRecording: Recording = {
|
||||
sid: 'test-session',
|
||||
user: 'alice',
|
||||
@@ -235,7 +233,7 @@ test('renders all view modes with all densities', async () => {
|
||||
});
|
||||
|
||||
test('shows thumbnail not available if it fails to load', async () => {
|
||||
jest.spyOn(console, 'error').mockImplementation();
|
||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
server.use(thumbnailError());
|
||||
|
||||
@@ -263,7 +261,7 @@ test('shows non-interactive session message for non-playable recordings', async
|
||||
});
|
||||
|
||||
test('allows custom action slot', async () => {
|
||||
const actionComponent = jest
|
||||
const actionComponent = vi
|
||||
.fn()
|
||||
.mockReturnValue(
|
||||
<button data-testid="custom-action">Custom Action</button>
|
||||
+3
-9
@@ -16,19 +16,13 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
enableMswServer,
|
||||
render,
|
||||
screen,
|
||||
server,
|
||||
testQueryClient,
|
||||
} from 'design/utils/testing';
|
||||
import { expect, test, afterEach } from 'vitest';
|
||||
|
||||
import { render, screen, server, testQueryClient } from 'design/utils/testing';
|
||||
|
||||
import { getThumbnail, MOCK_THUMBNAIL } from './mock';
|
||||
import { RecordingThumbnail } from './RecordingThumbnail';
|
||||
|
||||
enableMswServer();
|
||||
|
||||
afterEach(() => {
|
||||
testQueryClient.clear();
|
||||
});
|
||||
+5
-7
@@ -18,9 +18,9 @@
|
||||
|
||||
import { http, HttpResponse } from 'msw';
|
||||
import { generatePath, MemoryRouter } from 'react-router';
|
||||
import { vi, beforeEach, afterEach, describe, expect, it } from 'vitest';
|
||||
|
||||
import {
|
||||
enableMswServer,
|
||||
render,
|
||||
screen,
|
||||
server,
|
||||
@@ -48,8 +48,6 @@ import {
|
||||
import type { RecordingsListState } from './state';
|
||||
import { Density, ViewMode } from './ViewSwitcher';
|
||||
|
||||
enableMswServer();
|
||||
|
||||
beforeEach(() => {
|
||||
server.use(
|
||||
getThumbnail(MOCK_THUMBNAIL),
|
||||
@@ -90,10 +88,10 @@ const defaultState: RecordingsListState = {
|
||||
};
|
||||
|
||||
const mockHandlers = {
|
||||
onFilterChange: jest.fn(),
|
||||
onPageChange: jest.fn(),
|
||||
onSearchChange: jest.fn(),
|
||||
onSortChange: jest.fn(),
|
||||
onFilterChange: vi.fn(),
|
||||
onPageChange: vi.fn(),
|
||||
onSearchChange: vi.fn(),
|
||||
onSortChange: vi.fn(),
|
||||
};
|
||||
|
||||
const listRecordingsUrl = generatePath(cfg.api.clusterEventsRecordingsPath, {
|
||||
+16
-14
@@ -16,6 +16,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { vi, expect, test, afterEach } from 'vitest';
|
||||
|
||||
import { render, screen, userEvent } from 'design/utils/testing';
|
||||
|
||||
import {
|
||||
@@ -29,7 +31,7 @@ const defaultProps: RecordingsPaginationProps = {
|
||||
to: 9,
|
||||
page: 0,
|
||||
pageSize: 10,
|
||||
onPageChange: jest.fn(),
|
||||
onPageChange: vi.fn(),
|
||||
};
|
||||
|
||||
function setupTest(props: Partial<RecordingsPaginationProps> = {}) {
|
||||
@@ -37,7 +39,7 @@ function setupTest(props: Partial<RecordingsPaginationProps> = {}) {
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
function getPaginationIndicator() {
|
||||
@@ -93,7 +95,7 @@ test('enables both buttons on middle page', async () => {
|
||||
});
|
||||
|
||||
test('calls onPageChange with previous page when clicking previous', async () => {
|
||||
const onPageChange = jest.fn();
|
||||
const onPageChange = vi.fn();
|
||||
|
||||
setupTest({
|
||||
page: 5,
|
||||
@@ -109,7 +111,7 @@ test('calls onPageChange with previous page when clicking previous', async () =>
|
||||
});
|
||||
|
||||
test('calls onPageChange with next page when clicking next', async () => {
|
||||
const onPageChange = jest.fn();
|
||||
const onPageChange = vi.fn();
|
||||
|
||||
setupTest({
|
||||
page: 5,
|
||||
@@ -125,7 +127,7 @@ test('calls onPageChange with next page when clicking next', async () => {
|
||||
});
|
||||
|
||||
test('does not call onPageChange when clicking disabled previous button', async () => {
|
||||
const onPageChange = jest.fn();
|
||||
const onPageChange = vi.fn();
|
||||
|
||||
setupTest({
|
||||
page: 0,
|
||||
@@ -140,7 +142,7 @@ test('does not call onPageChange when clicking disabled previous button', async
|
||||
});
|
||||
|
||||
test('does not call onPageChange when clicking disabled next button', async () => {
|
||||
const onPageChange = jest.fn();
|
||||
const onPageChange = vi.fn();
|
||||
|
||||
setupTest({
|
||||
page: 9,
|
||||
@@ -158,7 +160,7 @@ test('does not call onPageChange when clicking disabled next button', async () =
|
||||
test('shows fetch more button when fetchMoreAvailable is true', async () => {
|
||||
setupTest({
|
||||
fetchMoreAvailable: true,
|
||||
onFetchMore: jest.fn(),
|
||||
onFetchMore: vi.fn(),
|
||||
});
|
||||
|
||||
expect(screen.getByText('Fetch More')).toBeInTheDocument();
|
||||
@@ -167,7 +169,7 @@ test('shows fetch more button when fetchMoreAvailable is true', async () => {
|
||||
test('does not show fetch more button when fetchMoreAvailable is false', async () => {
|
||||
setupTest({
|
||||
fetchMoreAvailable: false,
|
||||
onFetchMore: jest.fn(),
|
||||
onFetchMore: vi.fn(),
|
||||
});
|
||||
|
||||
expect(screen.queryByText('Fetch More')).not.toBeInTheDocument();
|
||||
@@ -182,7 +184,7 @@ test('does not show fetch more button when onFetchMore is not provided', async (
|
||||
});
|
||||
|
||||
test('calls onFetchMore when clicking fetch more button', async () => {
|
||||
const onFetchMore = jest.fn();
|
||||
const onFetchMore = vi.fn();
|
||||
|
||||
setupTest({
|
||||
fetchMoreAvailable: true,
|
||||
@@ -199,7 +201,7 @@ test('disables fetch more button when fetchMoreDisabled is true', async () => {
|
||||
setupTest({
|
||||
fetchMoreAvailable: true,
|
||||
fetchMoreDisabled: true,
|
||||
onFetchMore: jest.fn(),
|
||||
onFetchMore: vi.fn(),
|
||||
});
|
||||
|
||||
const fetchMoreButton = screen.getByText('Fetch More');
|
||||
@@ -216,7 +218,7 @@ test('shows error message when fetchMoreError is true', async () => {
|
||||
});
|
||||
|
||||
test('shows retry button instead of fetch more when error occurs', async () => {
|
||||
const onFetchMore = jest.fn();
|
||||
const onFetchMore = vi.fn();
|
||||
|
||||
setupTest({
|
||||
fetchMoreAvailable: true,
|
||||
@@ -229,7 +231,7 @@ test('shows retry button instead of fetch more when error occurs', async () => {
|
||||
});
|
||||
|
||||
test('calls onFetchMore when clicking retry button', async () => {
|
||||
const onFetchMore = jest.fn();
|
||||
const onFetchMore = vi.fn();
|
||||
|
||||
setupTest({
|
||||
fetchMoreAvailable: true,
|
||||
@@ -256,7 +258,7 @@ test('displays correct page indicator for different pages', async () => {
|
||||
rerender(
|
||||
<RecordingsPagination
|
||||
{...defaultProps}
|
||||
onPageChange={jest.fn()}
|
||||
onPageChange={vi.fn()}
|
||||
page={5}
|
||||
from={50}
|
||||
to={59}
|
||||
@@ -269,7 +271,7 @@ test('displays correct page indicator for different pages', async () => {
|
||||
rerender(
|
||||
<RecordingsPagination
|
||||
{...defaultProps}
|
||||
onPageChange={jest.fn()}
|
||||
onPageChange={vi.fn()}
|
||||
page={9}
|
||||
from={90}
|
||||
to={99}
|
||||
+1
@@ -19,6 +19,7 @@
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { MemoryRouter, useLocation, useNavigate } from 'react-router';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { EventRange } from 'teleport/components/EventRangePicker';
|
||||
|
||||
+16
-13
@@ -19,6 +19,7 @@
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
import { act, createRef } from 'react';
|
||||
import { vi, test, afterEach, expect, beforeEach } from 'vitest';
|
||||
|
||||
import { fireEvent, render, screen } from 'design/utils/testing';
|
||||
|
||||
@@ -34,11 +35,11 @@ import { DesktopPlayer } from './DesktopPlayer';
|
||||
class FakePlayerClient {
|
||||
private events = new EventEmitter();
|
||||
|
||||
connect = jest.fn().mockResolvedValue(undefined);
|
||||
shutdown = jest.fn();
|
||||
togglePlayPause = jest.fn();
|
||||
setPlaySpeed = jest.fn();
|
||||
seekTo = jest.fn((pos: number) => {
|
||||
connect = vi.fn().mockResolvedValue(undefined);
|
||||
shutdown = vi.fn();
|
||||
togglePlayPause = vi.fn();
|
||||
setPlaySpeed = vi.fn();
|
||||
seekTo = vi.fn((pos: number) => {
|
||||
this.emitAnchor({ ms: pos, speed: 1, paused: false });
|
||||
});
|
||||
|
||||
@@ -70,17 +71,19 @@ class FakePlayerClient {
|
||||
|
||||
let mockPlayerClient: FakePlayerClient;
|
||||
|
||||
jest.mock('teleport/lib/tdp', () => ({
|
||||
PlayerClient: jest.fn().mockImplementation(() => mockPlayerClient),
|
||||
vi.mock('teleport/lib/tdp', () => ({
|
||||
PlayerClient: vi.fn().mockImplementation(function () {
|
||||
return mockPlayerClient;
|
||||
}),
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
mockPlayerClient = new FakePlayerClient();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
const INACTIVITY_EVENT: SessionRecordingEvent = {
|
||||
@@ -110,12 +113,12 @@ function startPlayback() {
|
||||
|
||||
function advance(ms: number) {
|
||||
act(() => {
|
||||
jest.advanceTimersByTime(ms);
|
||||
vi.advanceTimersByTime(ms);
|
||||
});
|
||||
}
|
||||
|
||||
test('emits rAF-smoothed time updates from time anchors', () => {
|
||||
const onTimeChange = jest.fn();
|
||||
const onTimeChange = vi.fn();
|
||||
renderPlayer({ onTimeChange });
|
||||
startPlayback();
|
||||
|
||||
@@ -134,7 +137,7 @@ test('emits rAF-smoothed time updates from time anchors', () => {
|
||||
});
|
||||
|
||||
test('interpolates at the anchor speed', () => {
|
||||
const onTimeChange = jest.fn();
|
||||
const onTimeChange = vi.fn();
|
||||
renderPlayer({ onTimeChange });
|
||||
startPlayback();
|
||||
|
||||
@@ -150,7 +153,7 @@ test('interpolates at the anchor speed', () => {
|
||||
});
|
||||
|
||||
test('holds the time while paused', () => {
|
||||
const onTimeChange = jest.fn();
|
||||
const onTimeChange = vi.fn();
|
||||
renderPlayer({ onTimeChange });
|
||||
startPlayback();
|
||||
|
||||
+2
@@ -16,6 +16,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { theme } from 'design/utils/testing';
|
||||
|
||||
import {
|
||||
+12
-5
@@ -16,6 +16,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { vi, test, afterEach, expect, beforeEach } from 'vitest';
|
||||
|
||||
import { theme } from 'design/utils/testing';
|
||||
|
||||
import { SessionRecordingThumbnail } from 'teleport/services/recordings';
|
||||
@@ -24,10 +26,10 @@ import type { TimelineRenderContext } from 'teleport/SessionRecordings/view/Time
|
||||
import { FramesRenderer, type LoadedImageResult } from './FramesRenderer';
|
||||
|
||||
// Mock the SVG utilities
|
||||
jest.mock('teleport/SessionRecordings/svg', () => ({
|
||||
generateTerminalSVGStyleTag: jest.fn(() => '<style></style>'),
|
||||
injectSVGStyles: jest.fn(svg => svg),
|
||||
svgToDataURIBase64: jest.fn(svg => `data:image/svg+xml;base64,${svg}`),
|
||||
vi.mock('teleport/SessionRecordings/svg', () => ({
|
||||
generateTerminalSVGStyleTag: vi.fn(() => '<style></style>'),
|
||||
injectSVGStyles: vi.fn(svg => svg),
|
||||
svgToDataURIBase64: vi.fn(svg => `data:image/svg+xml;base64,${svg}`),
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -37,7 +39,12 @@ beforeEach(() => {
|
||||
value: 1,
|
||||
});
|
||||
|
||||
global.OffscreenCanvas = jest.fn().mockImplementation((width, height) => {
|
||||
// Regular function, not an arrow: it's constructed with `new` and arrows
|
||||
// aren't constructors.
|
||||
global.OffscreenCanvas = vi.fn().mockImplementation(function (
|
||||
width: number,
|
||||
height: number
|
||||
) {
|
||||
const canvas = document.createElement('canvas');
|
||||
|
||||
canvas.width = width;
|
||||
+2
@@ -16,6 +16,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import { theme } from 'design/utils/testing';
|
||||
|
||||
import { SessionRecordingMetadata } from 'teleport/services/recordings';
|
||||
+10
-8
@@ -16,6 +16,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { theme } from 'design/utils/testing';
|
||||
|
||||
import { SessionRecordingMetadata } from 'teleport/services/recordings';
|
||||
@@ -266,7 +268,7 @@ describe('visibility', () => {
|
||||
|
||||
// Should only render markers visible in the viewport (with 100px buffer)
|
||||
// At this zoom and offset, should see markers starting from 9 seconds
|
||||
expect(fillTextCalls.length).toBe(8); // 9s, 10s, 11s, 12s, 13s, 14s, 15s, 16s
|
||||
expect(fillTextCalls).toHaveLength(8); // 9s, 10s, 11s, 12s, 13s, 14s, 15s, 16s
|
||||
|
||||
// Check that we're seeing markers in the expected range
|
||||
const visibleTexts = fillTextCalls.map(call => call.props.text);
|
||||
@@ -304,7 +306,7 @@ describe('sub-tick rendering', () => {
|
||||
|
||||
// At high zoom with 1-second intervals, should have 7 sub-ticks per interval
|
||||
// 10 intervals × 7 sub-ticks = 70 sub-ticks total
|
||||
expect(subTickCalls.length).toBe(70);
|
||||
expect(subTickCalls).toHaveLength(70);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -333,9 +335,9 @@ describe('label spacing', () => {
|
||||
|
||||
// At very low zoom, should show 60-second intervals with label skipping
|
||||
// Should render 11 tick marks (one every 60s for 10 minutes)
|
||||
expect(fillRectCalls.length).toBe(11);
|
||||
expect(fillRectCalls).toHaveLength(11);
|
||||
// Should show only 4 labels due to label skipping
|
||||
expect(fillTextCalls.length).toBe(4);
|
||||
expect(fillTextCalls).toHaveLength(4);
|
||||
|
||||
expect(fillTextCalls[0].props.text).toBe('0:00');
|
||||
expect(fillTextCalls[1].props.text).toBe('3:00');
|
||||
@@ -366,7 +368,7 @@ describe('label spacing', () => {
|
||||
);
|
||||
|
||||
// When markers are well-spaced, should show all labels
|
||||
expect(fillTextCalls.length).toBe(fillRectCalls.length);
|
||||
expect(fillTextCalls).toHaveLength(fillRectCalls.length);
|
||||
});
|
||||
|
||||
it('should render tick marks even when labels are hidden', () => {
|
||||
@@ -391,7 +393,7 @@ describe('label spacing', () => {
|
||||
);
|
||||
|
||||
// Should render 6 tick marks (one every 60s for 5 minutes)
|
||||
expect(fillRectCalls.length).toBe(6);
|
||||
expect(fillRectCalls).toHaveLength(6);
|
||||
});
|
||||
|
||||
it('should use 30-second intervals when very zoomed out', () => {
|
||||
@@ -415,7 +417,7 @@ describe('label spacing', () => {
|
||||
|
||||
// Should use 30-second intervals when pixelsPerSecond < 5
|
||||
// With label skipping (every 10th marker), should show 7 labels
|
||||
expect(fillTextCalls.length).toBe(7);
|
||||
expect(fillTextCalls).toHaveLength(7);
|
||||
});
|
||||
|
||||
it('should use 60-second intervals when extremely zoomed out', () => {
|
||||
@@ -439,6 +441,6 @@ describe('label spacing', () => {
|
||||
|
||||
// Should use 60-second intervals when pixelsPerSecond < 2
|
||||
// With label skipping (every 10th marker), should show 7 labels
|
||||
expect(fillTextCalls.length).toBe(7);
|
||||
expect(fillTextCalls).toHaveLength(7);
|
||||
});
|
||||
});
|
||||
+8
-6
@@ -16,6 +16,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { vi, beforeEach, afterEach, expect, describe, it } from 'vitest';
|
||||
|
||||
import { theme } from 'design/utils/testing';
|
||||
|
||||
import {
|
||||
@@ -127,22 +129,22 @@ function createRenderer(
|
||||
let animationFrameCallback: FrameRequestCallback | null = null;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
|
||||
// Mock requestAnimationFrame to capture the callback
|
||||
global.requestAnimationFrame = jest.fn(callback => {
|
||||
global.requestAnimationFrame = vi.fn(callback => {
|
||||
animationFrameCallback = callback;
|
||||
return 1;
|
||||
});
|
||||
|
||||
global.cancelAnimationFrame = jest.fn();
|
||||
global.cancelAnimationFrame = vi.fn();
|
||||
|
||||
// Mock performance.now
|
||||
jest.spyOn(performance, 'now').mockReturnValue(0);
|
||||
vi.spyOn(performance, 'now').mockReturnValue(0);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
vi.restoreAllMocks();
|
||||
animationFrameCallback = null;
|
||||
});
|
||||
|
||||
@@ -407,7 +409,7 @@ describe('wheel accumulation cleanup', () => {
|
||||
renderer.accumulatePan(50);
|
||||
|
||||
// Simulate time passing
|
||||
jest.spyOn(performance, 'now').mockReturnValue(50);
|
||||
vi.spyOn(performance, 'now').mockReturnValue(50);
|
||||
|
||||
for (let i = 0; i < 50; i++) {
|
||||
if (animationFrameCallback) {
|
||||
+16
-19
@@ -21,17 +21,12 @@ import { screen } from '@testing-library/react';
|
||||
import { http, HttpResponse } from 'msw';
|
||||
import type { ComponentType } from 'react';
|
||||
import { MemoryRouter, Route, Routes } from 'react-router';
|
||||
import { vi, expect, test, afterEach } from 'vitest';
|
||||
|
||||
import {
|
||||
enableMswServer,
|
||||
render,
|
||||
server,
|
||||
testQueryClient,
|
||||
} from 'design/utils/testing';
|
||||
import { render, server, testQueryClient } from 'design/utils/testing';
|
||||
|
||||
import { ContextProvider } from 'teleport';
|
||||
import cfg from 'teleport/config';
|
||||
import { MockAuthenticatedWebSocket } from 'teleport/lib/AuthenticatedWebSocket.mock';
|
||||
import { createTeleportContext } from 'teleport/mocks/contexts';
|
||||
import {
|
||||
type RecordingType,
|
||||
@@ -42,19 +37,21 @@ import type { RecordingWithSummaryProps } from 'teleport/SessionRecordings/view/
|
||||
import { createMetadataHandler } from './mock';
|
||||
import { ViewSessionRecordingRoute } from './ViewSessionRecordingRoute';
|
||||
|
||||
jest.spyOn(cfg, 'getSessionRecordingMetadataUrl').mockImplementation(() => {
|
||||
return 'ws://localhost/v1/webapi/sites/:clusterId/sessionrecording/:sessionId/metadata/ws';
|
||||
});
|
||||
vi.spyOn(cfg, 'getSessionRecordingMetadataUrl').mockReturnValue(
|
||||
'ws://localhost/v1/webapi/sites/:clusterId/sessionrecording/:sessionId/metadata/ws'
|
||||
);
|
||||
|
||||
jest.mock('teleport/lib/AuthenticatedWebSocket', () => ({
|
||||
AuthenticatedWebSocket: MockAuthenticatedWebSocket,
|
||||
// Import the mock inside the factory: vi.mock is hoisted above the file's imports, so referencing a top-level
|
||||
// import binding here risks a before-initialization error.
|
||||
vi.mock('teleport/lib/AuthenticatedWebSocket', async () => ({
|
||||
AuthenticatedWebSocket: (
|
||||
await import('teleport/lib/AuthenticatedWebSocket.mock')
|
||||
).MockAuthenticatedWebSocket,
|
||||
}));
|
||||
|
||||
enableMswServer();
|
||||
|
||||
afterEach(() => {
|
||||
testQueryClient.clear();
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
const mockMetadata: SessionRecordingMetadata = {
|
||||
@@ -71,7 +68,7 @@ const mockMetadata: SessionRecordingMetadata = {
|
||||
};
|
||||
|
||||
// mock the RecordingPlayer component
|
||||
jest.mock('./RecordingPlayer', () => ({
|
||||
vi.mock('./RecordingPlayer', () => ({
|
||||
RecordingPlayer: ({ clusterId, sessionId, durationMs, recordingType }) => (
|
||||
<div data-testid="recording-player">
|
||||
RecordingPlayer: {clusterId}/{sessionId}/{durationMs}/{recordingType}
|
||||
@@ -176,7 +173,7 @@ test('renders non-SSH recordings correctly', async () => {
|
||||
});
|
||||
|
||||
test('falls back to the player when the custom summary component fails to load', async () => {
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
server.use(createMetadataHandler({ ...mockMetadata, type: 'desktop' }, []));
|
||||
|
||||
@@ -278,7 +275,7 @@ test('falls back to loading the duration if metadata is not available and no URL
|
||||
});
|
||||
|
||||
test('falls back to the session player if metadata is not available', async () => {
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
server.use(
|
||||
createMetadataHandler(mockMetadata, [], {
|
||||
@@ -304,7 +301,7 @@ test('falls back to the session player if metadata is not available', async () =
|
||||
});
|
||||
|
||||
test('shows error if metadata and duration are not available', async () => {
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
server.use(
|
||||
createMetadataHandler(mockMetadata, [], {
|
||||
+15
-13
@@ -18,6 +18,8 @@
|
||||
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
import { vi, expect, describe, it } from 'vitest';
|
||||
|
||||
import {
|
||||
PlayerState,
|
||||
SessionStream,
|
||||
@@ -47,7 +49,7 @@ describe('play', () => {
|
||||
it('should not transition to playing whilst loading', () => {
|
||||
const { stream } = setup();
|
||||
|
||||
const stateListener = jest.fn();
|
||||
const stateListener = vi.fn();
|
||||
stream.on('state', stateListener);
|
||||
|
||||
stream.play();
|
||||
@@ -122,7 +124,7 @@ describe('pause', () => {
|
||||
it('should transition from playing to paused', () => {
|
||||
const { stream, ws } = setup();
|
||||
|
||||
const stateListener = jest.fn();
|
||||
const stateListener = vi.fn();
|
||||
stream.on('state', stateListener);
|
||||
|
||||
stream.loadInitial();
|
||||
@@ -158,7 +160,7 @@ describe('pause', () => {
|
||||
it('should not do anything if already paused', () => {
|
||||
const { stream, ws } = setup();
|
||||
|
||||
const stateListener = jest.fn();
|
||||
const stateListener = vi.fn();
|
||||
|
||||
stream.loadInitial();
|
||||
ws.receiveMessage(
|
||||
@@ -177,7 +179,7 @@ describe('seek', () => {
|
||||
it('should emit time event when seeking', () => {
|
||||
const { stream, ws } = setup();
|
||||
|
||||
const timeListener = jest.fn();
|
||||
const timeListener = vi.fn();
|
||||
stream.on('time', timeListener);
|
||||
|
||||
stream.loadInitial();
|
||||
@@ -227,7 +229,7 @@ describe('seek', () => {
|
||||
|
||||
describe('event handling', () => {
|
||||
it('should ignore messages with wrong requestId', () => {
|
||||
jest.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
vi.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
|
||||
const { stream, ws, player } = setup();
|
||||
|
||||
@@ -243,7 +245,7 @@ describe('event handling', () => {
|
||||
it('should stop when an end event is encountered', () => {
|
||||
const { stream, ws } = setup();
|
||||
|
||||
const stateListener = jest.fn();
|
||||
const stateListener = vi.fn();
|
||||
|
||||
stream.loadInitial();
|
||||
|
||||
@@ -255,8 +257,8 @@ describe('event handling', () => {
|
||||
])
|
||||
);
|
||||
|
||||
jest.spyOn(performance, 'now').mockReturnValueOnce(0);
|
||||
jest.spyOn(performance, 'now').mockReturnValueOnce(400);
|
||||
vi.spyOn(performance, 'now').mockReturnValueOnce(0);
|
||||
vi.spyOn(performance, 'now').mockReturnValueOnce(400);
|
||||
|
||||
stream.on('state', stateListener);
|
||||
stream.play();
|
||||
@@ -269,7 +271,7 @@ describe('time events', () => {
|
||||
it('should emit time events during playback', () => {
|
||||
const { stream, ws } = setup();
|
||||
|
||||
const timeListener = jest.fn();
|
||||
const timeListener = vi.fn();
|
||||
stream.on('time', timeListener);
|
||||
|
||||
stream.loadInitial();
|
||||
@@ -388,10 +390,10 @@ class MockPlayer extends Player<MockEvent> {
|
||||
this.events = [];
|
||||
}
|
||||
|
||||
onPlay = jest.fn();
|
||||
onPause = jest.fn();
|
||||
onSeek = jest.fn();
|
||||
onStop = jest.fn();
|
||||
onPlay = vi.fn();
|
||||
onPause = vi.fn();
|
||||
onSeek = vi.fn();
|
||||
onStop = vi.fn();
|
||||
}
|
||||
|
||||
interface WebSocketEventMap {
|
||||
+3
-1
@@ -16,12 +16,14 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { vi, expect, test } from 'vitest';
|
||||
|
||||
import api from 'teleport/services/api';
|
||||
|
||||
import RecordingsService from './recordings';
|
||||
|
||||
test('fetch session recordings, response formatting', async () => {
|
||||
jest.spyOn(api, 'get').mockResolvedValue(recordingsJSON);
|
||||
vi.spyOn(api, 'get').mockResolvedValue(recordingsJSON);
|
||||
|
||||
const recordings = new RecordingsService();
|
||||
const response = await recordings.fetchRecordings('im-a-cluster', {
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Teleport
|
||||
* Copyright (C) 2026 Gravitational, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { spawnSync } from 'node:child_process';
|
||||
|
||||
// Routes `pnpm test <args>` during the jest -> vitest migration. Vitest owns *.vitest.{ts,tsx} files, Jest owns
|
||||
// *.test.{ts,tsx}. A positional naming neither (a directory or a bare path fragment) goes to both runners, since
|
||||
// each one's own testMatch/include already narrows the filter to the files it owns. With no args, both full
|
||||
// suites run.
|
||||
//
|
||||
// For advanced flag combos across a mixture (e.g. `-t <pattern>` alongside both file kinds), run `pnpm jest` or
|
||||
// `pnpm vitest` directly, since a flag can only be forwarded verbatim to each selected runner. Watching a path is
|
||||
// one such case: the runners are spawned in sequence, so the first watcher holds the terminal and the second
|
||||
// never starts.
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const isVitestFile = arg => arg.includes('.vitest.');
|
||||
const isJestFile = arg => arg.includes('.test.');
|
||||
|
||||
const flags = args.filter(arg => arg.startsWith('-'));
|
||||
const positionals = args.filter(arg => !arg.startsWith('-'));
|
||||
const vitestFiles = positionals.filter(isVitestFile);
|
||||
const jestFiles = positionals.filter(isJestFile);
|
||||
const paths = positionals.filter(arg => !isVitestFile(arg) && !isJestFile(arg));
|
||||
|
||||
const commands = [];
|
||||
if (args.length === 0) {
|
||||
// Bare `pnpm test`: run both full suites, unchanged from before the wrapper existed.
|
||||
commands.push(['jest', []], ['vitest', ['run']]);
|
||||
} else {
|
||||
// A path filter can legitimately match files for only one runner, so neither may fail on an empty selection.
|
||||
const passWithNoTests = paths.length > 0 ? ['--passWithNoTests'] : [];
|
||||
// Run Jest when it owns a positional, or when only flags were passed so `pnpm test --watch` still starts Jest.
|
||||
if (jestFiles.length > 0 || paths.length > 0 || vitestFiles.length === 0) {
|
||||
commands.push([
|
||||
'jest',
|
||||
[...passWithNoTests, ...flags, ...jestFiles, ...paths],
|
||||
]);
|
||||
}
|
||||
if (vitestFiles.length > 0 || paths.length > 0) {
|
||||
commands.push([
|
||||
'vitest',
|
||||
['run', ...passWithNoTests, ...flags, ...vitestFiles, ...paths],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
let exitCode = 0;
|
||||
for (const [command, commandArgs] of commands) {
|
||||
const { status, error } = spawnSync(command, commandArgs, {
|
||||
stdio: 'inherit',
|
||||
});
|
||||
if (error) {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
}
|
||||
if (status !== 0 && exitCode === 0) {
|
||||
exitCode = status ?? 1;
|
||||
}
|
||||
}
|
||||
|
||||
process.exit(exitCode);
|
||||
Reference in New Issue
Block a user