@testspectra/cli 1.0.0

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.
Files changed (41) hide show
  1. package/CLI_IMPLEMENTATION_PLAN.md +369 -0
  2. package/README.md +167 -0
  3. package/bin/spectra.js +7 -0
  4. package/bin/testspectra-runner +0 -0
  5. package/dist/commands/devices.d.ts +3 -0
  6. package/dist/commands/devices.js +37 -0
  7. package/dist/commands/doctor.d.ts +3 -0
  8. package/dist/commands/doctor.js +54 -0
  9. package/dist/commands/init.d.ts +3 -0
  10. package/dist/commands/init.js +401 -0
  11. package/dist/commands/run.d.ts +8 -0
  12. package/dist/commands/run.js +82 -0
  13. package/dist/commands/watch.d.ts +3 -0
  14. package/dist/commands/watch.js +30 -0
  15. package/dist/config/loader.d.ts +7 -0
  16. package/dist/config/loader.js +79 -0
  17. package/dist/config/schema.d.ts +365 -0
  18. package/dist/config/schema.js +80 -0
  19. package/dist/index.d.ts +6 -0
  20. package/dist/index.js +51 -0
  21. package/dist/runner/bridge.d.ts +20 -0
  22. package/dist/runner/bridge.js +122 -0
  23. package/dist/runner/reporter.d.ts +26 -0
  24. package/dist/runner/reporter.js +42 -0
  25. package/dist/types/generator.d.ts +7 -0
  26. package/dist/types/generator.js +195 -0
  27. package/package.json +32 -0
  28. package/src/commands/devices.ts +41 -0
  29. package/src/commands/doctor.ts +57 -0
  30. package/src/commands/init.ts +424 -0
  31. package/src/commands/run.ts +102 -0
  32. package/src/commands/watch.ts +34 -0
  33. package/src/config/loader.ts +82 -0
  34. package/src/config/schema.ts +489 -0
  35. package/src/index.ts +61 -0
  36. package/src/runner/bridge.ts +146 -0
  37. package/src/runner/reporter.ts +64 -0
  38. package/src/types/generator.ts +202 -0
  39. package/src/types/webdriverio.d.ts +46 -0
  40. package/testspectra-cli-1.0.0.tgz +0 -0
  41. package/tsconfig.json +16 -0
