@testspectra/cli 1.0.18 → 1.0.20

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 CHANGED
@@ -161,14 +161,14 @@ export default defineConfig({
161
161
 
162
162
  | Command | Description |
163
163
  | :--- | :--- |
164
- | `spectra init` | Scaffolds a complete multi-platform project from scratch with tsconfigs, specs, page objects, actions, steps, and fixtures. |
165
- | `spectra run` | Generates declaration types and invokes the native Rust test runner to execute the test suite. |
164
+ | `spectra init` / `npx @testspectra/cli init` | Interactive project setup. Auto-detects standalone or Nx Monorepos, discovers workspace packages from `pnpm-workspace.yaml`, and scaffolds centralized/distributed configurations. |
165
+ | `spectra run [spec]` | Automatically updates ambient declarations and invokes the native Rust test runner to execute the test suite. |
166
166
  | `spectra doctor` | Verifies local environment prerequisites (ADB, Java, Chrome, Bun, Node). |
167
167
  | `spectra devices` | Lists connected Android/iOS devices and local browsers. |
168
168
 
169
169
  ---
170
170
 
171
- ## 4. Directory Structure of a TestSpectra Project
171
+ ## 4. Standalone Project Directory Structure
172
172
 
173
173
  ```
174
174
  ├── spectra.config.ts # Central typed project configuration
@@ -189,19 +189,17 @@ export default defineConfig({
189
189
  │ └── loginUser/
190
190
  │ ├── web.step.ts
191
191
  │ └── mobile.step.ts
192
- ├── hooks/ # Suite lifecycle hooks
193
- │ └── default/
194
- ├── before.web.hook.ts
195
- ├── before.android.hook.ts
196
- │ └── before.ios.hook.ts
197
- ├── specs/ # Standalone zero-import test cases
198
- └── TC-LOGIN-01/
199
- ├── web.test.ts
200
- │ ├── android.test.ts
201
- │ └── ios.test.ts
192
+ ├── global-hooks/ # Global lifecycle hooks
193
+ │ └── before.web.hook.ts
194
+ ├── specs/ # Layered zero-import test cases
195
+ └── Auth/
196
+ │ └── TC-AUTH-01/
197
+ ├── web.test.ts
198
+ ├── android.test.ts
199
+ └── ios.test.ts
202
200
  ├── fixtures/ # Platform-agnostic test data
203
201
  │ └── userData.json
204
- └── .testspectra/ # Auto-generated ambient typings
202
+ └── .testspectra/ # Auto-generated ambient typings & cache
205
203
  └── types/
206
204
  ├── fixtures.d.ts
207
205
  ├── web.d.ts
@@ -213,15 +211,83 @@ export default defineConfig({
213
211
 
214
212
  ---
215
213
 
216
- ## 5. Development & Verification
214
+ ## 5. Enterprise Monorepo Architecture (Nx & PNPM Workspace)
215
+
216
+ TestSpectra features an enterprise-grade architecture for large monorepos: **"Centralized Configuration, Distributed Implementation"**.
217
+
218
+ ```
219
+ ┌───────────────────────────────────────────────────────────┐
220
+ │ Root Monorepo Directory │
221
+ │ │
222
+ │ ├── spectra.config.ts (Central Execution Config) │
223
+ │ ├── .testspectra/ (Central Cache, AppData, Log)│
224
+ │ ├── pnpm-workspace.yaml (Workspace Definition) │
225
+ │ ├── nx.json (Nx Target & Caching Rules) │
226
+ │ └── tsconfig.json (Solution References) │
227
+ └─────────────────────────────┬─────────────────────────────┘
228
+
229
+ ┌──────────────────────────────┴──────────────────────────────┐
230
+ ▼ ▼
231
+ ┌───────────────────────────────┐ ┌───────────────────────────────┐
232
+ │ shared/testing/ (Library) │ │ packages/features/auth/e2e/ │
233
+ ├───────────────────────────────┤ ├───────────────────────────────┤
234
+ │ - Shared Page Objects │ ◄─── Auto-Scanned Globals ──│ - Feature Specs (specs/) │
235
+ │ - Shared Steps (loginAsAdmin) │ (100% Zero-Import!) │ - Feature Page Objects (POMs) │
236
+ │ - Shared Actions (dismissBtn) │ │ - project.json (Nx Target) │
237
+ │ - Shared Fixtures (appConfig) │ │ - tsconfig.web/android/ios │
238
+ └───────────────────────────────┘ └───────────────────────────────┘
239
+ ```
240
+
241
+ ### Key Pillars of Monorepo Integration:
242
+
243
+ 1. **Interactive Workspace Auto-Discovery (`spectra init`)**:
244
+ - Parses `pnpm-workspace.yaml` (e.g. `packages/features/*`, `modules/**`).
245
+ - Scans sub-directories for existing `project.json` or `package.json`.
246
+ - Prompts the user with an interactive multi-select checkbox to choose which features will receive E2E testing.
247
+ - Prompts for customizable E2E folder names (e.g. `e2e`, `test/e2e`) and the shared testing library path (`shared/testing`).
248
+
249
+ 2. **Centralized Configuration (`spectra.config.ts`) & App Data (`.testspectra/`)**:
250
+ - `spectra.config.ts` lives exclusively at the root of the monorepo.
251
+ - CLI test runs executed from sub-feature folders automatically traverse up to find the root configuration.
252
+ - Driver caches, binaries, and logs reside in `<root>/.testspectra/`, preventing repository clutter across individual feature folders.
253
+
254
+ 3. **Global Zero-Import Consumption of Shared Library**:
255
+ - Entities placed inside `shared/testing/page-objects/`, `shared/testing/steps/`, `shared/testing/actions/`, and `shared/testing/fixtures/` are automatically aggregated into ambient declarations.
256
+ - Feature test specs consume shared Page Objects (`NavigationBar.goToHome()`), steps (`Step.loginAsAdmin()`), actions (`Spectra.dismissBanner()`), and fixtures (`Fixture.appConfig`) **without a single line of `import` statement**.
257
+
258
+ 4. **Nx Target Execution & Affected Caching**:
259
+ - Each feature E2E folder includes an Nx `project.json`:
260
+ ```json
261
+ {
262
+ "name": "auth-e2e",
263
+ "targets": {
264
+ "e2e": {
265
+ "executor": "nx:run-commands",
266
+ "options": { "command": "spectra run", "cwd": "modules/auth/e2e" },
267
+ "configurations": {
268
+ "android": { "command": "spectra run --target android" },
269
+ "ios": { "command": "spectra run --target ios" },
270
+ "headless": { "command": "spectra run --headless" }
271
+ }
272
+ }
273
+ }
274
+ }
275
+ ```
276
+ - Running `nx run-many -t e2e` executes all feature test suites in parallel.
277
+ 5. **Automatic Architecture Documentation (`ARCHITECTURE.md`)**:
278
+ - Every `spectra init` run produces a comprehensive, project-tailored `ARCHITECTURE.md` file in the root workspace.
279
+ - It documents the generated file map, exact distributed feature paths, shared library resolution, and zero-import mechanics for onboarding engineers.
280
+
281
+ ---
282
+
283
+ ## 6. Development & Verification
217
284
 
218
285
  To verify the CLI and example app:
219
286
  ```bash
220
287
  # Build CLI
221
288
  pnpm --filter @testspectra/cli build
222
289
 
223
- # Initialize and verify example app
224
- cd apps/example-app
225
- ../../cli/bin/spectra.js init
226
- npx tsc -b tsconfig.json
290
+ # Test interactive scaffolding
291
+ npx @testspectra/cli init
292
+ pnpm type-check
227
293
  ```
@@ -190,6 +190,7 @@ export async function initCommand(options = {}) {
190
190
  }
191
191
  cur = path.dirname(cur);
192
192
  }
193
+ const projectName = path.basename(cwd);
193
194
  const cliDepVersion = isInternalWorkspace ? "workspace:*" : cliVersion;
194
195
  // Helper: Copy directory contents recursively
195
196
  function copyRecursive(src, dest, replacements = {}) {
@@ -343,21 +344,102 @@ export async function initCommand(options = {}) {
343
344
  else {
344
345
  rootTsConfig = { files: [], references };
345
346
  }
346
- fs.writeFileSync(rootTsConfigPath, JSON.stringify(rootTsConfig, null, 2), "utf-8");
347
347
  // 6. Generate Ambient Types for Shared + All E2E Feature Directories
348
348
  TypeGenerator.writeDeclarationFiles(cwd);
349
349
  for (const e2eDir of featureE2eDirs) {
350
350
  TypeGenerator.writeDeclarationFiles(e2eDir);
351
351
  }
352
+ // 7. Generate ARCHITECTURE.md in root documenting the exact generated layout
353
+ const archDocContent = `# TestSpectra Enterprise Monorepo Architecture
354
+
355
+ This workspace uses TestSpectra's **"Centralized Configuration, Distributed Implementation"** model for automated cross-platform testing.
356
+
357
+ ---
358
+
359
+ ## 1. Directory & File Overview
360
+
361
+ ### Centralized Root Elements
362
+ - \`./spectra.config.ts\`: Single source of truth for runtime configurations (Base URL, Appium devices, browser targets, timeouts).
363
+ - \`./.testspectra/\`: Centralized app data folder containing driver caches (ChromeDriver, GeckoDriver, Appium), execution logs, and universal ambient types (\`.testspectra/types/\`).
364
+ - \`./nx.json\`: Nx target defaults with execution caching and inputs.
365
+ - \`./pnpm-workspace.yaml\`: Monorepo package glob definitions.
366
+ - \`./tsconfig.json\`: Solution-style TypeScript orchestrator linking all distributed E2E projects and shared libraries.
367
+
368
+ ### Centralized Shared Library (\`./${sharedTestingRelPath}\`)
369
+ Provides cross-feature reusable test entities with **100% zero-import global resolution**:
370
+ - \`page-objects/\`: Shared Page Object models (e.g. NavigationBar, AppHeader).
371
+ - \`steps/\`: Cross-feature business step flows (e.g. \`Step.loginAsAdmin()\`).
372
+ - \`actions/\`: Custom atomic actions (e.g. \`Spectra.dismissBanner()\`).
373
+ - \`fixtures/\`: Common test data and environment configurations (e.g. \`Fixture.appConfig\`).
374
+
375
+ ### Distributed Feature E2E Modules (${featureE2eDirs.length} Features)
376
+ ${featureE2eDirs.map((d) => {
377
+ const rel = path.relative(cwd, d);
378
+ const name = path.basename(path.dirname(d));
379
+ return `- \`./${rel}\` (**${name}**):
380
+ - \`specs/\`: Feature test cases (\`specs/<SuiteName>/<CaseId>/\` for web, android, ios).
381
+ - \`page-objects/\`: Feature-specific Page Objects (e.g. LoginPage, ProductPage).
382
+ - \`project.json\`: Nx targets (\`e2e\`, \`type-check\`) supporting configurations (\`--configuration=android\`, \`--configuration=ios\`, \`--configuration=headless\`).
383
+ - \`tsconfig.json\`: Solution TypeScript config reference.`;
384
+ }).join("\n")}
385
+
386
+ ---
387
+
388
+ ## 2. Zero-Import Consumption Flow
389
+
390
+ \`\`\`
391
+ ┌──────────────────────────────┐ ┌──────────────────────────────┐
392
+ │ shared/testing/page-objects │ │ modules/*/e2e/specs/ │
393
+ │ shared/testing/steps │ ───────► │ (Zero-Import Test Cases) │
394
+ │ shared/testing/actions │ │ - NavigationBar.goToHome() │
395
+ │ shared/testing/fixtures │ │ - Step.loginAsAdmin() │
396
+ └──────────────────────────────┘ │ - Spectra.dismissBanner() │
397
+ └──────────────────────────────┘
398
+ \`\`\`
399
+
400
+ ---
401
+
402
+ ## 3. Running Tests via Nx
403
+
404
+ \`\`\`bash
405
+ # Run all feature E2E suites in parallel
406
+ pnpm nx run-many -t e2e
407
+
408
+ # Run only E2E tests for features changed in PR
409
+ pnpm nx affected -t e2e
410
+
411
+ # Run E2E for a specific feature on Android
412
+ pnpm nx run auth-${e2eFolderName}:e2e --configuration=android
413
+
414
+ # Run type check across all E2E projects
415
+ pnpm nx run-many -t type-check
416
+ # Or standard TypeScript compilation
417
+ pnpm type-check
418
+ \`\`\`
419
+ `;
420
+ fs.writeFileSync(path.join(cwd, "ARCHITECTURE.md"), archDocContent, "utf-8");
421
+ // 8. Safely append to root README.md (do not overwrite existing content)
422
+ const rootReadmePath = path.join(cwd, "README.md");
423
+ const archSection = `\n## E2E Testing Architecture (TestSpectra)\n\nThis workspace uses TestSpectra's **Centralized Configuration, Distributed Implementation** architecture.\nDetailed architecture, folder map, and zero-import mechanics are documented in: \n👉 **[ARCHITECTURE.md](./ARCHITECTURE.md)**\n\n- **Run all E2E tests**: \`pnpm nx run-many -t e2e\`\n- **Run affected E2E tests**: \`pnpm nx affected -t e2e\`\n- **Type-check E2E suites**: \`pnpm type-check\`\n`;
424
+ if (fs.existsSync(rootReadmePath)) {
425
+ const existing = fs.readFileSync(rootReadmePath, "utf-8");
426
+ if (!existing.includes("ARCHITECTURE.md")) {
427
+ fs.appendFileSync(rootReadmePath, archSection, "utf-8");
428
+ }
429
+ }
430
+ else {
431
+ const readmeContent = `# ${projectName}\n\nAutomated cross-platform E2E testing powered by [TestSpectra](https://github.com/testspectra).\n${archSection}`;
432
+ fs.writeFileSync(rootReadmePath, readmeContent, "utf-8");
433
+ }
352
434
  console.log(`\n\x1b[32m[TestSpectra]\x1b[0m Enterprise Nx Monorepo initialized successfully!`);
353
435
  console.log(`\x1b[36m- Centralized Configuration:\x1b[0m ./spectra.config.ts`);
354
436
  console.log(`\x1b[36m- Centralized App Data/Cache:\x1b[0m ./.testspectra/`);
355
437
  console.log(`\x1b[36m- Shared Testing Library:\x1b[0m ./${sharedTestingRelPath}`);
438
+ console.log(`\x1b[36m- Architecture Documentation:\x1b[0m ./ARCHITECTURE.md`);
356
439
  console.log(`\x1b[36m- Initialized Features (${featureE2eDirs.length}):\x1b[0m\n ${featureE2eDirs.map((d) => path.relative(cwd, d)).join("\n ")}`);
357
440
  return;
358
441
  }
359
442
  // --- STANDALONE / DEFAULT PROJECT FLOW ---
360
- const projectName = path.basename(cwd);
361
443
  copyRecursive(templateDir, cwd);
362
444
  if (!isInternalWorkspace) {
363
445
  const pnpmWorkspacePath = path.join(cwd, "pnpm-workspace.yaml");
@@ -367,6 +449,49 @@ export async function initCommand(options = {}) {
367
449
  }
368
450
  }
369
451
  TypeGenerator.writeDeclarationFiles(cwd);
452
+ // Standalone Architecture Documentation
453
+ const standaloneArchDoc = `# TestSpectra Project Architecture
454
+
455
+ This project is built with the TestSpectra testing framework.
456
+
457
+ ## Structure & File Map
458
+ - \`./spectra.config.ts\`: Typed runner configuration.
459
+ - \`./specs/\`: Layered test cases (\`specs/<Suite>/<CaseId>/\` with \`web.test.ts\`, \`android.test.ts\`, \`ios.test.ts\`).
460
+ - \`./page-objects/\`: Page Object models per platform.
461
+ - \`./steps/\`: Business flows accessible globally via \`Step.*\`.
462
+ - \`./actions/\`: Atomic actions accessible globally via \`Spectra.*\`.
463
+ - \`./fixtures/\`: JSON fixtures accessible globally via \`Fixture.*\`.
464
+ - \`./global-hooks/\`: Global suite lifecycle hooks.
465
+ - \`./.testspectra/\`: Auto-generated ambient typings and local runtime cache.
466
+
467
+ ## Execution
468
+ \`\`\`bash
469
+ # Run web test suite
470
+ pnpm test
471
+
472
+ # Run Android / iOS
473
+ pnpm spectra run --target android
474
+ pnpm spectra run --target ios
475
+
476
+ # Type check
477
+ pnpm type-check
478
+ \`\`\`
479
+ `;
480
+ fs.writeFileSync(path.join(cwd, "ARCHITECTURE.md"), standaloneArchDoc, "utf-8");
481
+ // Safely update root README.md (do not overwrite existing content)
482
+ const standaloneReadmePath = path.join(cwd, "README.md");
483
+ const standaloneArchSection = `\n## E2E Testing Architecture (TestSpectra)\n\nDetailed test architecture and folder map are documented in: \n👉 **[ARCHITECTURE.md](./ARCHITECTURE.md)**\n\n- **Run tests**: \`pnpm test\`\n- **Type-check**: \`pnpm type-check\`\n`;
484
+ if (fs.existsSync(standaloneReadmePath)) {
485
+ const existing = fs.readFileSync(standaloneReadmePath, "utf-8");
486
+ if (!existing.includes("ARCHITECTURE.md")) {
487
+ fs.appendFileSync(standaloneReadmePath, standaloneArchSection, "utf-8");
488
+ }
489
+ }
490
+ else {
491
+ const standaloneReadme = `# ${projectName}\n\nTestSpectra automated testing project.\n${standaloneArchSection}`;
492
+ fs.writeFileSync(standaloneReadmePath, standaloneReadme, "utf-8");
493
+ }
370
494
  console.log(`\x1b[32m[TestSpectra]\x1b[0m Initialized project from template successfully!`);
495
+ console.log(`\x1b[32m[TestSpectra]\x1b[0m Generated documentation at ./ARCHITECTURE.md`);
371
496
  console.log(`\x1b[32m[TestSpectra]\x1b[0m Generated ambient multi-platform types in .testspectra/types/`);
372
497
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testspectra/cli",
3
- "version": "1.0.18",
3
+ "version": "1.0.20",
4
4
  "description": "TestSpectra Zero-Config Cross-Platform Test Runner CLI",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",