@testspectra/cli 1.1.7 → 1.1.8-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/.testspectra-runner.hash +1 -1
- package/bin/spectra.js +0 -0
- package/bin/testspectra-runner.exe +0 -0
- package/demo-app/assets/index-BhlW-eXG.css +1 -0
- package/demo-app/assets/index-DOtRypCa.js +154 -0
- package/demo-app/index.html +2 -2
- package/dist/.tsbuildinfo +1 -1
- package/dist/commands/__tests__/run-e2e.test.js +270 -29
- package/dist/commands/__tests__/run.test.js +92 -16
- package/dist/commands/demo.js +17 -7
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.js +154 -149
- package/dist/commands/lint.d.ts +5 -0
- package/dist/commands/lint.js +55 -0
- package/dist/commands/refactor.d.ts +2 -1
- package/dist/commands/refactor.js +129 -35
- package/dist/commands/run.d.ts +2 -3
- package/dist/commands/run.js +93 -28
- package/dist/commands/skills.d.ts +9 -0
- package/dist/commands/skills.js +28 -0
- package/dist/commands/sync-types.js +1 -0
- package/dist/commands/test.d.ts +17 -0
- package/dist/commands/test.js +104 -0
- package/dist/commands/watch.js +9 -3
- package/dist/config/loader.js +1 -1
- package/dist/config/schema.d.ts +5 -114
- package/dist/config/schema.js +1 -17
- package/dist/generator/__tests__/tsconfig-isolation.test.js +6 -2
- package/dist/generator/__tests__/type-generator.test.js +1 -1
- package/dist/generator/tsconfig-generator.js +44 -16
- package/dist/generator/type-generator.d.ts +24 -1
- package/dist/generator/type-generator.js +104 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +76 -40
- package/dist/linter/__tests__/anonymous-export.test.js +184 -0
- package/dist/linter/__tests__/component-test-imports.test.d.ts +1 -0
- package/dist/linter/__tests__/component-test-imports.test.js +115 -0
- package/dist/linter/__tests__/shared-lib-boundary.test.d.ts +1 -0
- package/dist/linter/__tests__/shared-lib-boundary.test.js +270 -0
- package/dist/linter/__tests__/spec-schema.test.d.ts +1 -0
- package/dist/linter/__tests__/spec-schema.test.js +369 -0
- package/dist/linter/__tests__/step-parity.test.d.ts +1 -0
- package/dist/linter/__tests__/step-parity.test.js +372 -0
- package/dist/linter/discovery.d.ts +30 -0
- package/dist/linter/discovery.js +249 -0
- package/dist/linter/extractor.d.ts +67 -0
- package/dist/linter/extractor.js +245 -0
- package/dist/linter/index.d.ts +7 -0
- package/dist/linter/index.js +7 -0
- package/dist/linter/parser.d.ts +24 -0
- package/dist/linter/parser.js +219 -0
- package/dist/linter/schemas/spec.schema.d.ts +83 -0
- package/dist/linter/schemas/spec.schema.js +150 -0
- package/dist/linter/schemas/suite.schema.d.ts +59 -0
- package/dist/linter/schemas/suite.schema.js +83 -0
- package/dist/linter/spec-linter.d.ts +23 -0
- package/dist/linter/spec-linter.js +630 -0
- package/dist/linter/types.d.ts +28 -0
- package/dist/linter/types.js +1 -0
- package/dist/refactor/__tests__/refactor-engine.test.js +698 -0
- package/dist/refactor/refactor-engine.d.ts +25 -0
- package/dist/refactor/refactor-engine.js +374 -42
- package/dist/reporter/semantic-formatter.js +22 -2
- package/dist/reporter/types.d.ts +1 -1
- package/dist/runner/bridge.d.ts +1 -1
- package/dist/runner/bridge.js +34 -21
- package/dist/runner/reporter.d.ts +2 -0
- package/dist/runner/reporter.js +11 -3
- package/dist/utils/__tests__/api-server.test.d.ts +1 -0
- package/dist/utils/__tests__/api-server.test.js +62 -0
- package/dist/utils/__tests__/demo-server.test.d.ts +1 -0
- package/dist/utils/__tests__/demo-server.test.js +35 -0
- package/dist/utils/api-server.d.ts +19 -0
- package/dist/utils/api-server.js +179 -0
- package/dist/utils/demo-server.d.ts +5 -0
- package/dist/utils/demo-server.js +8 -1
- package/package.json +29 -25
- package/templates/default/CLAUDE.md +16 -11
- package/templates/default/global-hooks/after/mobile.hook.ts +3 -3
- package/templates/default/global-hooks/after/web.hook.ts +3 -3
- package/templates/default/global-hooks/before/mobile.hook.ts +3 -3
- package/templates/default/global-hooks/before/web.hook.ts +3 -3
- package/templates/default/package.json +3 -3
- package/templates/default/page-objects/AuthPage/mobile.ts +5 -0
- package/templates/default/page-objects/AuthPage/web.ts +10 -0
- package/templates/default/page-objects/MatchersPage/mobile.ts +70 -46
- package/templates/default/page-objects/MatchersPage/web.ts +43 -37
- package/templates/default/page-objects/NavigationPage/mobile.ts +14 -14
- package/templates/default/page-objects/NavigationPage/web.ts +8 -8
- package/templates/default/page-objects/PlaygroundPage/mobile.ts +42 -36
- package/templates/default/page-objects/PlaygroundPage/web.ts +31 -31
- package/templates/default/specs/ApiInterception/TC-0008-fetch-mocking/mobile.test.ts +53 -11
- package/templates/default/specs/ApiInterception/TC-0008-fetch-mocking/spec.md +19 -12
- package/templates/default/specs/ApiInterception/TC-0008-fetch-mocking/web.test.ts +31 -27
- package/templates/default/specs/ApiInterception/TC-0009-post-mocking/android.test.ts +3 -0
- package/templates/default/specs/ApiInterception/TC-0009-post-mocking/common.test.ts +3 -0
- package/templates/default/specs/ApiInterception/TC-0009-post-mocking/mobile.test.ts +27 -16
- package/templates/default/specs/ApiInterception/TC-0009-post-mocking/spec.md +19 -12
- package/templates/default/specs/ApiInterception/TC-0009-post-mocking/web.test.ts +26 -24
- package/templates/default/specs/ApiInterception/TC-0012-direct-and-late-response/common.test.ts +30 -0
- package/templates/default/specs/ApiInterception/TC-0012-direct-and-late-response/spec.md +22 -0
- package/templates/default/specs/ApiInterception/TC-0013-real-network-call-recorded/common.test.ts +27 -0
- package/templates/default/specs/ApiInterception/TC-0013-real-network-call-recorded/spec.md +20 -0
- package/templates/default/specs/ApiInterception/TC-0015-mock-server-sent-events/spec.md +24 -0
- package/templates/default/specs/ApiInterception/TC-0015-mock-server-sent-events/web.test.ts +26 -0
- package/templates/default/specs/ApiInterception/TC-0016-bypass-websocket-with-app-level-mock/spec.md +37 -0
- package/templates/default/specs/ApiInterception/TC-0016-bypass-websocket-with-app-level-mock/web.test.ts +21 -0
- package/templates/default/specs/ApiInterception/TC-0017-bypass-captcha-with-test-mode-flag/spec.md +29 -0
- package/templates/default/specs/ApiInterception/TC-0017-bypass-captcha-with-test-mode-flag/web.test.ts +16 -0
- package/templates/default/specs/ApiInterception/suite.md +10 -9
- package/templates/default/specs/ApiSeeding/TC-0014-seed-and-cleanup-via-hooks/common.test.ts +30 -0
- package/templates/default/specs/ApiSeeding/TC-0014-seed-and-cleanup-via-hooks/spec.md +23 -0
- package/templates/default/specs/ApiSeeding/hooks/after/common.hook.ts +16 -0
- package/templates/default/specs/ApiSeeding/hooks/before/common.hook.ts +28 -0
- package/templates/default/specs/ApiSeeding/suite.md +9 -0
- package/templates/default/specs/Authentication/TC-0021-seed-authenticated-session/mobile.test.ts +7 -0
- package/templates/default/specs/Authentication/TC-0021-seed-authenticated-session/spec.md +19 -0
- package/templates/default/specs/Authentication/TC-0021-seed-authenticated-session/web.test.ts +9 -0
- package/templates/default/specs/Authentication/suite.md +9 -0
- package/templates/default/specs/BrowserContext/TC-0007-title-and-navigation/mobile.test.ts +9 -9
- package/templates/default/specs/BrowserContext/TC-0007-title-and-navigation/spec.md +17 -12
- package/templates/default/specs/BrowserContext/TC-0007-title-and-navigation/web.test.ts +19 -19
- package/templates/default/specs/BrowserContext/TC-0022-history-navigation/mobile.test.ts +17 -0
- package/templates/default/specs/BrowserContext/TC-0022-history-navigation/spec.md +28 -0
- package/templates/default/specs/BrowserContext/TC-0022-history-navigation/web.test.ts +26 -0
- package/templates/default/specs/ContentMatchers/TC-0005-text-and-values/common.test.ts +26 -0
- package/templates/default/specs/ContentMatchers/TC-0005-text-and-values/spec.md +19 -12
- package/templates/default/specs/ContentMatchers/TC-0006-collections-and-empty/mobile.test.ts +11 -11
- package/templates/default/specs/ContentMatchers/TC-0006-collections-and-empty/spec.md +17 -12
- package/templates/default/specs/ContentMatchers/TC-0006-collections-and-empty/web.test.ts +11 -11
- package/templates/default/specs/ContentMatchers/TC-0020-scoped-element-access/common.test.ts +14 -0
- package/templates/default/specs/ContentMatchers/TC-0020-scoped-element-access/spec.md +21 -0
- package/templates/default/specs/DeepLink/TC-0018-navigate-via-deep-link/mobile.test.ts +28 -0
- package/templates/default/specs/DeepLink/TC-0018-navigate-via-deep-link/spec.md +29 -0
- package/templates/default/specs/DeepLink/suite.md +9 -0
- package/templates/default/specs/ElementMatchers/TC-0003-visibility-and-dom/mobile.test.ts +11 -11
- package/templates/default/specs/ElementMatchers/TC-0003-visibility-and-dom/spec.md +17 -12
- package/templates/default/specs/ElementMatchers/TC-0003-visibility-and-dom/web.test.ts +11 -11
- package/templates/default/specs/ElementMatchers/TC-0004-states-and-attributes/mobile.test.ts +29 -29
- package/templates/default/specs/ElementMatchers/TC-0004-states-and-attributes/spec.md +19 -12
- package/templates/default/specs/ElementMatchers/TC-0004-states-and-attributes/web.test.ts +29 -29
- package/templates/default/specs/ElementMatchers/suite.md +10 -9
- package/templates/default/specs/EnvironmentConfig/TC-0019-read-custom-environment-variable/common.test.ts +5 -0
- package/templates/default/specs/EnvironmentConfig/TC-0019-read-custom-environment-variable/spec.md +16 -0
- package/templates/default/specs/EnvironmentConfig/suite.md +9 -0
- package/templates/default/specs/PermissionRationale/TC-0010-camera-permission-allow/mobile.test.ts +26 -0
- package/templates/default/specs/PermissionRationale/TC-0010-camera-permission-allow/spec.md +22 -0
- package/templates/default/specs/PermissionRationale/TC-0011-camera-permission-deny/mobile.test.ts +13 -0
- package/templates/default/specs/PermissionRationale/TC-0011-camera-permission-deny/spec.md +20 -0
- package/templates/default/specs/PermissionRationale/suite.md +9 -0
- package/templates/default/specs/Playground/TC-0001-form-controls/mobile.test.ts +6 -6
- package/templates/default/specs/Playground/TC-0001-form-controls/spec.md +18 -12
- package/templates/default/specs/Playground/TC-0001-form-controls/web.test.ts +6 -6
- package/templates/default/specs/Playground/TC-0002-toggle-elements/mobile.test.ts +6 -6
- package/templates/default/specs/Playground/TC-0002-toggle-elements/spec.md +18 -12
- package/templates/default/specs/Playground/TC-0002-toggle-elements/web.test.ts +6 -6
- package/templates/default/spectra.config.ts +52 -68
- package/templates/default/support/actions/fillCredentials/mobile.action.ts +4 -4
- package/templates/default/support/actions/fillCredentials/web.action.ts +4 -4
- package/templates/default/support/actions/seedSession/mobile.action.ts +9 -0
- package/templates/default/support/actions/seedSession/web.action.ts +13 -0
- package/templates/default/support/steps/togglePlaygroundStates/mobile.step.ts +5 -5
- package/templates/default/support/steps/togglePlaygroundStates/web.step.ts +5 -5
- package/templates/default/support/steps/verifyPlaygroundState/mobile.step.ts +6 -6
- package/templates/default/support/steps/verifyPlaygroundState/web.step.ts +6 -6
- package/templates/nx/.nx/workspace-data/59842386-c7c4-44ca-b2c2-20e1700bd13d.db +0 -0
- package/templates/nx/.nx/workspace-data/59842386-c7c4-44ca-b2c2-20e1700bd13d.db-shm +0 -0
- package/templates/nx/.nx/workspace-data/59842386-c7c4-44ca-b2c2-20e1700bd13d.db-wal +0 -0
- package/templates/nx/.nx/workspace-data/d/daemon.log +1577 -168
- package/templates/nx/.nx/workspace-data/d/server-process.json +3 -0
- package/templates/nx/.nx/workspace-data/file-map.json +464 -0
- package/templates/nx/.nx/workspace-data/lockfile.hash +1 -0
- package/templates/nx/.nx/workspace-data/nx_files.nxt +0 -0
- package/templates/nx/.nx/workspace-data/parsed-lock-file.json +13485 -0
- package/templates/nx/.nx/workspace-data/project-graph.json +14389 -0
- package/templates/nx/CLAUDE.md +10 -10
- package/templates/nx/package.json +3 -3
- package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0008-fetch-mocking/mobile.test.ts +27 -3
- package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0008-fetch-mocking/web.test.ts +27 -27
- package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0009-post-mocking/mobile.test.ts +24 -3
- package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0009-post-mocking/web.test.ts +24 -24
- package/templates/nx/packages/matchers/e2e/specs/BrowserContext/TC-0007-title-and-navigation/mobile.test.ts +3 -3
- package/templates/nx/packages/matchers/e2e/specs/BrowserContext/TC-0007-title-and-navigation/web.test.ts +19 -19
- package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0005-text-and-values/mobile.test.ts +3 -3
- package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0005-text-and-values/web.test.ts +17 -17
- package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0006-collections-and-empty/mobile.test.ts +3 -3
- package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0006-collections-and-empty/web.test.ts +11 -11
- package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0003-visibility-and-dom/mobile.test.ts +3 -3
- package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0003-visibility-and-dom/web.test.ts +11 -11
- package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0004-states-and-attributes/mobile.test.ts +3 -3
- package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0004-states-and-attributes/web.test.ts +29 -29
- package/templates/nx/packages/matchers/e2e/specs/EnvironmentConfig/TC-0019-read-custom-environment-variable/common.test.ts +5 -0
- package/templates/nx/packages/matchers/e2e/specs/EnvironmentConfig/TC-0019-read-custom-environment-variable/spec.md +16 -0
- package/templates/nx/packages/matchers/e2e/specs/EnvironmentConfig/suite.md +9 -0
- package/templates/nx/packages/playground/e2e/specs/Playground/TC-0001-form-controls/mobile.test.ts +3 -3
- package/templates/nx/packages/playground/e2e/specs/Playground/TC-0001-form-controls/web.test.ts +6 -6
- package/templates/nx/packages/playground/e2e/specs/Playground/TC-0002-toggle-elements/mobile.test.ts +3 -3
- package/templates/nx/packages/playground/e2e/specs/Playground/TC-0002-toggle-elements/web.test.ts +6 -6
- package/templates/nx/pnpm-lock.yaml +6663 -6663
- package/templates/nx/pnpm-workspace.yaml +9 -9
- package/templates/nx/shared/testing/page-objects/MatchersPage/mobile.ts +33 -33
- package/templates/nx/shared/testing/page-objects/MatchersPage/web.ts +91 -37
- package/templates/nx/shared/testing/page-objects/NavigationPage/mobile.ts +5 -5
- package/templates/nx/shared/testing/page-objects/NavigationPage/web.ts +8 -8
- package/templates/nx/shared/testing/page-objects/PlaygroundPage/mobile.ts +26 -26
- package/templates/nx/shared/testing/page-objects/PlaygroundPage/web.ts +31 -31
- package/templates/nx/shared/testing/project.json +19 -19
- package/templates/nx/shared/testing/support/actions/fillCredentials/mobile.action.ts +4 -4
- package/templates/nx/shared/testing/support/actions/fillCredentials/web.action.ts +4 -4
- package/templates/nx/shared/testing/support/steps/togglePlaygroundStates/mobile.step.ts +3 -3
- package/templates/nx/shared/testing/support/steps/togglePlaygroundStates/web.step.ts +5 -5
- package/templates/nx/shared/testing/support/steps/verifyPlaygroundState/mobile.step.ts +4 -4
- package/templates/nx/shared/testing/support/steps/verifyPlaygroundState/web.step.ts +6 -6
- package/templates/nx/spectra.config.ts +52 -68
- package/templates/react-component/.cursorrules +17 -0
- package/templates/react-component/.vscode/extensions.json +5 -0
- package/templates/react-component/CLAUDE.md +14 -0
- package/templates/react-component/README.md +69 -0
- package/templates/react-component/fixtures/component-mock.json +12 -0
- package/templates/react-component/global-hooks/after/web.hook.ts +3 -0
- package/templates/react-component/global-hooks/before/web.hook.ts +3 -0
- package/templates/react-component/package.json +27 -0
- package/templates/react-component/page-objects/BadgeComponent/web.ts +23 -0
- package/templates/react-component/page-objects/ButtonComponent/web.ts +23 -0
- package/templates/react-component/page-objects/InputComponent/web.ts +13 -0
- package/templates/react-component/specs/BadgeComponent/TC-0002-badge-severities-and-dot/spec.md +18 -0
- package/templates/react-component/specs/BadgeComponent/TC-0002-badge-severities-and-dot/web.test.tsx +11 -0
- package/templates/react-component/specs/BadgeComponent/TC-0006-badge-success-with-dot/spec.md +18 -0
- package/templates/react-component/specs/BadgeComponent/TC-0006-badge-success-with-dot/web.test.tsx +10 -0
- package/templates/react-component/specs/BadgeComponent/TC-0007-badge-by-severity-lookup/spec.md +18 -0
- package/templates/react-component/specs/BadgeComponent/TC-0007-badge-by-severity-lookup/web.test.tsx +16 -0
- package/templates/react-component/specs/BadgeComponent/suite.md +12 -0
- package/templates/react-component/specs/ButtonComponent/TC-0001-button-rendering-and-click/spec.md +19 -0
- package/templates/react-component/specs/ButtonComponent/TC-0001-button-rendering-and-click/web.test.tsx +28 -0
- package/templates/react-component/specs/ButtonComponent/TC-0004-disabled-button-not-clickable/spec.md +19 -0
- package/templates/react-component/specs/ButtonComponent/TC-0004-disabled-button-not-clickable/web.test.tsx +22 -0
- package/templates/react-component/specs/ButtonComponent/TC-0005-button-renders-icon/spec.md +18 -0
- package/templates/react-component/specs/ButtonComponent/TC-0005-button-renders-icon/web.test.tsx +8 -0
- package/templates/react-component/specs/ButtonComponent/suite.md +12 -0
- package/templates/react-component/specs/InputComponent/TC-0003-input-typing-and-clear/spec.md +20 -0
- package/templates/react-component/specs/InputComponent/TC-0003-input-typing-and-clear/web.test.tsx +28 -0
- package/templates/react-component/specs/InputComponent/TC-0008-disabled-input-not-editable/spec.md +18 -0
- package/templates/react-component/specs/InputComponent/TC-0008-disabled-input-not-editable/web.test.tsx +9 -0
- package/templates/react-component/specs/InputComponent/suite.md +12 -0
- package/templates/react-component/spectra.config.ts +27 -0
- package/templates/react-component/src/components/Badge/Badge.tsx +60 -0
- package/templates/react-component/src/components/Button/Button.tsx +57 -0
- package/templates/react-component/src/components/Input/Input.tsx +41 -0
- package/templates/react-component/src/test-utils.tsx +23 -0
- package/templates/react-component/support/actions/fillInputField/web.action.ts +9 -0
- package/templates/react-component/support/steps/verifyButtonState/web.step.ts +12 -0
- package/templates/react-component/tsconfig.json +8 -0
- package/bin/testspectra-runner +0 -0
- package/demo-app/assets/index-DPfv5_EF.js +0 -116
- package/demo-app/assets/index-gIwu2EMV.css +0 -1
- package/dist/commands/__tests__/cloud-run.test.js +0 -93
- package/dist/commands/cloud-run.d.ts +0 -13
- package/dist/commands/cloud-run.js +0 -120
- package/templates/default/specs/ContentMatchers/TC-0005-text-and-values/mobile.test.ts +0 -17
- package/templates/default/specs/ContentMatchers/TC-0005-text-and-values/web.test.ts +0 -17
- /package/dist/{commands/__tests__/cloud-run.test.d.ts → linter/__tests__/anonymous-export.test.d.ts} +0 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# TestSpectra React Component Testing Template
|
|
2
|
+
|
|
3
|
+
A high-performance, real-browser React component testing template powered by **TestSpectra**, **WebdriverIO Browser Runner**, and **Testing Library**.
|
|
4
|
+
|
|
5
|
+
## 🚀 Features
|
|
6
|
+
|
|
7
|
+
- **Direct Component Mounting**: Mount TSX components directly in real Chromium/Blink engines using `@testing-library/react`.
|
|
8
|
+
- **Zero Mock Browser**: Real layout calculations, CSS rendering, focus states, and browser events without JSDOM/HappyDOM limitations.
|
|
9
|
+
- **Fast Vite HMR Core**: Instant test startup powered by Vite bundler inside the browser runner.
|
|
10
|
+
- **TestSpectra Matchers**: Comprehensive semantic assertions (`.shouldBeVisible()`, `.shouldExist()`, `expect(el).toHaveText()`).
|
|
11
|
+
|
|
12
|
+
## 📁 Directory Structure
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
.
|
|
16
|
+
├── spectra.config.ts # TestSpectra centralized configuration
|
|
17
|
+
├── wdio.conf.ts # WebdriverIO Browser Runner + Vite config
|
|
18
|
+
├── tsconfig.json # TypeScript configuration for JSX & runner types
|
|
19
|
+
└── src/
|
|
20
|
+
├── components/ # React components and tests
|
|
21
|
+
│ ├── Button/
|
|
22
|
+
│ │ ├── Button.tsx
|
|
23
|
+
│ │ └── Button.test.tsx
|
|
24
|
+
│ ├── Badge/
|
|
25
|
+
│ │ ├── Badge.tsx
|
|
26
|
+
│ │ └── Badge.test.tsx
|
|
27
|
+
│ └── Input/
|
|
28
|
+
│ ├── Input.tsx
|
|
29
|
+
│ └── Input.test.tsx
|
|
30
|
+
└── test-utils.tsx # Common testing helpers & providers
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 🛠️ Usage & Commands
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Run all component tests
|
|
37
|
+
pnpm test
|
|
38
|
+
|
|
39
|
+
# Run component tests in headless mode
|
|
40
|
+
pnpm run test:headless
|
|
41
|
+
|
|
42
|
+
# Run tests in high-concurrency chunked worker mode
|
|
43
|
+
pnpm run test:chunked
|
|
44
|
+
|
|
45
|
+
# Type check
|
|
46
|
+
pnpm run type-check
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 📝 Writing Component Tests
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import React from 'react';
|
|
53
|
+
import { render } from '@testing-library/react';
|
|
54
|
+
import { expect, $ } from '@wdio/globals';
|
|
55
|
+
import { Button } from './Button';
|
|
56
|
+
|
|
57
|
+
describe('Button Component', () => {
|
|
58
|
+
it('renders label and handles user clicks', async () => {
|
|
59
|
+
let clicked = false;
|
|
60
|
+
render(<Button label="Submit" onClick={() => (clicked = true)} />);
|
|
61
|
+
|
|
62
|
+
const button = await $('button=Submit');
|
|
63
|
+
await expect(button).toBeDisplayed();
|
|
64
|
+
|
|
65
|
+
await button.click();
|
|
66
|
+
expect(clicked).toBe(true);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@testspectra/template-react-component",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "spectra test",
|
|
8
|
+
"test:headed": "spectra test --headed",
|
|
9
|
+
"spectra": "spectra",
|
|
10
|
+
"doctor": "spectra doctor",
|
|
11
|
+
"watch": "spectra watch",
|
|
12
|
+
"type-check": "tsc -b",
|
|
13
|
+
"sync-types": "spectra sync-types",
|
|
14
|
+
"postinstall": "spectra sync-types"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@testspectra/cli": "link:../..",
|
|
18
|
+
"@testspectra/matchers": "link:../../../tools/matchers",
|
|
19
|
+
"@testspectra/react": "link:../../../tools/react",
|
|
20
|
+
"@types/node": "^20.14.0",
|
|
21
|
+
"@types/react": "^18.3.3",
|
|
22
|
+
"@types/react-dom": "^18.3.0",
|
|
23
|
+
"react": "^18.3.1",
|
|
24
|
+
"react-dom": "^18.3.1",
|
|
25
|
+
"typescript": "^5.4.5"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class BadgeComponent {
|
|
2
|
+
/** Root badge element */
|
|
3
|
+
get root() {
|
|
4
|
+
return Spectra.get("[data-testid='testspectra-badge']");
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/** Dot indicator element */
|
|
8
|
+
get dot() {
|
|
9
|
+
return Spectra.get("[data-testid='badge-dot']");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Badge label text element */
|
|
13
|
+
get label() {
|
|
14
|
+
return Spectra.get("[data-testid='badge-label']");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Lookup badge by severity attribute */
|
|
18
|
+
bySeverity(severity: 'info' | 'success' | 'warning' | 'danger') {
|
|
19
|
+
return Spectra.get(`[data-testid='testspectra-badge'][data-severity='${severity}']`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default new BadgeComponent();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class ButtonComponent {
|
|
2
|
+
/** Root button element */
|
|
3
|
+
get root() {
|
|
4
|
+
return Spectra.get("[data-testid='testspectra-button']");
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/** Label element inside button */
|
|
8
|
+
get label() {
|
|
9
|
+
return Spectra.get("[data-testid='button-label']");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Optional icon element */
|
|
13
|
+
get icon() {
|
|
14
|
+
return Spectra.get("[data-testid='button-icon']");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Lookup button element by visible text */
|
|
18
|
+
byText(text: string) {
|
|
19
|
+
return Spectra.get(`button*=${text}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default new ButtonComponent();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class InputComponent {
|
|
2
|
+
/** Root input element */
|
|
3
|
+
get root() {
|
|
4
|
+
return Spectra.get("[data-testid='testspectra-input']");
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/** Lookup input element by placeholder substring */
|
|
8
|
+
byPlaceholder(placeholder: string) {
|
|
9
|
+
return Spectra.get(`input[placeholder*='${placeholder}']`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default new InputComponent();
|
package/templates/react-component/specs/BadgeComponent/TC-0002-badge-severities-and-dot/spec.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: TC-0002
|
|
3
|
+
title: Verify default badge with info severity
|
|
4
|
+
priority: Critical
|
|
5
|
+
caseType: Positive
|
|
6
|
+
status: automated
|
|
7
|
+
coverage:
|
|
8
|
+
web: automated
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# TC-0002: Badge Default Rendering
|
|
12
|
+
|
|
13
|
+
Verify that `<Badge />` renders with the default `info` severity when no `severity` prop is provided.
|
|
14
|
+
|
|
15
|
+
## Test Steps
|
|
16
|
+
|
|
17
|
+
1. Mount `<Badge label="System Active" />`.
|
|
18
|
+
2. Verify the badge is visible, shows the correct label text, and has `data-severity="info"`.
|
package/templates/react-component/specs/BadgeComponent/TC-0002-badge-severities-and-dot/web.test.tsx
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Badge } from '../../../src/components/Badge/Badge.js';
|
|
2
|
+
import { withProviders } from '../../../src/test-utils.js';
|
|
3
|
+
|
|
4
|
+
it('Verify default badge with info severity', async () => {
|
|
5
|
+
await Spectra.mount(withProviders(<Badge label="System Active" />));
|
|
6
|
+
|
|
7
|
+
// Assert via BadgeComponent component object
|
|
8
|
+
await BadgeComponent.root.shouldBeVisible();
|
|
9
|
+
await BadgeComponent.label.shouldHaveText('System Active');
|
|
10
|
+
await BadgeComponent.root.shouldHaveAttribute('data-severity', 'info');
|
|
11
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: TC-0006
|
|
3
|
+
title: Verify badge with success severity and dot indicator
|
|
4
|
+
priority: High
|
|
5
|
+
caseType: Positive
|
|
6
|
+
status: automated
|
|
7
|
+
coverage:
|
|
8
|
+
web: automated
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# TC-0006: Badge Success Severity with Dot Indicator
|
|
12
|
+
|
|
13
|
+
Verify that `<Badge />` renders the `success` severity styling and shows a dot indicator when the `dot` prop is set.
|
|
14
|
+
|
|
15
|
+
## Test Steps
|
|
16
|
+
|
|
17
|
+
1. Mount `<Badge label="Completed" severity="success" dot />`.
|
|
18
|
+
2. Verify the badge is visible with `data-severity="success"` and the dot indicator is visible.
|
package/templates/react-component/specs/BadgeComponent/TC-0006-badge-success-with-dot/web.test.tsx
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Badge } from '../../../src/components/Badge/Badge.js';
|
|
2
|
+
import { withProviders } from '../../../src/test-utils.js';
|
|
3
|
+
|
|
4
|
+
it('Verify badge with success severity and dot indicator', async () => {
|
|
5
|
+
await Spectra.mount(withProviders(<Badge label="Completed" severity="success" dot />));
|
|
6
|
+
|
|
7
|
+
await BadgeComponent.root.shouldBeVisible();
|
|
8
|
+
await BadgeComponent.root.shouldHaveAttribute('data-severity', 'success');
|
|
9
|
+
await BadgeComponent.dot.shouldBeVisible();
|
|
10
|
+
});
|
package/templates/react-component/specs/BadgeComponent/TC-0007-badge-by-severity-lookup/spec.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: TC-0007
|
|
3
|
+
title: Verify dynamic lookup using bySeverity helper
|
|
4
|
+
priority: Medium
|
|
5
|
+
caseType: Positive
|
|
6
|
+
status: automated
|
|
7
|
+
coverage:
|
|
8
|
+
web: automated
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# TC-0007: Badge Lookup by Severity Helper
|
|
12
|
+
|
|
13
|
+
Verify that multiple `<Badge />` instances rendered together can be located individually via `BadgeComponent.bySeverity(...)`.
|
|
14
|
+
|
|
15
|
+
## Test Steps
|
|
16
|
+
|
|
17
|
+
1. Mount two badges: `<Badge label="Warning Alert" severity="warning" />` and `<Badge label="Critical Error" severity="danger" />`.
|
|
18
|
+
2. Verify each badge can be located and is visible via `BadgeComponent.bySeverity('warning')` and `BadgeComponent.bySeverity('danger')`.
|
package/templates/react-component/specs/BadgeComponent/TC-0007-badge-by-severity-lookup/web.test.tsx
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Badge } from '../../../src/components/Badge/Badge.js';
|
|
2
|
+
import { withProviders } from '../../../src/test-utils.js';
|
|
3
|
+
|
|
4
|
+
it('Verify dynamic lookup using bySeverity helper', async () => {
|
|
5
|
+
await Spectra.mount(
|
|
6
|
+
withProviders(
|
|
7
|
+
<div>
|
|
8
|
+
<Badge label="Warning Alert" severity="warning" />
|
|
9
|
+
<Badge label="Critical Error" severity="danger" />
|
|
10
|
+
</div>,
|
|
11
|
+
),
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
await BadgeComponent.bySeverity('warning').shouldBeVisible();
|
|
15
|
+
await BadgeComponent.bySeverity('danger').shouldBeVisible();
|
|
16
|
+
});
|
package/templates/react-component/specs/ButtonComponent/TC-0001-button-rendering-and-click/spec.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: TC-0001
|
|
3
|
+
title: Verify button render, text, and click with Spectra DSL
|
|
4
|
+
priority: Critical
|
|
5
|
+
caseType: Positive
|
|
6
|
+
status: automated
|
|
7
|
+
coverage:
|
|
8
|
+
web: automated
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# TC-0001: Button Rendering and Click Interaction
|
|
12
|
+
|
|
13
|
+
Verify that the `<Button />` component renders with the requested label and variant, and fires its `onClick` callback when clicked.
|
|
14
|
+
|
|
15
|
+
## Test Steps
|
|
16
|
+
|
|
17
|
+
1. Mount `<Button label="Save Changes" variant="primary" />`.
|
|
18
|
+
2. Verify the button is visible with the correct label and `data-variant` attribute.
|
|
19
|
+
3. Click the button and verify the `onClick` callback fires.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Button } from '../../../src/components/Button/Button.js';
|
|
2
|
+
import { withProviders } from '../../../src/test-utils.js';
|
|
3
|
+
|
|
4
|
+
it('Verify button render, text, and click with Spectra DSL', async () => {
|
|
5
|
+
let isClicked = false;
|
|
6
|
+
|
|
7
|
+
// Spectra.mount() renders into the shared root — no explicit cleanup between mounts needed.
|
|
8
|
+
await Spectra.mount(
|
|
9
|
+
withProviders(
|
|
10
|
+
<Button
|
|
11
|
+
label="Save Changes"
|
|
12
|
+
variant="primary"
|
|
13
|
+
onClick={() => {
|
|
14
|
+
isClicked = true;
|
|
15
|
+
}}
|
|
16
|
+
/>,
|
|
17
|
+
),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
// TestSpectra Ambient Component Object (ButtonComponent)
|
|
21
|
+
await ButtonComponent.root.shouldBeVisible();
|
|
22
|
+
await ButtonComponent.root.shouldHaveText('Save Changes');
|
|
23
|
+
await ButtonComponent.root.shouldHaveAttribute('data-variant', 'primary');
|
|
24
|
+
await ButtonComponent.root.click();
|
|
25
|
+
|
|
26
|
+
// Verify callback state
|
|
27
|
+
expect(isClicked).toBe(true);
|
|
28
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: TC-0004
|
|
3
|
+
title: Verify disabled button cannot be clicked
|
|
4
|
+
priority: High
|
|
5
|
+
caseType: Negative
|
|
6
|
+
status: automated
|
|
7
|
+
coverage:
|
|
8
|
+
web: automated
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# TC-0004: Disabled Button Interaction
|
|
12
|
+
|
|
13
|
+
Verify that a disabled `<Button />` renders in a disabled state and its `onClick` callback does not fire when clicked.
|
|
14
|
+
|
|
15
|
+
## Test Steps
|
|
16
|
+
|
|
17
|
+
1. Mount `<Button label="Disabled Action" disabled />`.
|
|
18
|
+
2. Verify the button is visible and disabled.
|
|
19
|
+
3. Attempt to click the button and verify the `onClick` callback does not fire.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Button } from '../../../src/components/Button/Button.js';
|
|
2
|
+
|
|
3
|
+
it('Verify disabled button cannot be clicked', async () => {
|
|
4
|
+
let isClicked = false;
|
|
5
|
+
|
|
6
|
+
await Spectra.mount(
|
|
7
|
+
<Button
|
|
8
|
+
label="Disabled Action"
|
|
9
|
+
disabled
|
|
10
|
+
onClick={() => {
|
|
11
|
+
isClicked = true;
|
|
12
|
+
}}
|
|
13
|
+
/>,
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
await ButtonComponent.root.shouldBeVisible();
|
|
17
|
+
await ButtonComponent.root.shouldBeDisabled();
|
|
18
|
+
|
|
19
|
+
// Attempt click - should not fire callback
|
|
20
|
+
await ButtonComponent.root.click().catch(() => {});
|
|
21
|
+
expect(isClicked).toBe(false);
|
|
22
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: TC-0005
|
|
3
|
+
title: Verify button renders optional icon
|
|
4
|
+
priority: Medium
|
|
5
|
+
caseType: Positive
|
|
6
|
+
status: automated
|
|
7
|
+
coverage:
|
|
8
|
+
web: automated
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# TC-0005: Button Optional Icon Rendering
|
|
12
|
+
|
|
13
|
+
Verify that `<Button />` renders an optional leading icon when the `icon` prop is provided.
|
|
14
|
+
|
|
15
|
+
## Test Steps
|
|
16
|
+
|
|
17
|
+
1. Mount `<Button label="Download Report" icon={...} />` with an icon element.
|
|
18
|
+
2. Verify the icon is visible and renders the expected content.
|
package/templates/react-component/specs/ButtonComponent/TC-0005-button-renders-icon/web.test.tsx
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Button } from '../../../src/components/Button/Button.js';
|
|
2
|
+
|
|
3
|
+
it('Verify button renders optional icon', async () => {
|
|
4
|
+
await Spectra.mount(<Button label="Download Report" icon={<span data-testid="button-icon">📥</span>} />);
|
|
5
|
+
|
|
6
|
+
await ButtonComponent.icon.shouldBeVisible();
|
|
7
|
+
await ButtonComponent.icon.shouldHaveText('📥');
|
|
8
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: button-component-suite
|
|
3
|
+
name: Button Component Suite
|
|
4
|
+
executionOrder: 1
|
|
5
|
+
tags:
|
|
6
|
+
- component
|
|
7
|
+
- button
|
|
8
|
+
- atoms
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Button Component Testing Suite
|
|
12
|
+
Verification of isolated button props, event listeners, accessibility, and visual variants.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: TC-0003
|
|
3
|
+
title: Verify input placeholder and typing interaction
|
|
4
|
+
priority: Critical
|
|
5
|
+
caseType: Positive
|
|
6
|
+
status: automated
|
|
7
|
+
coverage:
|
|
8
|
+
web: automated
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# TC-0003: Input Typing and Placeholder
|
|
12
|
+
|
|
13
|
+
Verify that `<Input />` renders its placeholder, accepts typed text, and fires `onChange` with the typed value.
|
|
14
|
+
|
|
15
|
+
## Test Steps
|
|
16
|
+
|
|
17
|
+
1. Mount `<Input placeholder="Enter email address" />` with an `onChange` handler.
|
|
18
|
+
2. Verify the input is visible and the placeholder is discoverable.
|
|
19
|
+
3. Type `test@example.com` into the input and verify the value updates.
|
|
20
|
+
4. Verify the `onChange` handler received the typed value.
|
package/templates/react-component/specs/InputComponent/TC-0003-input-typing-and-clear/web.test.tsx
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Input } from '../../../src/components/Input/Input.js';
|
|
2
|
+
import { withProviders } from '../../../src/test-utils.js';
|
|
3
|
+
|
|
4
|
+
it('Verify input placeholder and typing interaction', async () => {
|
|
5
|
+
let currentVal = '';
|
|
6
|
+
|
|
7
|
+
await Spectra.mount(
|
|
8
|
+
withProviders(
|
|
9
|
+
<Input
|
|
10
|
+
placeholder="Enter email address"
|
|
11
|
+
onChange={(e) => {
|
|
12
|
+
currentVal = e.target.value;
|
|
13
|
+
}}
|
|
14
|
+
/>,
|
|
15
|
+
),
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
// 1. Assert element is visible via InputComponent
|
|
19
|
+
await InputComponent.root.shouldBeVisible();
|
|
20
|
+
await InputComponent.byPlaceholder('email address').shouldBeVisible();
|
|
21
|
+
|
|
22
|
+
// 2. Type text using Spectra DSL
|
|
23
|
+
await InputComponent.root.type('test@example.com');
|
|
24
|
+
await InputComponent.root.shouldHaveValue('test@example.com');
|
|
25
|
+
|
|
26
|
+
// 3. Verify onChange state
|
|
27
|
+
expect(currentVal).toBe('test@example.com');
|
|
28
|
+
});
|
package/templates/react-component/specs/InputComponent/TC-0008-disabled-input-not-editable/spec.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: TC-0008
|
|
3
|
+
title: Verify disabled input cannot be typed into
|
|
4
|
+
priority: High
|
|
5
|
+
caseType: Negative
|
|
6
|
+
status: automated
|
|
7
|
+
coverage:
|
|
8
|
+
web: automated
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# TC-0008: Disabled Input State
|
|
12
|
+
|
|
13
|
+
Verify that a disabled `<Input />` renders in a disabled state.
|
|
14
|
+
|
|
15
|
+
## Test Steps
|
|
16
|
+
|
|
17
|
+
1. Mount `<Input disabled placeholder="Disabled field" />`.
|
|
18
|
+
2. Verify the input is visible and disabled.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Input } from '../../../src/components/Input/Input.js';
|
|
2
|
+
import { withProviders } from '../../../src/test-utils.js';
|
|
3
|
+
|
|
4
|
+
it('Verify disabled input cannot be typed into', async () => {
|
|
5
|
+
await Spectra.mount(withProviders(<Input disabled placeholder="Disabled field" />));
|
|
6
|
+
|
|
7
|
+
await InputComponent.root.shouldBeVisible();
|
|
8
|
+
await InputComponent.root.shouldBeDisabled();
|
|
9
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: input-component-suite
|
|
3
|
+
name: Input Component Suite
|
|
4
|
+
executionOrder: 3
|
|
5
|
+
tags:
|
|
6
|
+
- component
|
|
7
|
+
- input
|
|
8
|
+
- forms
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Input Component Testing Suite
|
|
12
|
+
Verification of text inputs, placeholder labels, keyboard typing, and onChange events.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { defineConfig } from "@testspectra/cli";
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
webConfig: {
|
|
5
|
+
baseUrl: "http://localhost:5173",
|
|
6
|
+
maxConcurrentSessions: "4",
|
|
7
|
+
headless: true,
|
|
8
|
+
implicitWait: "5000",
|
|
9
|
+
pageLoadTimeout: "30000",
|
|
10
|
+
scriptTimeout: "30000",
|
|
11
|
+
parallelizationMode: "testcase",
|
|
12
|
+
},
|
|
13
|
+
browsers: [
|
|
14
|
+
{
|
|
15
|
+
id: "chrome-desktop",
|
|
16
|
+
type: "chrome",
|
|
17
|
+
mobileEmulation: false,
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
executionConfig: {
|
|
21
|
+
networkMonitoringEnabled: true,
|
|
22
|
+
fastResponseTime: "200",
|
|
23
|
+
normalResponseTime: "1000",
|
|
24
|
+
monitoredDomains: [],
|
|
25
|
+
environmentVariables: [],
|
|
26
|
+
},
|
|
27
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export interface BadgeProps {
|
|
4
|
+
label: string;
|
|
5
|
+
severity?: 'info' | 'success' | 'warning' | 'danger';
|
|
6
|
+
dot?: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const Badge: React.FC<BadgeProps> = ({
|
|
10
|
+
label,
|
|
11
|
+
severity = 'info',
|
|
12
|
+
dot = false,
|
|
13
|
+
}) => {
|
|
14
|
+
const getColors = () => {
|
|
15
|
+
switch (severity) {
|
|
16
|
+
case 'success':
|
|
17
|
+
return { bg: '#dcfce7', text: '#15803d' };
|
|
18
|
+
case 'warning':
|
|
19
|
+
return { bg: '#fef9c3', text: '#a16207' };
|
|
20
|
+
case 'danger':
|
|
21
|
+
return { bg: '#fee2e2', text: '#b91c1c' };
|
|
22
|
+
case 'info':
|
|
23
|
+
default:
|
|
24
|
+
return { bg: '#e0f2fe', text: '#0369a1' };
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const { bg, text } = getColors();
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<span
|
|
32
|
+
data-testid="testspectra-badge"
|
|
33
|
+
data-severity={severity}
|
|
34
|
+
style={{
|
|
35
|
+
display: 'inline-flex',
|
|
36
|
+
alignItems: 'center',
|
|
37
|
+
gap: '6px',
|
|
38
|
+
padding: '2px 8px',
|
|
39
|
+
borderRadius: '9999px',
|
|
40
|
+
backgroundColor: bg,
|
|
41
|
+
color: text,
|
|
42
|
+
fontSize: '12px',
|
|
43
|
+
fontWeight: 600,
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
{dot && (
|
|
47
|
+
<span
|
|
48
|
+
data-testid="badge-dot"
|
|
49
|
+
style={{
|
|
50
|
+
width: '6px',
|
|
51
|
+
height: '6px',
|
|
52
|
+
borderRadius: '50%',
|
|
53
|
+
backgroundColor: text,
|
|
54
|
+
}}
|
|
55
|
+
/>
|
|
56
|
+
)}
|
|
57
|
+
<span data-testid="badge-label">{label}</span>
|
|
58
|
+
</span>
|
|
59
|
+
);
|
|
60
|
+
};
|