@testspectra/cli 1.1.7 → 1.1.8-rc.10
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/README.md +47 -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 +254 -13
- package/dist/commands/__tests__/run.test.js +92 -16
- package/dist/commands/add.js +2 -1
- package/dist/commands/demo.js +17 -7
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.js +8 -2
- 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 +39 -1
- package/dist/generator/tsconfig-generator.js +44 -16
- package/dist/generator/type-generator.d.ts +29 -3
- package/dist/generator/type-generator.js +115 -22
- package/dist/index.d.ts +1 -1
- package/dist/index.js +65 -29
- 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 +85 -24
- 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 +13 -4
- package/templates/default/CLAUDE.md +5 -0
- 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 +26 -2
- package/templates/default/page-objects/MatchersPage/web.ts +8 -2
- package/templates/default/page-objects/NavigationPage/mobile.ts +1 -1
- package/templates/default/page-objects/NavigationPage/web.ts +1 -1
- package/templates/default/page-objects/PlaygroundPage/mobile.ts +12 -6
- package/templates/default/page-objects/PlaygroundPage/web.ts +2 -2
- package/templates/default/specs/ApiInterception/TC-0008-fetch-mocking/mobile.test.ts +45 -3
- package/templates/default/specs/ApiInterception/TC-0008-fetch-mocking/spec.md +7 -0
- package/templates/default/specs/ApiInterception/TC-0008-fetch-mocking/web.test.ts +8 -4
- 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 +13 -2
- package/templates/default/specs/ApiInterception/TC-0009-post-mocking/spec.md +7 -0
- package/templates/default/specs/ApiInterception/TC-0009-post-mocking/web.test.ts +6 -4
- 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 +1 -0
- 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 +1 -1
- package/templates/default/specs/BrowserContext/TC-0007-title-and-navigation/spec.md +5 -0
- package/templates/default/specs/BrowserContext/TC-0007-title-and-navigation/web.test.ts +1 -1
- 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 +7 -0
- package/templates/default/specs/ContentMatchers/TC-0006-collections-and-empty/mobile.test.ts +1 -1
- package/templates/default/specs/ContentMatchers/TC-0006-collections-and-empty/spec.md +5 -0
- package/templates/default/specs/ContentMatchers/TC-0006-collections-and-empty/web.test.ts +1 -1
- 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 +1 -1
- package/templates/default/specs/ElementMatchers/TC-0003-visibility-and-dom/spec.md +5 -0
- package/templates/default/specs/ElementMatchers/TC-0003-visibility-and-dom/web.test.ts +1 -1
- package/templates/default/specs/ElementMatchers/TC-0004-states-and-attributes/mobile.test.ts +1 -1
- package/templates/default/specs/ElementMatchers/TC-0004-states-and-attributes/spec.md +7 -0
- package/templates/default/specs/ElementMatchers/TC-0004-states-and-attributes/web.test.ts +1 -1
- package/templates/default/specs/ElementMatchers/suite.md +2 -1
- 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 +1 -1
- package/templates/default/specs/Playground/TC-0001-form-controls/spec.md +6 -0
- package/templates/default/specs/Playground/TC-0001-form-controls/web.test.ts +1 -1
- package/templates/default/specs/Playground/TC-0002-toggle-elements/mobile.test.ts +1 -1
- package/templates/default/specs/Playground/TC-0002-toggle-elements/spec.md +6 -0
- package/templates/default/specs/Playground/TC-0002-toggle-elements/web.test.ts +1 -1
- package/templates/default/spectra.config.ts +1 -17
- package/templates/default/support/actions/fillCredentials/mobile.action.ts +3 -3
- package/templates/default/support/actions/fillCredentials/web.action.ts +1 -1
- 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 +1 -1
- package/templates/default/support/steps/togglePlaygroundStates/web.step.ts +1 -1
- package/templates/default/support/steps/verifyPlaygroundState/mobile.step.ts +1 -1
- package/templates/default/support/steps/verifyPlaygroundState/web.step.ts +1 -1
- package/templates/nx/.nx/workspace-data/70094CFD-E89B-57A1-9619-2FC5F4963C54.db +0 -0
- package/templates/nx/.nx/workspace-data/70094CFD-E89B-57A1-9619-2FC5F4963C54.db-shm +0 -0
- package/templates/nx/.nx/workspace-data/70094CFD-E89B-57A1-9619-2FC5F4963C54.db-wal +0 -0
- package/templates/nx/.nx/workspace-data/d/daemon.log +5803 -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 +14388 -0
- package/templates/nx/package.json +3 -3
- package/templates/nx/packages/matchers/e2e/project.json +2 -2
- package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0008-fetch-mocking/mobile.test.ts +25 -1
- package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0008-fetch-mocking/web.test.ts +2 -2
- package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0009-post-mocking/mobile.test.ts +22 -1
- package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0009-post-mocking/web.test.ts +2 -2
- package/templates/nx/packages/matchers/e2e/specs/BrowserContext/TC-0007-title-and-navigation/mobile.test.ts +1 -1
- package/templates/nx/packages/matchers/e2e/specs/BrowserContext/TC-0007-title-and-navigation/web.test.ts +1 -1
- package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0005-text-and-values/mobile.test.ts +1 -1
- package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0005-text-and-values/web.test.ts +1 -1
- package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0006-collections-and-empty/mobile.test.ts +1 -1
- package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0006-collections-and-empty/web.test.ts +1 -1
- package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0003-visibility-and-dom/mobile.test.ts +1 -1
- package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0003-visibility-and-dom/web.test.ts +1 -1
- package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0004-states-and-attributes/mobile.test.ts +1 -1
- package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0004-states-and-attributes/web.test.ts +1 -1
- 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/project.json +2 -2
- package/templates/nx/packages/playground/e2e/specs/Playground/TC-0001-form-controls/mobile.test.ts +1 -1
- package/templates/nx/packages/playground/e2e/specs/Playground/TC-0001-form-controls/web.test.ts +1 -1
- package/templates/nx/packages/playground/e2e/specs/Playground/TC-0002-toggle-elements/mobile.test.ts +1 -1
- package/templates/nx/packages/playground/e2e/specs/Playground/TC-0002-toggle-elements/web.test.ts +1 -1
- package/templates/nx/shared/testing/page-objects/MatchersPage/mobile.ts +1 -1
- package/templates/nx/shared/testing/page-objects/MatchersPage/web.ts +83 -29
- package/templates/nx/shared/testing/page-objects/NavigationPage/mobile.ts +1 -1
- package/templates/nx/shared/testing/page-objects/NavigationPage/web.ts +1 -1
- package/templates/nx/shared/testing/page-objects/PlaygroundPage/mobile.ts +1 -1
- package/templates/nx/shared/testing/page-objects/PlaygroundPage/web.ts +2 -2
- package/templates/nx/shared/testing/project.json +1 -2
- package/templates/nx/shared/testing/support/actions/fillCredentials/mobile.action.ts +1 -1
- package/templates/nx/shared/testing/support/actions/fillCredentials/web.action.ts +1 -1
- package/templates/nx/shared/testing/support/steps/togglePlaygroundStates/mobile.step.ts +1 -1
- package/templates/nx/shared/testing/support/steps/togglePlaygroundStates/web.step.ts +1 -1
- package/templates/nx/shared/testing/support/steps/verifyPlaygroundState/mobile.step.ts +1 -1
- package/templates/nx/shared/testing/support/steps/verifyPlaygroundState/web.step.ts +1 -1
- package/templates/nx/spectra.config.ts +1 -17
- 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.hash +0 -1
- 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,104 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import * as p from '@clack/prompts';
|
|
4
|
+
import { renderSummaryView } from '../reporter/summary-view.js';
|
|
5
|
+
import { Reporter } from '../runner/reporter.js';
|
|
6
|
+
import { runSystemChecks } from './doctor.js';
|
|
7
|
+
/**
|
|
8
|
+
* Finds the Chrome-for-Testing binary that `spectra doctor` already installs/manages for the
|
|
9
|
+
* E2E CDP driver (`core/driver-cdp`) — same install, same binary. `@testspectra/react` must not
|
|
10
|
+
* contain any browser-discovery logic of its own (see the package-level comment in
|
|
11
|
+
* tools/react/vitest.config.ts): this is the one place that resolves the path, passed down to
|
|
12
|
+
* the bundled Vitest/Playwright runner as a plain argument (env var), so component testing never
|
|
13
|
+
* requires a separate `playwright install` download alongside TestSpectra's own browser.
|
|
14
|
+
*/
|
|
15
|
+
async function resolveBrowserExecutable(cwd) {
|
|
16
|
+
try {
|
|
17
|
+
const { dependencies } = await runSystemChecks(cwd);
|
|
18
|
+
const chrome = dependencies.find((d) => d.category === 'web' && (d.name.includes('Chrome') || d.name.includes('Chromium')));
|
|
19
|
+
return chrome?.installed && chrome.location ? chrome.location : null;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* `spectra test` — delegates to `@testspectra/react`'s bundled Vitest browser-mode runner for
|
|
27
|
+
* component testing. Deliberately separate from `spectra run` (E2E via core/orchestrator): see
|
|
28
|
+
* docs/v2/features/component-testing/react/README.md §2 for why these are two independent
|
|
29
|
+
* runners rather than one extended pipeline.
|
|
30
|
+
*/
|
|
31
|
+
export async function testCommand(options = {}) {
|
|
32
|
+
const cwd = options.cwd ?? process.cwd();
|
|
33
|
+
let reactPkg;
|
|
34
|
+
try {
|
|
35
|
+
reactPkg = await import('@testspectra/react');
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
p.log.error(chalk.red('✖ @testspectra/react is not installed in this workspace.'));
|
|
39
|
+
p.log.info(chalk.dim('Component testing requires the @testspectra/react package.'));
|
|
40
|
+
p.log.info(chalk.dim(' 👉 Install it: pnpm add -D @testspectra/react'));
|
|
41
|
+
process.exit(1);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const browserExecutablePath = await resolveBrowserExecutable(cwd);
|
|
45
|
+
if (!browserExecutablePath) {
|
|
46
|
+
p.log.error(chalk.red('✖ TestSpectra-managed Chrome for Testing was not found.'));
|
|
47
|
+
p.log.info(chalk.dim('Component testing reuses the same browser install as `spectra run` (web).'));
|
|
48
|
+
p.log.info(chalk.dim(' 👉 Install it: spectra doctor --fix'));
|
|
49
|
+
process.exit(1);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
let stepDelayMs;
|
|
53
|
+
const rawDelay = options.stepDelay ?? options.delay;
|
|
54
|
+
if (rawDelay !== undefined) {
|
|
55
|
+
const delayNum = parseInt(String(rawDelay), 10);
|
|
56
|
+
if (!isNaN(delayNum) && delayNum >= 0) {
|
|
57
|
+
stepDelayMs = delayNum;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
let headless = true;
|
|
61
|
+
if (options.headed) {
|
|
62
|
+
headless = false;
|
|
63
|
+
}
|
|
64
|
+
else if (options.headless !== undefined) {
|
|
65
|
+
headless = options.headless;
|
|
66
|
+
}
|
|
67
|
+
const concurrency = options.concurrency !== undefined ? parseInt(String(options.concurrency), 10) : undefined;
|
|
68
|
+
const outputFile = options.output ? path.resolve(cwd, options.output) : undefined;
|
|
69
|
+
// Reuses the exact same semantic terminal reporter `spectra run` drives (see
|
|
70
|
+
// docs/v2/cli/matchers-semantic-reporter.md) — @testspectra/react emits the identical
|
|
71
|
+
// [TESTSPECTRA_*] protocol lines the E2E Rust orchestrator does (see tools/react/src/prelude.ts
|
|
72
|
+
// / setup.ts), so the same Reporter class parses them with zero changes on either side.
|
|
73
|
+
const reporter = new Reporter();
|
|
74
|
+
const runStartedAt = Date.now();
|
|
75
|
+
const ok = await reactPkg.runComponentTests({
|
|
76
|
+
cwd,
|
|
77
|
+
headless,
|
|
78
|
+
stepDelayMs,
|
|
79
|
+
spec: options.spec,
|
|
80
|
+
outputFile,
|
|
81
|
+
concurrency: concurrency !== undefined && !isNaN(concurrency) ? concurrency : undefined,
|
|
82
|
+
browserExecutablePath,
|
|
83
|
+
onLine: (line) => {
|
|
84
|
+
if (!line.startsWith('[TESTSPECTRA_'))
|
|
85
|
+
return;
|
|
86
|
+
reporter.addLog({ timestamp: new Date().toLocaleTimeString(), level: 'INFO', message: line });
|
|
87
|
+
if (!reporter.isInteractiveMode()) {
|
|
88
|
+
console.log(line);
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
const durationMs = Date.now() - runStartedAt;
|
|
93
|
+
const result = reporter.generateResult(ok ? 'passed' : 'failed', `${(durationMs / 1000).toFixed(1)}s`);
|
|
94
|
+
const totalTests = result.passedCount + result.failedCount;
|
|
95
|
+
renderSummaryView({
|
|
96
|
+
totalSuites: totalTests,
|
|
97
|
+
totalTests,
|
|
98
|
+
passedCount: result.passedCount,
|
|
99
|
+
failedCount: result.failedCount,
|
|
100
|
+
durationMs,
|
|
101
|
+
reportLocation: outputFile ? path.relative(cwd, outputFile) : '(use -o/--output to save a report)',
|
|
102
|
+
});
|
|
103
|
+
process.exit(ok ? 0 : 1);
|
|
104
|
+
}
|
package/dist/commands/watch.js
CHANGED
|
@@ -3,15 +3,22 @@ import path from 'path';
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import { TypeGenerator } from '../types/generator.js';
|
|
5
5
|
export function startWatcher(cwd, debounceMs = 60) {
|
|
6
|
-
// Initial generation
|
|
6
|
+
// Initial generation. TypeGenerator.generateAll itself stays synchronous (reading
|
|
7
|
+
// spectra.config.ts is unavoidably async, so that part is handled by the separate
|
|
8
|
+
// syncEnvDeclaration call below); startWatcher stays sync so it can return the watcher handle
|
|
9
|
+
// immediately, with the async env sync fired-and-forgotten.
|
|
7
10
|
TypeGenerator.generateAll(cwd);
|
|
11
|
+
TypeGenerator.syncEnvDeclaration(cwd).catch((err) => {
|
|
12
|
+
console.error(chalk.red(`✖ Error generating initial env.d.ts: ${err?.message}`));
|
|
13
|
+
});
|
|
8
14
|
let debounceTimer = null;
|
|
9
15
|
const triggerRegen = (filePath, eventType) => {
|
|
10
16
|
if (debounceTimer)
|
|
11
17
|
clearTimeout(debounceTimer);
|
|
12
|
-
debounceTimer = setTimeout(() => {
|
|
18
|
+
debounceTimer = setTimeout(async () => {
|
|
13
19
|
try {
|
|
14
20
|
TypeGenerator.generateAll(cwd);
|
|
21
|
+
await TypeGenerator.syncEnvDeclaration(cwd);
|
|
15
22
|
const time = new Date().toLocaleTimeString();
|
|
16
23
|
const rel = path.relative(cwd, filePath) || filePath;
|
|
17
24
|
console.log(chalk.gray(`[${time}] `) + chalk.cyan(`✨ Updated ambient types `) + chalk.gray(`(${eventType}: ${rel})`));
|
|
@@ -34,7 +41,6 @@ export function startWatcher(cwd, debounceMs = 60) {
|
|
|
34
41
|
}
|
|
35
42
|
if (fn.includes('fixtures') ||
|
|
36
43
|
fn.includes('page-objects') ||
|
|
37
|
-
fn.includes('pageobjects') ||
|
|
38
44
|
fn.includes('actions') ||
|
|
39
45
|
fn.includes('steps') ||
|
|
40
46
|
fn.includes('hooks') ||
|
package/dist/config/loader.js
CHANGED
package/dist/config/schema.d.ts
CHANGED
|
@@ -20,19 +20,11 @@ export interface WebConfig {
|
|
|
20
20
|
headless: boolean | 'new';
|
|
21
21
|
/**
|
|
22
22
|
* Implicit wait timeout (in milliseconds) for finding elements before throwing an error.
|
|
23
|
+
* Also the ceiling auto-waiting element assertions/actions poll against (capped at 2000ms for
|
|
24
|
+
* assertions — see `getAssertionTimeoutMs()`).
|
|
23
25
|
* @default "5000"
|
|
24
26
|
*/
|
|
25
27
|
implicitWait: string;
|
|
26
|
-
/**
|
|
27
|
-
* Maximum time (in milliseconds) allowed for a webpage to complete navigation and initial load.
|
|
28
|
-
* @default "30000"
|
|
29
|
-
*/
|
|
30
|
-
pageLoadTimeout: string;
|
|
31
|
-
/**
|
|
32
|
-
* Maximum time (in milliseconds) allowed for asynchronous scripts to finish executing.
|
|
33
|
-
* @default "30000"
|
|
34
|
-
*/
|
|
35
|
-
scriptTimeout: string;
|
|
36
28
|
/**
|
|
37
29
|
* Delay between consecutive actions and commands in milliseconds (slow motion).
|
|
38
30
|
* @default 0
|
|
@@ -46,37 +38,6 @@ export interface WebConfig {
|
|
|
46
38
|
*/
|
|
47
39
|
parallelizationMode: 'testcase' | 'suite';
|
|
48
40
|
}
|
|
49
|
-
/**
|
|
50
|
-
* Browser target definition for web test execution.
|
|
51
|
-
*/
|
|
52
|
-
export interface Browser {
|
|
53
|
-
/**
|
|
54
|
-
* Unique identifier for this browser configuration.
|
|
55
|
-
*/
|
|
56
|
-
id: string;
|
|
57
|
-
/**
|
|
58
|
-
* Browser type/engine: `"chrome"`, `"firefox"`, `"safari"`, `"edge"`.
|
|
59
|
-
* @default "chrome"
|
|
60
|
-
*/
|
|
61
|
-
type: string;
|
|
62
|
-
/**
|
|
63
|
-
* Whether to simulate mobile viewport and touch metrics.
|
|
64
|
-
* @default false
|
|
65
|
-
*/
|
|
66
|
-
mobileEmulation: boolean;
|
|
67
|
-
/**
|
|
68
|
-
* Emulated device name when `mobileEmulation` is true (e.g. `"iPhone 14"`, `"Pixel 7"`).
|
|
69
|
-
*/
|
|
70
|
-
deviceName?: string;
|
|
71
|
-
/**
|
|
72
|
-
* Custom browser window width in pixels.
|
|
73
|
-
*/
|
|
74
|
-
width?: string;
|
|
75
|
-
/**
|
|
76
|
-
* Custom browser window height in pixels.
|
|
77
|
-
*/
|
|
78
|
-
height?: string;
|
|
79
|
-
}
|
|
80
41
|
/**
|
|
81
42
|
* Target Android device specification for multi-device parallel execution.
|
|
82
43
|
*/
|
|
@@ -156,11 +117,6 @@ export interface AndroidConfig {
|
|
|
156
117
|
* Main activity name launched when starting the app.
|
|
157
118
|
*/
|
|
158
119
|
appActivity: string;
|
|
159
|
-
/**
|
|
160
|
-
* Whether to automatically grant Android runtime permissions upon installation.
|
|
161
|
-
* @default true
|
|
162
|
-
*/
|
|
163
|
-
autoGrantPermissions: boolean;
|
|
164
120
|
/**
|
|
165
121
|
* Whether to preserve app state and prevent clearing app data/cache between sessions.
|
|
166
122
|
* @default false
|
|
@@ -265,40 +221,6 @@ export interface IosConfig {
|
|
|
265
221
|
*/
|
|
266
222
|
parallelizationMode: 'testcase' | 'suite';
|
|
267
223
|
}
|
|
268
|
-
/**
|
|
269
|
-
* Load testing stage ramp-up profile.
|
|
270
|
-
*/
|
|
271
|
-
export interface LoadStage {
|
|
272
|
-
/**
|
|
273
|
-
* Stage identifier.
|
|
274
|
-
*/
|
|
275
|
-
id: string;
|
|
276
|
-
/**
|
|
277
|
-
* Duration for this load stage (e.g. `"30s"`, `"2m"`).
|
|
278
|
-
*/
|
|
279
|
-
duration: string;
|
|
280
|
-
/**
|
|
281
|
-
* Target virtual users (VUs) to scale to during this stage.
|
|
282
|
-
*/
|
|
283
|
-
targetVUs: string;
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Performance and pass/fail metric threshold definition.
|
|
287
|
-
*/
|
|
288
|
-
export interface SuccessThreshold {
|
|
289
|
-
/**
|
|
290
|
-
* Unique threshold identifier.
|
|
291
|
-
*/
|
|
292
|
-
id: string;
|
|
293
|
-
/**
|
|
294
|
-
* Performance metric type (e.g. `"http_req_duration"`, `"http_req_failed"`).
|
|
295
|
-
*/
|
|
296
|
-
metricType: string;
|
|
297
|
-
/**
|
|
298
|
-
* Maximum acceptable value (e.g. `"500ms"`, `"0.01"`).
|
|
299
|
-
*/
|
|
300
|
-
maxValue: string;
|
|
301
|
-
}
|
|
302
224
|
/**
|
|
303
225
|
* Specific domain filter for real-time network interception and recording.
|
|
304
226
|
*/
|
|
@@ -312,19 +234,6 @@ export interface MonitoredDomain {
|
|
|
312
234
|
*/
|
|
313
235
|
enabled: boolean;
|
|
314
236
|
}
|
|
315
|
-
/**
|
|
316
|
-
* Custom environment variable key-value pair injected into the test execution sandbox.
|
|
317
|
-
*/
|
|
318
|
-
export interface EnvironmentVariable {
|
|
319
|
-
/**
|
|
320
|
-
* Environment variable name (e.g. `"API_SECRET_KEY"`).
|
|
321
|
-
*/
|
|
322
|
-
key: string;
|
|
323
|
-
/**
|
|
324
|
-
* Environment variable value.
|
|
325
|
-
*/
|
|
326
|
-
value: string;
|
|
327
|
-
}
|
|
328
237
|
/**
|
|
329
238
|
* Test execution, CDP network monitoring, and sandbox environment configuration.
|
|
330
239
|
*/
|
|
@@ -349,9 +258,10 @@ export interface ExecutionConfig {
|
|
|
349
258
|
*/
|
|
350
259
|
monitoredDomains?: MonitoredDomain[];
|
|
351
260
|
/**
|
|
352
|
-
* Custom environment variables injected into the test process runtime
|
|
261
|
+
* Custom environment variables injected into the test process runtime
|
|
262
|
+
* (e.g. `{ API_SECRET_KEY: "..." }`).
|
|
353
263
|
*/
|
|
354
|
-
environmentVariables?:
|
|
264
|
+
environmentVariables?: Record<string, string>;
|
|
355
265
|
}
|
|
356
266
|
/**
|
|
357
267
|
* Root configuration data structure matching TestSpectra project schema.
|
|
@@ -361,10 +271,6 @@ export interface ConfigData {
|
|
|
361
271
|
* Web browser execution settings.
|
|
362
272
|
*/
|
|
363
273
|
webConfig: WebConfig;
|
|
364
|
-
/**
|
|
365
|
-
* List of target browsers for web automation runs.
|
|
366
|
-
*/
|
|
367
|
-
browsers: Browser[];
|
|
368
274
|
/**
|
|
369
275
|
* Android Appium driver and device options.
|
|
370
276
|
*/
|
|
@@ -373,21 +279,6 @@ export interface ConfigData {
|
|
|
373
279
|
* iOS Appium driver and device options.
|
|
374
280
|
*/
|
|
375
281
|
iosConfig: IosConfig;
|
|
376
|
-
/**
|
|
377
|
-
* Load testing parameters.
|
|
378
|
-
*/
|
|
379
|
-
loadConfig: {
|
|
380
|
-
virtualUsers: string;
|
|
381
|
-
duration: string;
|
|
382
|
-
};
|
|
383
|
-
/**
|
|
384
|
-
* Load testing stages.
|
|
385
|
-
*/
|
|
386
|
-
loadStages: LoadStage[];
|
|
387
|
-
/**
|
|
388
|
-
* Pass/fail metric thresholds.
|
|
389
|
-
*/
|
|
390
|
-
thresholds: SuccessThreshold[];
|
|
391
282
|
/**
|
|
392
283
|
* Advanced execution and network recording settings.
|
|
393
284
|
*/
|
package/dist/config/schema.js
CHANGED
|
@@ -25,22 +25,12 @@ export const DEFAULT_CONFIG_DATA = {
|
|
|
25
25
|
maxConcurrentSessions: '1',
|
|
26
26
|
headless: true,
|
|
27
27
|
implicitWait: '5000',
|
|
28
|
-
pageLoadTimeout: '30000',
|
|
29
|
-
scriptTimeout: '30000',
|
|
30
28
|
parallelizationMode: 'testcase',
|
|
31
29
|
},
|
|
32
|
-
browsers: [
|
|
33
|
-
{
|
|
34
|
-
id: 'chrome-desktop',
|
|
35
|
-
type: 'chrome',
|
|
36
|
-
mobileEmulation: false,
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
30
|
androidConfig: {
|
|
40
31
|
driverServer: 'http://127.0.0.1:4800',
|
|
41
32
|
appPackage: '',
|
|
42
33
|
appActivity: '',
|
|
43
|
-
autoGrantPermissions: true,
|
|
44
34
|
noReset: false,
|
|
45
35
|
implicitWait: 10000,
|
|
46
36
|
parallelizationMode: 'suite',
|
|
@@ -71,17 +61,11 @@ export const DEFAULT_CONFIG_DATA = {
|
|
|
71
61
|
},
|
|
72
62
|
],
|
|
73
63
|
},
|
|
74
|
-
loadConfig: {
|
|
75
|
-
virtualUsers: '10',
|
|
76
|
-
duration: '1m',
|
|
77
|
-
},
|
|
78
|
-
loadStages: [],
|
|
79
|
-
thresholds: [],
|
|
80
64
|
executionConfig: {
|
|
81
65
|
networkMonitoringEnabled: true,
|
|
82
66
|
fastResponseTime: '200',
|
|
83
67
|
normalResponseTime: '1000',
|
|
84
68
|
monitoredDomains: [],
|
|
85
|
-
environmentVariables:
|
|
69
|
+
environmentVariables: {},
|
|
86
70
|
},
|
|
87
71
|
};
|
|
@@ -261,7 +261,7 @@ describe('Platform TSConfigs & Type Isolation (docs/v2/cli/tsconfig-platform-iso
|
|
|
261
261
|
expect(threw).toBe(true);
|
|
262
262
|
expect(errorMessage).toContain("Cannot find name 'AuthLoginPage'");
|
|
263
263
|
});
|
|
264
|
-
it('E2E: compiles the full Nx monorepo template via tsc -b with 0 errors', () => {
|
|
264
|
+
it('E2E: compiles the full Nx monorepo template via tsc -b with 0 errors', async () => {
|
|
265
265
|
let root = process.cwd();
|
|
266
266
|
while (root && root !== path.dirname(root)) {
|
|
267
267
|
if (fs.existsSync(path.join(root, 'pnpm-workspace.yaml')))
|
|
@@ -269,8 +269,12 @@ describe('Platform TSConfigs & Type Isolation (docs/v2/cli/tsconfig-platform-iso
|
|
|
269
269
|
root = path.dirname(root);
|
|
270
270
|
}
|
|
271
271
|
const nxTemplateDir = path.join(root, 'cli', 'templates', 'nx');
|
|
272
|
-
// Generate latest ambient types for the nx template
|
|
272
|
+
// Generate latest ambient types for the nx template, including env.d.ts (a separate async
|
|
273
|
+
// step — see TypeGenerator.syncEnvDeclaration — since spectra.config.ts's
|
|
274
|
+
// executionConfig.environmentVariables is what the template's EnvironmentConfig suite
|
|
275
|
+
// exercises via the typed Env global).
|
|
273
276
|
TypeGenerator.generateAll(nxTemplateDir);
|
|
277
|
+
await TypeGenerator.syncEnvDeclaration(nxTemplateDir);
|
|
274
278
|
expect(() => {
|
|
275
279
|
execSync(`npx tsc -b ${nxTemplateDir}`, { stdio: 'pipe' });
|
|
276
280
|
}).not.toThrow();
|
|
@@ -52,7 +52,7 @@ describe('TypeGenerator Engine (docs/v2/cli/ambient-types-generator.md)', () =>
|
|
|
52
52
|
fs.writeFileSync(path.join(poDir, 'web.ts'), 'export default class LoginPage {\n static username = "#user";\n static async login() {}\n}');
|
|
53
53
|
const stepDir = path.join(tmpDir, 'support', 'steps', 'loginAsAdmin');
|
|
54
54
|
fs.mkdirSync(stepDir, { recursive: true });
|
|
55
|
-
fs.writeFileSync(path.join(stepDir, 'web.step.ts'), 'export default async function
|
|
55
|
+
fs.writeFileSync(path.join(stepDir, 'web.step.ts'), 'export default async function (role?: string) {}');
|
|
56
56
|
const fixDir = path.join(tmpDir, 'fixtures');
|
|
57
57
|
fs.mkdirSync(fixDir, { recursive: true });
|
|
58
58
|
fs.writeFileSync(path.join(fixDir, 'users.json'), JSON.stringify({ admin: { id: 101, email: 'admin@test.local' } }));
|
|
@@ -383,4 +383,42 @@ async function verifyZeroImport() {
|
|
|
383
383
|
expect(fs.existsSync(path.join(tmpDir, '.testspectra', 'types', 'web.d.ts'))).toBe(false);
|
|
384
384
|
expect(fs.existsSync(path.join(tmpDir, '.testspectra', 'types', 'common.d.ts'))).toBe(false);
|
|
385
385
|
});
|
|
386
|
+
it('nx monorepo: does NOT treat feature library as shared library and discovers nested e2e subproject', () => {
|
|
387
|
+
// 1. Shared library with testspectra:shared
|
|
388
|
+
const sharedDir = path.join(tmpDir, 'shared', 'testing');
|
|
389
|
+
fs.mkdirSync(path.join(sharedDir, 'page-objects', 'SharedNav'), { recursive: true });
|
|
390
|
+
fs.writeFileSync(path.join(sharedDir, 'project.json'), JSON.stringify({ name: 'shared-testing', projectType: 'library', tags: ['testspectra:shared'] }));
|
|
391
|
+
fs.writeFileSync(path.join(sharedDir, 'page-objects', 'SharedNav', 'common.ts'), 'export default class SharedNav {}');
|
|
392
|
+
// 2. Nx Feature library (projectType: "library", standard Nx tags, NO testspectra tags)
|
|
393
|
+
const featureLibDir = path.join(tmpDir, 'packages', 'features', 'auth');
|
|
394
|
+
fs.mkdirSync(featureLibDir, { recursive: true });
|
|
395
|
+
fs.writeFileSync(path.join(featureLibDir, 'project.json'), JSON.stringify({
|
|
396
|
+
name: '@tagsamurai/feature-auth',
|
|
397
|
+
projectType: 'library',
|
|
398
|
+
sourceRoot: 'packages/features/auth',
|
|
399
|
+
targets: {},
|
|
400
|
+
tags: ['type:feature', 'scope:feature-auth'],
|
|
401
|
+
}));
|
|
402
|
+
// 3. Nested E2E subproject inside feature library
|
|
403
|
+
const featureE2eDir = path.join(featureLibDir, 'e2e');
|
|
404
|
+
fs.mkdirSync(path.join(featureE2eDir, 'specs', 'AuthSuite', 'TC-001'), { recursive: true });
|
|
405
|
+
fs.writeFileSync(path.join(featureE2eDir, 'project.json'), JSON.stringify({
|
|
406
|
+
name: 'feature-auth-e2e',
|
|
407
|
+
projectType: 'application',
|
|
408
|
+
tags: ['testspectra:e2e', 'testspectra:scope:feature-auth'],
|
|
409
|
+
}));
|
|
410
|
+
fs.writeFileSync(path.join(featureE2eDir, 'specs', 'AuthSuite', 'TC-001', 'web.test.ts'), 'it("auth test", async () => {});');
|
|
411
|
+
const scopes = TypeGenerator.getEntityScopes(tmpDir);
|
|
412
|
+
expect(scopes).toHaveLength(2);
|
|
413
|
+
const sharedScope = scopes.find((s) => s.isShared);
|
|
414
|
+
expect(sharedScope).toBeDefined();
|
|
415
|
+
expect(sharedScope?.name).toBe('shared');
|
|
416
|
+
expect(sharedScope?.dir).toBe(path.resolve(sharedDir));
|
|
417
|
+
const featureScope = scopes.find((s) => !s.isShared);
|
|
418
|
+
expect(featureScope).toBeDefined();
|
|
419
|
+
expect(featureScope?.name).toBe('feature-auth');
|
|
420
|
+
expect(featureScope?.dir).toBe(path.resolve(featureE2eDir));
|
|
421
|
+
// Verify packages/features/auth is NOT in scopes
|
|
422
|
+
expect(scopes.some((s) => s.dir === path.resolve(featureLibDir))).toBe(false);
|
|
423
|
+
});
|
|
386
424
|
});
|
|
@@ -31,7 +31,7 @@ export class TsConfigGenerator {
|
|
|
31
31
|
static getStemExcludes(prefix, stems) {
|
|
32
32
|
const excludes = [];
|
|
33
33
|
for (const stem of stems) {
|
|
34
|
-
excludes.push(`${prefix}/**/page-objects/**/${stem}.ts`, `${prefix}/**/
|
|
34
|
+
excludes.push(`${prefix}/**/page-objects/**/${stem}.ts`, `${prefix}/**/support/**/${stem}.*`, `${prefix}/**/global-hooks/**/${stem}.*`, `${prefix}/**/specs/**/hooks/**/${stem}.*`, `${prefix}/**/specs/**/${stem}.test.ts`, `${prefix}/**/${stem}.ts`, `${prefix}/**/${stem}.*`, `${prefix}/**/${stem}.*.ts`, `${prefix}/**/*.${stem}.ts`, `${prefix}/**/*.${stem}.*`, `${prefix}/**/*.${stem}.*.ts`);
|
|
35
35
|
}
|
|
36
36
|
return excludes;
|
|
37
37
|
}
|
|
@@ -41,21 +41,28 @@ export class TsConfigGenerator {
|
|
|
41
41
|
target: 'ES2022',
|
|
42
42
|
module: 'NodeNext',
|
|
43
43
|
moduleResolution: 'NodeNext',
|
|
44
|
+
jsx: 'react-jsx',
|
|
44
45
|
composite: true,
|
|
45
46
|
noEmit: true,
|
|
46
47
|
skipLibCheck: true,
|
|
47
48
|
strict: true,
|
|
48
|
-
types: ['node'
|
|
49
|
+
types: ['node'],
|
|
49
50
|
},
|
|
50
51
|
include: [
|
|
51
52
|
'../types/web.d.ts',
|
|
52
53
|
'../types/fixtures.d.ts',
|
|
53
54
|
'../../**/specs/**/*.ts',
|
|
55
|
+
'../../**/specs/**/*.tsx',
|
|
54
56
|
'../../**/page-objects/**/*.ts',
|
|
55
|
-
'../../**/
|
|
57
|
+
'../../**/page-objects/**/*.tsx',
|
|
56
58
|
'../../**/support/**/*.ts',
|
|
59
|
+
'../../**/support/**/*.tsx',
|
|
57
60
|
'../../**/global-hooks/**/*.ts',
|
|
61
|
+
'../../**/global-hooks/**/*.tsx',
|
|
58
62
|
'../../**/fixtures/**/*.ts',
|
|
63
|
+
'../../**/fixtures/**/*.json',
|
|
64
|
+
'../../**/src/**/*.ts',
|
|
65
|
+
'../../**/src/**/*.tsx',
|
|
59
66
|
'../../spectra.config.ts',
|
|
60
67
|
],
|
|
61
68
|
exclude: [
|
|
@@ -74,21 +81,28 @@ export class TsConfigGenerator {
|
|
|
74
81
|
target: 'ES2022',
|
|
75
82
|
module: 'NodeNext',
|
|
76
83
|
moduleResolution: 'NodeNext',
|
|
84
|
+
jsx: 'react-jsx',
|
|
77
85
|
composite: true,
|
|
78
86
|
noEmit: true,
|
|
79
87
|
skipLibCheck: true,
|
|
80
88
|
strict: true,
|
|
81
|
-
types: ['node'
|
|
89
|
+
types: ['node'],
|
|
82
90
|
},
|
|
83
91
|
include: [
|
|
84
92
|
'../types/mobile.d.ts',
|
|
85
93
|
'../types/fixtures.d.ts',
|
|
86
94
|
'../../**/specs/**/*.ts',
|
|
95
|
+
'../../**/specs/**/*.tsx',
|
|
87
96
|
'../../**/page-objects/**/*.ts',
|
|
88
|
-
'../../**/
|
|
97
|
+
'../../**/page-objects/**/*.tsx',
|
|
89
98
|
'../../**/support/**/*.ts',
|
|
99
|
+
'../../**/support/**/*.tsx',
|
|
90
100
|
'../../**/global-hooks/**/*.ts',
|
|
101
|
+
'../../**/global-hooks/**/*.tsx',
|
|
91
102
|
'../../**/fixtures/**/*.ts',
|
|
103
|
+
'../../**/fixtures/**/*.json',
|
|
104
|
+
'../../**/src/**/*.ts',
|
|
105
|
+
'../../**/src/**/*.tsx',
|
|
92
106
|
'../../spectra.config.ts',
|
|
93
107
|
],
|
|
94
108
|
exclude: [
|
|
@@ -107,21 +121,28 @@ export class TsConfigGenerator {
|
|
|
107
121
|
target: 'ES2022',
|
|
108
122
|
module: 'NodeNext',
|
|
109
123
|
moduleResolution: 'NodeNext',
|
|
124
|
+
jsx: 'react-jsx',
|
|
110
125
|
composite: true,
|
|
111
126
|
noEmit: true,
|
|
112
127
|
skipLibCheck: true,
|
|
113
128
|
strict: true,
|
|
114
|
-
types: ['node'
|
|
129
|
+
types: ['node'],
|
|
115
130
|
},
|
|
116
131
|
include: [
|
|
117
132
|
'../types/android.d.ts',
|
|
118
133
|
'../types/fixtures.d.ts',
|
|
119
134
|
'../../**/specs/**/*.ts',
|
|
135
|
+
'../../**/specs/**/*.tsx',
|
|
120
136
|
'../../**/page-objects/**/*.ts',
|
|
121
|
-
'../../**/
|
|
137
|
+
'../../**/page-objects/**/*.tsx',
|
|
122
138
|
'../../**/support/**/*.ts',
|
|
139
|
+
'../../**/support/**/*.tsx',
|
|
123
140
|
'../../**/global-hooks/**/*.ts',
|
|
141
|
+
'../../**/global-hooks/**/*.tsx',
|
|
124
142
|
'../../**/fixtures/**/*.ts',
|
|
143
|
+
'../../**/fixtures/**/*.json',
|
|
144
|
+
'../../**/src/**/*.ts',
|
|
145
|
+
'../../**/src/**/*.tsx',
|
|
125
146
|
'../../spectra.config.ts',
|
|
126
147
|
],
|
|
127
148
|
exclude: [
|
|
@@ -140,21 +161,28 @@ export class TsConfigGenerator {
|
|
|
140
161
|
target: 'ES2022',
|
|
141
162
|
module: 'NodeNext',
|
|
142
163
|
moduleResolution: 'NodeNext',
|
|
164
|
+
jsx: 'react-jsx',
|
|
143
165
|
composite: true,
|
|
144
166
|
noEmit: true,
|
|
145
167
|
skipLibCheck: true,
|
|
146
168
|
strict: true,
|
|
147
|
-
types: ['node'
|
|
169
|
+
types: ['node'],
|
|
148
170
|
},
|
|
149
171
|
include: [
|
|
150
172
|
'../types/ios.d.ts',
|
|
151
173
|
'../types/fixtures.d.ts',
|
|
152
174
|
'../../**/specs/**/*.ts',
|
|
175
|
+
'../../**/specs/**/*.tsx',
|
|
153
176
|
'../../**/page-objects/**/*.ts',
|
|
154
|
-
'../../**/
|
|
177
|
+
'../../**/page-objects/**/*.tsx',
|
|
155
178
|
'../../**/support/**/*.ts',
|
|
179
|
+
'../../**/support/**/*.tsx',
|
|
156
180
|
'../../**/global-hooks/**/*.ts',
|
|
181
|
+
'../../**/global-hooks/**/*.tsx',
|
|
157
182
|
'../../**/fixtures/**/*.ts',
|
|
183
|
+
'../../**/fixtures/**/*.json',
|
|
184
|
+
'../../**/src/**/*.ts',
|
|
185
|
+
'../../**/src/**/*.tsx',
|
|
158
186
|
'../../spectra.config.ts',
|
|
159
187
|
],
|
|
160
188
|
exclude: [
|
|
@@ -173,21 +201,23 @@ export class TsConfigGenerator {
|
|
|
173
201
|
target: 'ES2022',
|
|
174
202
|
module: 'NodeNext',
|
|
175
203
|
moduleResolution: 'NodeNext',
|
|
204
|
+
jsx: 'react-jsx',
|
|
176
205
|
composite: true,
|
|
177
206
|
noEmit: true,
|
|
178
207
|
skipLibCheck: true,
|
|
179
208
|
strict: true,
|
|
180
|
-
types: ['node'
|
|
209
|
+
types: ['node'],
|
|
181
210
|
},
|
|
182
211
|
include: [
|
|
183
212
|
'../types/common.d.ts',
|
|
184
213
|
'../types/fixtures.d.ts',
|
|
185
214
|
'../../**/page-objects/**/common.ts',
|
|
186
|
-
'../../**/
|
|
215
|
+
'../../**/page-objects/**/common.tsx',
|
|
187
216
|
'../../**/support/**/common.*',
|
|
188
217
|
'../../**/global-hooks/**/common.*',
|
|
189
218
|
'../../**/specs/**/hooks/**/common.*',
|
|
190
219
|
'../../**/specs/**/common.test.ts',
|
|
220
|
+
'../../**/specs/**/common.test.tsx',
|
|
191
221
|
'../../spectra.config.ts',
|
|
192
222
|
],
|
|
193
223
|
exclude: [
|
|
@@ -215,7 +245,7 @@ export class TsConfigGenerator {
|
|
|
215
245
|
const relCache = path.relative(subConfigDir, path.join(options.cwd, '.testspectra', 'cache')).replace(/\\/g, '/');
|
|
216
246
|
const platformDts = `${relTypesDir}/${platform}.d.ts`;
|
|
217
247
|
const fixturesDts = `${relTypesDir}/fixtures.d.ts`;
|
|
218
|
-
const include = [platformDts, fixturesDts, `${relScope}/**/*.ts`, relSpectraConfig];
|
|
248
|
+
const include = [platformDts, fixturesDts, `${relScope}/**/*.ts`, `${relScope}/**/*.tsx`, relSpectraConfig];
|
|
219
249
|
const baseExcludes = [relNodeModules, relDist, relReports, relRuns, relCache];
|
|
220
250
|
const stemMap = {
|
|
221
251
|
web: ['android', 'ios', 'mobile'],
|
|
@@ -234,7 +264,7 @@ export class TsConfigGenerator {
|
|
|
234
264
|
noEmit: true,
|
|
235
265
|
skipLibCheck: true,
|
|
236
266
|
strict: true,
|
|
237
|
-
types: ['node'
|
|
267
|
+
types: ['node'],
|
|
238
268
|
},
|
|
239
269
|
include,
|
|
240
270
|
exclude: [...baseExcludes, ...platformExcludes],
|
|
@@ -269,9 +299,7 @@ export class TsConfigGenerator {
|
|
|
269
299
|
const sharedScope = scopes.find((s) => s.isShared);
|
|
270
300
|
const featureScopes = scopes.filter((s) => !s.isShared);
|
|
271
301
|
const hasScopes = Boolean(sharedScope || featureScopes.length > 0);
|
|
272
|
-
const hasRootEntities = fs.existsSync(path.join(cwd, 'specs')) ||
|
|
273
|
-
fs.existsSync(path.join(cwd, 'page-objects')) ||
|
|
274
|
-
fs.existsSync(path.join(cwd, 'pageobjects'));
|
|
302
|
+
const hasRootEntities = fs.existsSync(path.join(cwd, 'specs')) || fs.existsSync(path.join(cwd, 'page-objects'));
|
|
275
303
|
if (!hasScopes || hasRootEntities) {
|
|
276
304
|
for (const filename of Object.keys(platformConfigs)) {
|
|
277
305
|
references.push({ path: `./tsconfig/${filename}` });
|