@@ -0,0 +1,369 @@
1
+ # TestSpectra CLI (`@testspectra/cli`) Implementation Plan
2
+
3
+ ## 1. Overview
4
+ The TestSpectra CLI provides a zero-config, command-line interface for running Web and Mobile (Android/iOS) test suites using the shared Rust core runner (`core/test-runner` and `core/device-manager`).
5
+
6
+ The CLI configuration strictly adheres to the backend `ProjectConfig` and `ConfigData` schema (`backend/src/models/project_config.rs` and `src/services/project-config-service.ts`).
7
+
8
+ ---
9
+
10
+ ## 2. Architecture
11
+
12
+ ```
13
+ ┌─────────────────────────────────┐
14
+ │ TypeScript CLI (`cli/`) │
15
+ │ (commander / inquirer / ora) │
16
+ └────────────────┬────────────────┘
17
+
18
+ ┌────────────────┴────────────────┐
19
+ ▼ ▼
20
+ Local Execution Remote Execution
21
+ ┌─────────────────────────────┐ ┌─────────────────────────────┐
22
+ │ NAPI-RS / Subprocess Bridge │ │ HTTP REST API Client │
23
+ │ to core/test-runner (Rust) │ │ to Backend API Server │
24
+ └──────────────┬──────────────┘ └──────────────┬──────────────┘
25
+ │ │
26
+ ▼ ▼
27
+ ┌───────────────────────┐ ┌───────────────────────┐
28
+ │ core/test-runner │ │ Backend API │
29
+ │ (Rust Engine) │ │ (PostgreSQL + Engine) │
30
+ └───────────────────────┘ └───────────────────────┘
31
+ ```
32
+
33
+ ---
34
+
35
+ ## 3. Package & File Structure
36
+
37
+ ```
38
+ testspectra-source/
39
+ └── cli/
40
+ ├── README.md
41
+ ├── CLI_IMPLEMENTATION_PLAN.md <-- This Plan
42
+ ├── package.json
43
+ ├── tsconfig.json
44
+ ├── bin/
45
+ │ └── testspectra.js
46
+ └── src/
47
+ ├── index.ts # Main entrypoint & Commander setup
48
+ ├── config/
49
+ │ ├── schema.ts # Exact ConfigData & ProjectConfig TypeScript types
50
+ │ └── loader.ts # Config resolution (file vs remote vs CLI flags)
51
+ ├── commands/
52
+ │ ├── init.ts # Generate default testspectra.config.json
53
+ │ ├── run.ts # Execute test cases/suites
54
+ │ ├── devices.ts # List connected Android/iOS/Web devices
55
+ │ └── doctor.ts # System diagnostic check (ADB, Appium, Java, Browsers)
56
+ ├── runner/
57
+ │ ├── bridge.ts # Interface to Rust core runner binary/NAPI
58
+ │ └── reporter.ts # Spec, JSON, & JUnit XML reporters
59
+ └── api/
60
+ └── client.ts # REST client for sync with backend project config
61
+ ```
62
+
63
+ ---
64
+
65
+ ## 4. Configuration Schema (`cli/src/config/schema.ts`)
66
+
67
+ Matches `backend/src/models/project_config.rs` and `src/services/project-config-service.ts`:
68
+
69
+ ```typescript
70
+ export interface WebConfig {
71
+ baseUrl: string;
72
+ maxConcurrentSessions: string;
73
+ headlessMode: boolean;
74
+ implicitWait: string;
75
+ pageLoadTimeout: string;
76
+ scriptTimeout: string;
77
+ parallelizationMode: "testcase" | "suite";
78
+ }
79
+
80
+ export interface AndroidConfig {
81
+ appiumServer: string;
82
+ platformName: string;
83
+ platformVersion: string;
84
+ deviceName: string;
85
+ automationName: string;
86
+ appPackage: string;
87
+ appActivity: string;
88
+ autoGrantPermissions: boolean;
89
+ noReset: boolean;
90
+ implicitWait: string;
91
+ parallelizationMode: "testcase" | "suite";
92
+ }
93
+
94
+ export interface IosConfig {
95
+ appiumServer: string;
96
+ platformName: string;
97
+ platformVersion: string;
98
+ deviceName: string;
99
+ automationName: string;
100
+ bundleId: string;
101
+ udid: string;
102
+ xcodeOrgId: string;
103
+ xcodeSigningId: string;
104
+ autoAcceptAlerts: boolean;
105
+ noReset: boolean;
106
+ implicitWait: string;
107
+ parallelizationMode: "testcase" | "suite";
108
+ }
109
+
110
+ export interface ConfigData {
111
+ webConfig: WebConfig;
112
+ browsers: Array<{
113
+ id: string;
114
+ type: string;
115
+ mobileEmulation: boolean;
116
+ deviceName?: string;
117
+ width?: string;
118
+ height?: string;
119
+ }>;
120
+ androidConfig: AndroidConfig;
121
+ iosConfig: IosConfig;
122
+ loadConfig: {
123
+ virtualUsers: string;
124
+ duration: string;
125
+ };
126
+ loadStages: Array<{
127
+ id: string;
128
+ duration: string;
129
+ targetVUs: string;
130
+ }>;
131
+ thresholds: Array<{
132
+ id: string;
133
+ metricType: string;
134
+ maxValue: string;
135
+ }>;
136
+ executionConfig?: {
137
+ networkMonitoringEnabled: boolean;
138
+ fastResponseTime: string;
139
+ normalResponseTime: string;
140
+ monitoredDomains?: Array<{ domain: string; enabled: boolean }>;
141
+ environmentVariables?: Array<{ key: string; value: string }>;
142
+ };
143
+ }
144
+
145
+ export interface ProjectConfig {
146
+ project_id: string;
147
+ config_data: ConfigData;
148
+ updated_at?: string;
149
+ }
150
+ ```
151
+
152
+ ---
153
+
154
+ ## 5. Key CLI Commands & Features
155
+
156
+ | Command | Arguments / Flags | Description |
157
+ |---|---|---|
158
+ | `testspectra init` | `--force` | Generate default `testspectra.config.json` adhering to `ConfigData`. |
159
+ | `testspectra doctor` | `--fix` | Diagnostic check for ADB, Appium, Chrome, Java, Node. |
160
+ | `testspectra devices` | `--target <android\|ios\|web>` | List connected devices & available browsers. |
161
+ | `testspectra run` | `<path>` `--target <target>` `--remote` `--project-id <id>` | Run test cases/suites via local config or remote backend config. |
162
+
163
+ ---
164
+
165
+ ## 6. Execution Flow & Driver Management
166
+
167
+ 1. **Base Directory Resolution (`app_data_path`):**
168
+ - CLI sets `RunnerContext.app_data_path` to `./.testspectra` inside the target project root (overridable via `--workdir`).
169
+ - Driver cache automatically lands in `./.testspectra/driver_cache`.
170
+ - Desktop Tauri app uses OS AppSupport (`~/Library/Application Support/...`), while CLI isolates everything inside project `.testspectra`.
171
+
172
+ 2. **Initialization:** CLI resolves config via local `testspectra.config.json` or fetches `ProjectConfig` from backend.
173
+ 3. **Environment Validation:** Verifies Appium / ADB readiness using `core/device-manager`.
174
+ 4. **Execution & Driver Auto-Recovery:**
175
+ - Pass resolved `ConfigData` JSON + test files payload into `core/test-runner` Rust engine via NAPI bridge or subprocess IPC stream.
176
+ - `core/test-runner` automatically monitors for Chromedriver download failures, wipes `./.testspectra/driver_cache`, and retries once transparently.
177
+ 5. **Reporting:** Stream real-time logs and output JUnit / Spec formatted result.
178
+
179
+ ---
180
+
181
+ ## 7. Refactoring Plan: Moving Shared Core Features from `src-tauri` to `core/`
182
+
183
+ To avoid code duplication and support CLI/Server environments natively, the following features will be refactored from `src-tauri` into the shared `core` workspace:
184
+
185
+ ### A. ADB Wireless & Pairing (`src-tauri/src/adb.rs` → `core/device-manager`)
186
+ - **Current State:** High-level device discovery and auto-reconnection loop (`get_adb_devices_impl`) live in `src-tauri/src/adb.rs` while primitive ADB calls live in `core/device-manager`.
187
+ - **Target Architecture:**
188
+ - Move stateful device tracking & background auto-reconnection into `core/device-manager::android`.
189
+ - Provide headless Rust/C-API/NAPI methods (`get_adb_devices`, `pair_adb_device`, `start_qr_pairing`) accessible to both Tauri app and `testspectra devices pair` CLI command.
190
+
191
+ ### B. Dependency Check & Installer (`src-tauri/src/dependencies.rs` → `core/test-runner`)
192
+ - **Current State:** `src-tauri/src/dependencies.rs` wraps `testspectra_core_runner::dependency` with Tauri `AppHandle` events for emitting install logs.
193
+ - **Target Architecture:**
194
+ - Decouple log emission using a generic callback/channel pattern (`fn(log: DependencyLog)`).
195
+ - Move full dependency resolution & auto-installer (`install_missing_dependencies`) into `core/test-runner::dependency`.
196
+ - Tauri UI subscribes via channel; CLI `testspectra doctor --fix` renders progress directly to terminal stdout/stderr via `ora` spinner / progress bar.
197
+
198
+ ---
199
+
200
+ ## 8. Multi-Platform Hierarchy & Ambient Type Resolution
201
+
202
+ TestSpectra scripts are organized natively by **Entity Folders** supporting multi-platform hierarchy resolution (as defined in `docs/features/v1.3-MULTI_PLATFORM_AUTOMATION.md`):
203
+
204
+ ### A. Resolution Hierarchy (Highest to Lowest Priority)
205
+ | Target Context / Spec | Hierarchy Chain |
206
+ | :--- | :--- |
207
+ | **Web Context (`web.test.ts`)** | `*.web.ts` &rarr; `*.common.ts` (or `*.ts` fallback) |
208
+ | **iOS Context (`ios.test.ts`)** | `*.ios.ts` &rarr; `*.mobile.ts` &rarr; `*.common.ts` |
209
+ | **Android Context (`android.test.ts`)** | `*.android.ts` &rarr; `*.mobile.ts` &rarr; `*.common.ts` |
210
+ | **Mobile Context (`mobile.test.ts`)** | `*.mobile.ts` &rarr; `*.common.ts` |
211
+ | **Common Context (`common.test.ts`)** | `*.common.ts` (Strict base only) |
212
+
213
+ ### B. Ambient Global Resolution in Specs (Zero Manual Imports)
214
+ TestSpectra execution preparer (`core/test-runner`) and the CLI Type Generator (`cli::TypeGenerator`) synthesize global ambient declarations (`.testspectra/types/{web,android,ios,mobile,common}.d.ts`) so specs never need manual imports for Page Objects, Actions, Steps, or Fixtures:
215
+ - **`LoginPage.open()`** &rarr; Ambiently declared via `declare const LoginPage: typeof import('../page-objects/LoginPage/web.js').default;`
216
+ - **`Spectra.actionName()`** &rarr; Ambiently declared per platform from `actions/`.
217
+ - **`Step.stepName()`** &rarr; Ambiently declared per platform from `steps/`.
218
+ - **`Fixture.fixtureName`** &rarr; Ambiently declared from `fixtures/` assets.
219
+ - **`browser.intercept()`** &rarr; Ambiently declared on `WebdriverIO.Browser`.
220
+
221
+ No custom VS Code language server plugin or extension is required. Standard TypeScript compiler (`tsc`) and standard IDEs (VS Code, Cursor, WebStorm) handle everything natively via the platform tsconfigs.
222
+
223
+ ## 9. Standard TestSpectra Multi-Platform Project Structure & Platform-Isolated TSConfigs
224
+
225
+ To ensure 100% accurate TypeScript type resolution without collisions across platform signatures (e.g. `login(u,p)` on Web vs `login(u,p,captcha)` on Mobile), TestSpectra uses **Platform-Isolated TSConfigs**:
226
+
227
+ ```text
228
+ my-test-project/
229
+ ├── tsconfig.json # Solution root pointing to platform tsconfigs
230
+ ├── tsconfig.web.json # Web TS context (web specs + web.d.ts + common.d.ts)
231
+ ├── tsconfig.android.json # Android TS context (android specs + android.d.ts + mobile.d.ts + common.d.ts)
232
+ ├── tsconfig.ios.json # iOS TS context (ios specs + ios.d.ts + mobile.d.ts + common.d.ts)
233
+ ├── spectra.config.ts # Matching backend ConfigData schema (typed with defineConfig)
234
+ ├── .testspectra/ # Local TestSpectra runtime & types (ignored in git)
235
+ │ ├── types/
236
+ │ │ ├── web.d.ts # Generated ambient types for web
237
+ │ │ ├── android.d.ts # Generated ambient types for android
238
+ │ │ ├── ios.d.ts # Generated ambient types for ios
239
+ │ │ └── common.d.ts # Generated ambient types for common
240
+ │ └── driver_cache/ # Managed Chromedriver / Appium cache
241
+
242
+ ├── specs/ # Entity folder per Test Case
243
+ │ └── TC-LOGIN-01/
244
+ │ ├── web.test.ts # Web implementation (zero-import single it block)
245
+ │ ├── android.test.ts # Android implementation
246
+ │ └── ios.test.ts # iOS implementation
247
+
248
+ ├── page-objects/ # Entity folder per Page Object
249
+ │ └── LoginPage/
250
+ │ ├── web.ts # Web Page Object implementation
251
+ │ └── mobile.ts # Shared mobile Page Object implementation
252
+
253
+ ├── actions/ # Entity folder per Action
254
+ │ └── verifyOtp/
255
+ │ ├── web.action.ts
256
+ │ └── mobile.action.ts
257
+
258
+ ├── steps/ # Entity folder per Step
259
+ │ └── loginUser/
260
+ │ ├── web.step.ts
261
+ │ └── mobile.step.ts
262
+
263
+ ├── fixtures/ # Test assets (JSON, PNG, CSV)
264
+ │ └── userData.json
265
+
266
+ └── hooks/ # Per-suite lifecycle hooks
267
+ └── default/
268
+ ├── before.web.hook.ts
269
+ ├── before.android.hook.ts
270
+ └── before.ios.hook.ts
271
+ ```
272
+
273
+ ### Complete Scaffolding on `spectra init`
274
+ Running `spectra init` automatically scaffolds:
275
+ 1. `spectra.config.ts` using `defineConfig`.
276
+ 2. Root `tsconfig.json` & platform-isolated `tsconfig.web.json`, `tsconfig.android.json`, `tsconfig.ios.json`.
277
+ 3. Complete boilerplate templates for **Page Objects**, **Specs**, **Actions**, **Steps**, **Fixtures**, and **Suite Hooks**.
278
+ 4. `.gitignore` ensuring `.testspectra/`, `dist/`, and `node_modules/` are not committed.
279
+ 5. All scaffolded templates pass TypeScript checking with **0 errors**.
280
+
281
+ 3. Updates TypeScript triple-slash references if necessary.
282
+
283
+ ### B. Dependencies Location & Isolation (`node_modules`)
284
+ - CLI isolates WebdriverIO & Appium dependencies into `./.testspectra/node_modules` (or uses root `node_modules` if a `package.json` is present).
285
+ - Ensures user test projects don't need a manually managed `package.json` unless desired.
286
+
287
+ ---
288
+
289
+ ## 11. Custom Browser Commands & Fixture-Integrated Interceptor (`browser.intercept`)
290
+
291
+ TestSpectra extends WebdriverIO's `browser` object with runtime custom commands bundled directly in `core/test-runner` execution preparer (keeping user `wdio.conf.ts` completely clean).
292
+
293
+ ### A. Feature Capabilities
294
+ - **`browser.intercept(path, method, fixture?, options?)`**: Strongly-typed API mock interceptor.
295
+ - **Fixture Object Integration:** Accepts `Fixture.sampleJson` asset references directly, auto-loading and parsing files from `fixtures/`.
296
+ - **Dynamic `mock.respondWith()`**: Allows updating mock responses on the fly within individual test steps.
297
+
298
+ ### B. Type Declarations (`cli/src/types/webdriverio.d.ts`)
299
+ ```typescript
300
+ declare global {
301
+ namespace WebdriverIO {
302
+ export interface InterceptFixtureOptions {
303
+ statusCode?: number;
304
+ headers?: Record<string, string>;
305
+ }
306
+
307
+ export interface InterceptFixtureObject<TData = unknown> {
308
+ statusCode?: number;
309
+ body: TData;
310
+ headers?: Record<string, string>;
311
+ }
312
+
313
+ export type InterceptInput<TData = unknown> =
314
+ | InterceptFixtureObject<TData>
315
+ | TData
316
+ | string;
317
+
318
+ interface Mock {
319
+ /**
320
+ * Dynamically set or change the fixture response for this mock instance.
321
+ * Supports Fixture paths, `{ statusCode, body, headers }` objects, or raw payloads.
322
+ */
323
+ respondWith<TData = unknown>(
324
+ fixture: InterceptInput<TData>,
325
+ options?: InterceptFixtureOptions,
326
+ ): Promise<void>;
327
+ }
328
+
329
+ interface Browser {
330
+ /**
331
+ * Clean & strongly-typed API interceptor for WebdriverIO.
332
+ * Automatically resolves relative path against browser.options.baseUrl.
333
+ * Integrated directly with TestSpectra Fixtures.
334
+ */
335
+ intercept<TData = unknown>(
336
+ path: string,
337
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH',
338
+ fixture?: InterceptInput<TData>,
339
+ options?: InterceptFixtureOptions,
340
+ ): Promise<Mock>;
341
+ }
342
+ }
343
+ }
344
+ ```
345
+
346
+ ### C. Usage Example in Test Files
347
+ ```typescript
348
+ test('intercept user API using TestSpectra Fixtures', async () => {
349
+ // Pass Fixture asset directly
350
+ await browser.intercept('/api/users', 'GET', Fixture.usersListJson);
351
+
352
+ // Pass Fixture object with custom status code
353
+ await browser.intercept('/api/login', 'POST', {
354
+ statusCode: 401,
355
+ body: { error: 'Invalid credentials' }
356
+ });
357
+
358
+ // Dynamic response update
359
+ const userMock = await browser.intercept('/api/profile', 'GET');
360
+ await userMock.respondWith(Fixture.adminProfileJson, { statusCode: 200 });
361
+ });
362
+ ```
363
+
364
+ ---
365
+
366
+ ### C. Test Output & Reports (Real-Time Stdout + Local JSON Export)
367
+ For local CLI runs, test execution provides real-time feedback and JSON persistence:
368
+ - **Terminal Stdout:** Real-time colored stdout stream of step `TestLog` entries.
369
+ - **Local JSON Output:** Saves complete `TestRunResult` payload (`status`, `duration`, `logs`, CDP `networkResources`) to `./.testspectra/reports/result.json` (or custom path via `--output <path>`).
package/README.md ADDED
@@ -0,0 +1,167 @@
1
+ # @testspectra/cli — Architecture & Implementation
2
+
3
+ The **TestSpectra CLI** (`spectra` / `testspectra`) is the command-line orchestrator and developer tooling layer for the TestSpectra testing framework. It enables unified multi-platform test authoring (Web, Android, iOS), zero-import ambient typing, dynamic configuration, and high-performance native test execution powered by the Rust core runner.
4
+
5
+ ---
6
+
7
+ ## 1. Core Architecture Overview
8
+
9
+ ```
10
+ ┌──────────────────────────┐
11
+ │ User Test Project │
12
+ │ (Zero-Import TypeScript) │
13
+ └─────────────┬────────────┘
14
+
15
+ ┌──────────────────────┴──────────────────────┐
16
+ │ │
17
+ ▼ ▼
18
+ ┌──────────────────────┐ ┌────────────────────────┐
19
+ │ spectra watch / run │ │ Solution TSConfigs │
20
+ │ (CLI Orchestration) │ │ (tsconfig.*.json) │
21
+ └───────────┬──────────┘ └────────────┬───────────┘
22
+ │ │
23
+ │ 1. Generates Ambient .d.ts │ 2. Isolated Platform
24
+ │ in .testspectra/types/ │ Type Checking
25
+ ▼ ▼
26
+ ┌──────────────────────┐ ┌────────────────────────┐
27
+ │ Core Test Runner │ │ Standard IDE & tsc │
28
+ │ (Rust Native Bin) │ │ (VS Code, Cursor, CI) │
29
+ └──────────────────────┘ └────────────────────────┘
30
+ ```
31
+
32
+ ---
33
+
34
+ ## 2. Key Architectural Pillars
35
+
36
+ ### A. Zero-Import Multi-Platform Authoring
37
+ TestSpectra allows developers to write clean, boilerplate-free test specs, steps, actions, and page objects without manual `import` statements for globals or framework entities:
38
+ - **Page Objects**: `LoginPage.login(...)` resolves automatically based on target platform.
39
+ - **Actions**: `Spectra.verifyOtp(...)` provides typed action access.
40
+ - **Steps**: `Step.loginUser(...)` exposes shared business step flows.
41
+ - **Fixtures**: `Fixture.userData` provides typed, platform-agnostic test fixture access.
42
+ - **WebdriverIO Globals**: `$`, `$$`, `browser`, `expect` are available globally across all platforms.
43
+
44
+ ### B. Platform Hierarchy & Resolution
45
+ Entities are structured with hierarchical platform stems:
46
+ ```
47
+ page-objects/
48
+ └── LoginPage/
49
+ ├── web.ts # Used for Web
50
+ └── mobile.ts # Fallback for Android and iOS
51
+
52
+ specs/
53
+ └── TC-LOGIN-01/
54
+ ├── web.test.ts # Web spec
55
+ ├── android.test.ts # Android spec
56
+ └── ios.test.ts # iOS spec
57
+ ```
58
+
59
+ Resolution order:
60
+ - **`web`**: `web` → `common`
61
+ - **`android`**: `android` → `mobile` → `common`
62
+ - **`ios`**: `ios` → `mobile` → `common`
63
+ - **`mobile`**: `mobile` → `common`
64
+ - **`common`**: `common`
65
+
66
+ ### C. Solution-Style TypeScript Configuration (`tsconfig.json`)
67
+ To avoid ambient type clashes between platforms (such as different method signatures across Web and Mobile Page Objects), TestSpectra uses standard TypeScript **Project References**:
68
+ - **`tsconfig.json`**: Root project reference orchestrator pointing to platform configs.
69
+ - **`tsconfig.web.json`**: Scoped exclusively to Web files and `.testspectra/types/web.d.ts`.
70
+ - **`tsconfig.android.json`**: Scoped exclusively to Android files and `.testspectra/types/android.d.ts`.
71
+ - **`tsconfig.ios.json`**: Scoped exclusively to iOS files and `.testspectra/types/ios.d.ts`.
72
+ - **`fixtures.d.ts`**: Single platform-agnostic declaration file referenced by all platform declarations.
73
+
74
+ Project verification is executed with standard `tsc`:
75
+ ```bash
76
+ tsc -b
77
+ ```
78
+
79
+ ### D. Typed Configuration with `defineConfig`
80
+ Configuration is strongly typed with full JSDoc documentation via `spectra.config.ts`:
81
+ ```typescript
82
+ import { defineConfig } from "@testspectra/cli";
83
+
84
+ export default defineConfig({
85
+ webConfig: {
86
+ baseUrl: "https://the-internet.herokuapp.com",
87
+ headlessMode: true,
88
+ },
89
+ browsers: [
90
+ { id: "chrome-desktop", type: "chrome" },
91
+ ],
92
+ androidConfig: {
93
+ platformName: "Android",
94
+ automationName: "UiAutomator2",
95
+ },
96
+ });
97
+ ```
98
+
99
+ ---
100
+
101
+ ## 3. CLI Commands
102
+
103
+ | Command | Description |
104
+ | :--- | :--- |
105
+ | `spectra init` | Scaffolds a complete multi-platform project from scratch with tsconfigs, specs, page objects, actions, steps, and fixtures. |
106
+ | `spectra watch` | Starts a file-system watcher that regenerates `.testspectra/types/` ambient declarations on changes in debounced mode. |
107
+ | `spectra run` | Generates declaration types and invokes the native Rust test runner to execute the test suite. |
108
+
109
+ ---
110
+
111
+ ## 4. Directory Structure of a TestSpectra Project
112
+
113
+ ```
114
+ ├── spectra.config.ts # Central typed project configuration
115
+ ├── package.json # Scripts & dependencies
116
+ ├── tsconfig.json # Root solution references
117
+ ├── tsconfig.web.json # Web platform TypeScript scope
118
+ ├── tsconfig.android.json # Android platform TypeScript scope
119
+ ├── tsconfig.ios.json # iOS platform TypeScript scope
120
+ ├── page-objects/ # Page Object Model folders
121
+ │ └── LoginPage/
122
+ │ ├── web.ts
123
+ │ └── mobile.ts
124
+ ├── actions/ # Reusable atomic actions
125
+ │ └── verifyOtp/
126
+ │ ├── web.action.ts
127
+ │ └── mobile.action.ts
128
+ ├── steps/ # High-level business flows
129
+ │ └── loginUser/
130
+ │ ├── web.step.ts
131
+ │ └── mobile.step.ts
132
+ ├── hooks/ # Suite lifecycle hooks
133
+ │ └── default/
134
+ │ ├── before.web.hook.ts
135
+ │ ├── before.android.hook.ts
136
+ │ └── before.ios.hook.ts
137
+ ├── specs/ # Standalone zero-import test cases
138
+ │ └── TC-LOGIN-01/
139
+ │ ├── web.test.ts
140
+ │ ├── android.test.ts
141
+ │ └── ios.test.ts
142
+ ├── fixtures/ # Platform-agnostic test data
143
+ │ └── userData.json
144
+ └── .testspectra/ # Auto-generated ambient typings
145
+ └── types/
146
+ ├── fixtures.d.ts
147
+ ├── web.d.ts
148
+ ├── android.d.ts
149
+ ├── ios.d.ts
150
+ ├── mobile.d.ts
151
+ └── common.d.ts
152
+ ```
153
+
154
+ ---
155
+
156
+ ## 5. Development & Verification
157
+
158
+ To verify the CLI and example app:
159
+ ```bash
160
+ # Build CLI
161
+ pnpm --filter @testspectra/cli build
162
+
163
+ # Initialize and verify example app
164
+ cd apps/example-app
165
+ ../../cli/bin/spectra.js init
166
+ npx tsc -b tsconfig.json
167
+ ```
package/bin/spectra.js ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { runCli } from "../dist/index.js";
3
+
4
+ runCli().catch((err) => {
5
+ console.error(err);
6
+ process.exit(1);
7
+ });
Binary file
@@ -0,0 +1,3 @@
1
+ export declare function devicesCommand(options: {
2
+ target?: "android" | "ios" | "web" | "all";
3
+ }): Promise<void>;
@@ -0,0 +1,37 @@
1
+ import { execSync } from "child_process";
2
+ export async function devicesCommand(options) {
3
+ const target = options.target || "all";
4
+ console.log(`\x1b[36m[TestSpectra Devices]\x1b[0m Listing connected test targets (scope: ${target})...\n`);
5
+ if (target === "all" || target === "android") {
6
+ console.log("\x1b[1mAndroid Devices (ADB):\x1b[0m");
7
+ try {
8
+ const adbOutput = execSync("adb devices -l", { stdio: "pipe" }).toString();
9
+ const lines = adbOutput.split("\n").slice(1);
10
+ let found = false;
11
+ for (const line of lines) {
12
+ if (line.trim()) {
13
+ found = true;
14
+ console.log(` \x1b[32m•\x1b[0m ${line.trim()}`);
15
+ }
16
+ }
17
+ if (!found) {
18
+ console.log(" \x1b[90mNo Android devices/emulators connected via ADB.\x1b[0m");
19
+ }
20
+ }
21
+ catch {
22
+ console.log(" \x1b[31mADB command failed or platform-tools not in PATH.\x1b[0m");
23
+ }
24
+ }
25
+ if (target === "all" || target === "web") {
26
+ console.log("\n\x1b[1mWeb Browsers:\x1b[0m");
27
+ try {
28
+ const chromeVer = execSync(process.platform === "darwin"
29
+ ? '"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --version'
30
+ : "google-chrome --version", { stdio: "pipe" }).toString().trim();
31
+ console.log(` \x1b[32m•\x1b[0m Chrome: ${chromeVer}`);
32
+ }
33
+ catch {
34
+ console.log(" \x1b[90m• Chrome: Not installed\x1b[0m");
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,3 @@
1
+ export declare function doctorCommand(options: {
2
+ fix?: boolean;
3
+ }): Promise<void>;
@@ -0,0 +1,54 @@
1
+ import { execSync } from "child_process";
2
+ export async function doctorCommand(options) {
3
+ console.log("\x1b[36m[TestSpectra Doctor]\x1b[0m Checking development and runtime dependencies...\n");
4
+ const checks = [
5
+ {
6
+ name: "Node.js",
7
+ command: "node -v",
8
+ required: true,
9
+ },
10
+ {
11
+ name: "Bun",
12
+ command: "bun -v",
13
+ required: false,
14
+ },
15
+ {
16
+ name: "ADB (Android Debug Bridge)",
17
+ command: "adb version",
18
+ required: false,
19
+ },
20
+ {
21
+ name: "Java JDK",
22
+ command: "java -version",
23
+ required: false,
24
+ },
25
+ {
26
+ name: "Google Chrome",
27
+ command: process.platform === "darwin"
28
+ ? '"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --version'
29
+ : "google-chrome --version",
30
+ required: false,
31
+ },
32
+ ];
33
+ let missingCount = 0;
34
+ for (const check of checks) {
35
+ try {
36
+ const out = execSync(check.command, { stdio: "pipe" }).toString().trim();
37
+ const firstLine = out.split("\n")[0];
38
+ console.log(` \x1b[32m✓\x1b[0m ${check.name.padEnd(30)} \x1b[90m(${firstLine})\x1b[0m`);
39
+ }
40
+ catch {
41
+ console.log(` \x1b[31m✗\x1b[0m ${check.name.padEnd(30)} \x1b[31m(Not found)\x1b[0m`);
42
+ if (check.required) {
43
+ missingCount++;
44
+ }
45
+ }
46
+ }
47
+ console.log("\n------------------------------------------------------------");
48
+ if (missingCount === 0) {
49
+ console.log("\x1b[32m[Doctor]\x1b[0m System ready for local test execution!");
50
+ }
51
+ else {
52
+ console.log(`\x1b[33m[Doctor]\x1b[0m Found ${missingCount} missing required dependencies.`);
53
+ }
54
+ }
@@ -0,0 +1,3 @@
1
+ export declare function initCommand(options: {
2
+ force?: boolean;
3
+ }): Promise<void>;