@nouhouari/conductor-e2e 0.0.0-stage → 0.1.8

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 (101) hide show
  1. package/CHANGELOG.md +228 -0
  2. package/LICENSE +21 -0
  3. package/README.md +138 -2
  4. package/config/environments/default.ts +41 -0
  5. package/config/environments/dev.ts +16 -0
  6. package/config/environments/staging.ts +15 -0
  7. package/config/index.ts +70 -0
  8. package/config/types.ts +94 -0
  9. package/dist/config/environments/default.d.ts +3 -0
  10. package/dist/config/environments/default.d.ts.map +1 -0
  11. package/dist/config/environments/default.js +40 -0
  12. package/dist/config/environments/default.js.map +1 -0
  13. package/dist/config/environments/dev.d.ts +3 -0
  14. package/dist/config/environments/dev.d.ts.map +1 -0
  15. package/dist/config/environments/dev.js +18 -0
  16. package/dist/config/environments/dev.js.map +1 -0
  17. package/dist/config/environments/staging.d.ts +3 -0
  18. package/dist/config/environments/staging.d.ts.map +1 -0
  19. package/dist/config/environments/staging.js +17 -0
  20. package/dist/config/environments/staging.js.map +1 -0
  21. package/dist/config/index.d.ts +7 -0
  22. package/dist/config/index.d.ts.map +1 -0
  23. package/dist/config/index.js +81 -0
  24. package/dist/config/index.js.map +1 -0
  25. package/dist/config/types.d.ts +93 -0
  26. package/dist/config/types.d.ts.map +1 -0
  27. package/dist/config/types.js +3 -0
  28. package/dist/config/types.js.map +1 -0
  29. package/dist/src/drivers/ApiDriver.d.ts +16 -0
  30. package/dist/src/drivers/ApiDriver.d.ts.map +1 -0
  31. package/dist/src/drivers/ApiDriver.js +48 -0
  32. package/dist/src/drivers/ApiDriver.js.map +1 -0
  33. package/dist/src/drivers/DatabaseDriver.d.ts +12 -0
  34. package/dist/src/drivers/DatabaseDriver.d.ts.map +1 -0
  35. package/dist/src/drivers/DatabaseDriver.js +15 -0
  36. package/dist/src/drivers/DatabaseDriver.js.map +1 -0
  37. package/dist/src/drivers/FlutterDesktopDriver.d.ts +139 -0
  38. package/dist/src/drivers/FlutterDesktopDriver.d.ts.map +1 -0
  39. package/dist/src/drivers/FlutterDesktopDriver.js +445 -0
  40. package/dist/src/drivers/FlutterDesktopDriver.js.map +1 -0
  41. package/dist/src/drivers/MaestroDriver.d.ts +19 -0
  42. package/dist/src/drivers/MaestroDriver.d.ts.map +1 -0
  43. package/dist/src/drivers/MaestroDriver.js +144 -0
  44. package/dist/src/drivers/MaestroDriver.js.map +1 -0
  45. package/dist/src/drivers/WebDriver.d.ts +21 -0
  46. package/dist/src/drivers/WebDriver.d.ts.map +1 -0
  47. package/dist/src/drivers/WebDriver.js +57 -0
  48. package/dist/src/drivers/WebDriver.js.map +1 -0
  49. package/dist/src/hooks/browser.hooks.d.ts +2 -0
  50. package/dist/src/hooks/browser.hooks.d.ts.map +1 -0
  51. package/dist/src/hooks/browser.hooks.js +15 -0
  52. package/dist/src/hooks/browser.hooks.js.map +1 -0
  53. package/dist/src/hooks/database.hooks.d.ts +2 -0
  54. package/dist/src/hooks/database.hooks.d.ts.map +1 -0
  55. package/dist/src/hooks/database.hooks.js +11 -0
  56. package/dist/src/hooks/database.hooks.js.map +1 -0
  57. package/dist/src/hooks/desktop.hooks.d.ts +2 -0
  58. package/dist/src/hooks/desktop.hooks.d.ts.map +1 -0
  59. package/dist/src/hooks/desktop.hooks.js +15 -0
  60. package/dist/src/hooks/desktop.hooks.js.map +1 -0
  61. package/dist/src/hooks/flutterDesktop.hooks.d.ts +2 -0
  62. package/dist/src/hooks/flutterDesktop.hooks.d.ts.map +1 -0
  63. package/dist/src/hooks/flutterDesktop.hooks.js +26 -0
  64. package/dist/src/hooks/flutterDesktop.hooks.js.map +1 -0
  65. package/dist/src/hooks/index.d.ts +6 -0
  66. package/dist/src/hooks/index.d.ts.map +1 -0
  67. package/dist/src/hooks/index.js +25 -0
  68. package/dist/src/hooks/index.js.map +1 -0
  69. package/dist/src/hooks/maestro.hooks.d.ts +2 -0
  70. package/dist/src/hooks/maestro.hooks.d.ts.map +1 -0
  71. package/dist/src/hooks/maestro.hooks.js +8 -0
  72. package/dist/src/hooks/maestro.hooks.js.map +1 -0
  73. package/dist/src/index.d.ts +21 -0
  74. package/dist/src/index.d.ts.map +1 -0
  75. package/dist/src/index.js +30 -0
  76. package/dist/src/index.js.map +1 -0
  77. package/dist/src/pages/BasePage.d.ts +11 -0
  78. package/dist/src/pages/BasePage.d.ts.map +1 -0
  79. package/dist/src/pages/BasePage.js +22 -0
  80. package/dist/src/pages/BasePage.js.map +1 -0
  81. package/dist/src/scenarios/RemoteScenarioFetcher.d.ts +51 -0
  82. package/dist/src/scenarios/RemoteScenarioFetcher.d.ts.map +1 -0
  83. package/dist/src/scenarios/RemoteScenarioFetcher.js +162 -0
  84. package/dist/src/scenarios/RemoteScenarioFetcher.js.map +1 -0
  85. package/dist/src/scenarios/cli.d.ts +3 -0
  86. package/dist/src/scenarios/cli.d.ts.map +1 -0
  87. package/dist/src/scenarios/cli.js +26 -0
  88. package/dist/src/scenarios/cli.js.map +1 -0
  89. package/dist/src/support/logger.d.ts +3 -0
  90. package/dist/src/support/logger.d.ts.map +1 -0
  91. package/dist/src/support/logger.js +16 -0
  92. package/dist/src/support/logger.js.map +1 -0
  93. package/dist/src/support/retry.d.ts +7 -0
  94. package/dist/src/support/retry.d.ts.map +1 -0
  95. package/dist/src/support/retry.js +21 -0
  96. package/dist/src/support/retry.js.map +1 -0
  97. package/dist/src/world/ConductorWorld.d.ts +39 -0
  98. package/dist/src/world/ConductorWorld.d.ts.map +1 -0
  99. package/dist/src/world/ConductorWorld.js +112 -0
  100. package/dist/src/world/ConductorWorld.js.map +1 -0
  101. package/package.json +81 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,228 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ### Fixed
10
+
11
+ - **`release-java.yml` no longer fails after a successful Central publish** — bumped `central-publishing-maven-plugin` 0.7.0 → 0.11.0. 0.7.0 could not parse the `warnings` field the Central Portal now returns while polling deployment status, so the job failed even though `conductor-java 0.2.0` was published.
12
+
13
+ ## [conductor-e2e 0.1.8] — 2026-10-02
14
+
15
+ ### Fixed
16
+
17
+ - **npmjs.org publish actually targets npmjs.org** — the second `setup-node` step in `release.yml` and `release-mcp.yml` now sets `scope: '@nouhouari'`. Without it, the `@nouhouari:registry=https://npm.pkg.github.com/` line written by the GitHub Packages step survived and overrode `--registry`, so the "Publish to npmjs.org" step re-published to GitHub Packages with the npm token and failed with E401. `conductor-e2e` 0.1.7 and `conductor-mcp` 0.2.1/0.2.2 therefore never reached npmjs.org; 0.1.8 and 0.2.3 are the first versions there.
18
+
19
+ ## [conductor-java 0.2.0] — 2026-10-02
20
+
21
+ ### Changed
22
+
23
+ - **Published to Maven Central under a new groupId** — the Java port is now `io.github.nouhouari.conductor:conductor-core` (was `com.nouhouari.conductor`, GitHub Packages only). Consumers no longer need a `<repositories>` entry or a `read:packages` token. Java package names (`com.nouhouari.conductor.*`) are unchanged.
24
+ - **`release-java.yml` publishes to Maven Central** — on `java-v*` tags it verifies the tag matches `java/pom.xml` (and refuses `-SNAPSHOT`), builds and tests `conductor-core`, attaches its jars to a GitHub Release, and runs `mvn -P release deploy`. Needs the `MAVEN_CENTRAL_USERNAME`, `MAVEN_CENTRAL_PASSWORD`, `MAVEN_GPG_PRIVATE_KEY` and `MAVEN_GPG_PASSPHRASE` repository secrets.
25
+ - `java/pom.xml` gained the metadata Central requires (url, license, developers, scm) and a `release` profile: sources + javadoc jars, GPG signing, and `central-publishing-maven-plugin`. The GitHub Packages `<distributionManagement>` was removed.
26
+
27
+ ### Added
28
+
29
+ - **CI coverage for the Java port** — `ci.yml` gained a `java` job (temurin JDK 21) that builds and unit-tests `conductor-core`, compiles `conductor-example`'s step definitions and page objects, and runs a Cucumber JVM `--dry-run` over `example/features` with the real glue so undefined/ambiguous steps fail the build. The example's suites need real browsers/devices and are never executed on a hosted runner.
30
+ - `java/README.md` gained a "CI & Releasing" section.
31
+
32
+ ## [conductor-mcp 0.2.3] — 2026-10-02
33
+
34
+ ### Changed
35
+
36
+ - `init_project` pins `@nouhouari/conductor-e2e` `^0.1.8`, the first version published to npmjs.org.
37
+ - `bin` path normalised to `dist/cli.js` (npm was auto-correcting `./dist/cli.js` on publish).
38
+
39
+ - **Java projects resolve `conductor-core` from Maven Central** — `init_project` with `language: "java"` now generates a `pom.xml` depending on `io.github.nouhouari.conductor:conductor-core:0.2.0`, with no GitHub Packages `<repositories>` block or `~/.m2/settings.xml` token step.
40
+ - **Docs: npm install** — `mcp/README.md` now installs `@nouhouari/conductor-mcp` from the public npm registry; the GitHub Packages `.npmrc` / `read:packages` setup is no longer required.
41
+
42
+ ## [conductor-e2e 0.1.7] — 2026-10-01
43
+
44
+ ### Changed
45
+
46
+ - **Release workflow publishes to npmjs.org** — `release.yml` now publishes `@nouhouari/conductor-e2e` to the public npm registry (via the `NPM_TOKEN` repository secret) in addition to GitHub Packages.
47
+ - **Idempotent release publishes** — publish steps in `release.yml` and `release-mcp.yml` skip versions already present on the target registry, so a partially failed release can be re-run.
48
+
49
+ ## [conductor-mcp 0.2.2] — 2026-10-01
50
+
51
+ ### Changed
52
+
53
+ - Re-release to publish `@nouhouari/conductor-mcp` to npmjs.org with the idempotent release workflow.
54
+
55
+ ## [conductor-mcp 0.2.1] — 2026-09-04
56
+
57
+ ### Changed
58
+
59
+ - **Release workflow publishes to npmjs.org** — `release-mcp.yml` now publishes `@nouhouari/conductor-mcp` to the public npm registry (via the `NPM_TOKEN` repository secret) in addition to GitHub Packages, so `npx @nouhouari/conductor-mcp` works without a GitHub Packages `.npmrc`.
60
+
61
+ - **Docs: GitHub Copilot CLI wire-up for `conductor-mcp`** — `mcp/README.md` and `docs/USER_GUIDE.md` now document the `~/.copilot/mcp-config.json` entry (including the Copilot-specific `"type": "stdio"` and `"tools"` allow-list) alongside the existing Claude Code / Cursor / Continue instructions. The user guide's setup snippet was also corrected to the published package name `@nouhouari/conductor-mcp` and now notes the GitHub Packages `.npmrc` requirement and Java target-project support.
62
+
63
+ ## [conductor-java 0.1.0] — 2026-07-30
64
+
65
+ First release of the Java port. Published to GitHub Packages as `com.nouhouari.conductor:conductor-core`.
66
+
67
+ ### Added
68
+
69
+ - **`conductor-core`** — Java/Cucumber-JVM/Playwright port of the framework, developed alongside the TypeScript implementation and driving the *same* Gherkin feature files under `example/features`.
70
+ - `ConductorWorld` with lazily-instantiated drivers, shared test data, and picocontainer-based injection into step definitions.
71
+ - Drivers: `WebDriver` (Playwright), `ApiDriver` (Playwright `APIRequestContext`), `MaestroDriver` (Maestro CLI), `JavaFxDriver` (fxagent HTTP API), `FlutterDesktopDriver` (Dart VM service), and the abstract `DatabaseDriver`.
72
+ - Tag-driven Cucumber-JVM hooks mirroring the TS `@web` / `@mobile` / `@flutter-desktop` / `@database` lifecycle, plus `BasePage`.
73
+ - YAML `ConfigLoader` with the TS precedence order (`config/default.yml` → `config/local-overrides.yml` → `config/${TEST_ENV}.yml` → environment variables) and the same env-var names.
74
+ - **`conductor-example`** (not published) — ported step definitions and page objects, plus one JUnit 5 `@Suite` class per platform tag, the Java equivalent of `example/cucumber.js`'s named profiles.
75
+
76
+ ### Notes
77
+
78
+ - Validated end-to-end against the real apps, no mocks: `ApiSuiteTest` 8/8, `WebSuiteTest` 9/9, `DesktopSuiteTest` 8/8, `FlutterDesktopSuiteTest` 5/5, `MobileSuiteTest` 8/8, `CrossPlatformSuiteTest` 10/10.
79
+ - `JavaFxDriver` targets `fxagent.jar` v1.0.0 (package `com.hin.fxagent`); waits are polled client-side via `POST /api/v1/elements/query` because the agent's `/elements/wait` cannot express `hidden`/absent states.
80
+ - The `RemoteScenarioFetcher` / `conductor-fetch-features` CLI equivalent is intentionally not ported.
81
+
82
+ ## [conductor-mcp 0.2.0] — 2026-07-30
83
+
84
+ ### Added
85
+
86
+ - **Java project support** — every project-aware tool now detects whether the working directory belongs to a TypeScript project (`cucumber.js`) or a Java/Maven project (`pom.xml` + Cucumber glue under `src/test/java`) and adapts accordingly. When both are found, the closest project to the working directory wins.
87
+ - `list_steps` parses `@Given` / `@When` / `@Then` annotations in `.java` sources.
88
+ - `list_page_objects` parses Java page-object classes and their public methods.
89
+ - `scaffold_step_def` / `scaffold_page_object` emit Java sources into the resolved glue and page packages.
90
+ - `dry_run_scenario` runs the Cucumber JVM CLI (`mvn test-compile` → `dependency:build-classpath` → `io.cucumber.core.cli.Main --dry-run`) and reports undefined/ambiguous steps. The CLI is used instead of `mvn test` because JUnit Platform suite `@ConfigurationParameter` values override `-D` system properties.
91
+ - `get_conductor_api` accepts `language: "java"` and returns the Java API surface for all 8 surfaces.
92
+ - **`init_project` accepts `language: "java"`** — bootstraps a Maven project (pom, JUnit Platform suites, `conductor.yml`, sample feature/step-def/page object, README, `.gitignore`) with configurable `groupId`, `artifactId` and `basePackage`. The `flutter-desktop` platform is now selectable.
93
+
94
+ ### Fixed
95
+
96
+ - **`wait_for_desktop_element` with `state: "hidden"` (or `disabled`) always errored** — it called the fxagent `POST /api/v1/elements/wait` endpoint, which returns HTTP 500 when nothing matches the selector, making "wait for this to disappear" impossible. The tool now polls `POST /api/v1/elements/query` client-side and reports the last-seen element on timeout. Supported states: `visible`, `hidden`, `enabled`, `disabled`, `exists`.
97
+
98
+ ## [0.1.6] — 2026-06-21
99
+
100
+ ### Added
101
+
102
+ - **Remote scenario sourcing** — opt-in mode to run Cucumber scenarios fetched from the requ scenario API (`GET /api/scenarios`) instead of the local `features/` folder. The local filesystem flow is unchanged and remains the default.
103
+ - `fetchScenarios()` / `reconstructFeatureFiles()` (exported from `src/scenarios/RemoteScenarioFetcher.ts`) — fetch scenarios with server-side filters (`project`, `story`, `requirement`, `phase`, `mode`, `tags`, `feature`, `q`, `valid`) and reconstruct them into `.feature` files grouped by feature, recovering feature-level tags, inserting `Background:`, and preserving `Examples:`.
104
+ - `conductor-fetch-features` bin (`src/scenarios/cli.ts`) — prefetch step that writes the reconstructed features to disk.
105
+ - New optional `remoteScenarios` config block with `REMOTE_SCENARIOS_*` env-var overrides.
106
+ - Example: new `remote` cucumber profile and `fetch:remote` / `test:remote` / `test:remote:dry` scripts.
107
+ - **New exported types**: `RemoteScenariosConfig`, `RemoteScenariosFilters`, `RemoteScenarioSummary`, `ReconstructResult`
108
+
109
+ ## [conductor-mcp 0.1.6] — 2026-06-21
110
+
111
+ ### Added
112
+
113
+ - **`init_project` scaffolds the remote scenario mode (opt-in)** — newly bootstrapped projects now include the `remote` cucumber profile, the `fetch:remote` / `test:remote` / `test:remote:dry` scripts, a commented `REMOTE_SCENARIOS_*` section in `.env.example`, `.remote-features/` in `.gitignore`, and a "Remote Scenarios" section in the README. Local feature files remain the default; the remote profile is inert until `npm run test:remote` is run. No new init parameter or prompt.
114
+ - Bootstrapped projects now depend on `@nouhouari/conductor-e2e@^0.1.6` (provides the `conductor-fetch-features` bin used by `fetch:remote`).
115
+
116
+ ## [0.1.5] — 2026-06-19
117
+
118
+ ### Added
119
+
120
+ - **`FlutterDesktopDriver`** — 9 new methods expanding the gesture and query API:
121
+ - `doubleTap(finder, timeoutMs?)` — double-tap gesture (`double_tap` command)
122
+ - `longPress(finder, timeoutMs?)` — long-press gesture (`long_press` command)
123
+ - `scroll(finder, dx, dy, durationMs?, frequency?, timeoutMs?)` — scroll a `Scrollable` widget by pixel offset
124
+ - `scrollIntoView(finder, alignment?, timeoutMs?)` — scroll until a widget is visible; `alignment` 0.0 = top, 0.5 = center, 1.0 = bottom
125
+ - `clearText(finder, timeoutMs?)` — clear a text field (enables text-entry emulation, taps to focus, sends empty string)
126
+ - `isVisible(finder, timeoutMs?)` → `boolean` — non-throwing visibility probe; returns `true`/`false` instead of throwing (default probe timeout 500 ms)
127
+ - `getOffset(finder, offsetType?, timeoutMs?)` → `{ dx, dy }` — get widget screen coordinates (`get_offset` command); `offsetType`: `'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'center'`
128
+ - `waitForCondition(condition, timeoutMs?)` — wait for the app to reach a quiescent state, the Flutter equivalent of `page.waitForLoadState()`; conditions: `'NoPendingFrames'`, `'NoTransientCallbacks'`, `'FirstFrameRasterized'`
129
+ - `setFrameSync(enabled, timeoutMs?)` — pause/resume Flutter's frame-sync during heavy animations, mirrors disabling CSS transitions in web tests
130
+ - **`FlutterDesktopDriver.connect(vmServiceUrl, timeoutMs?)`** — connect to an already-running Flutter app via its Dart VM service URL, without spawning a process. Enables use on Android (after `adb forward`), iOS (after `iproxy`), and Windows/Linux desktop. Accepts both HTTP (`http://localhost:PORT/TOKEN/`) and WebSocket (`ws://localhost:PORT/TOKEN/ws`) form. `isLaunched` now returns `true` after `connect()` as well as `launch()`.
131
+ - **New exported types**: `OffsetType`, `Offset`, `WaitCondition`
132
+ - **Example step definitions** for all new `FlutterDesktopDriver` methods
133
+
134
+ ## [conductor-mcp 0.1.4] — 2026-06-19
135
+
136
+ ### Added
137
+
138
+ - **`@nouhouari/conductor-mcp`**: Added `flutter` API surface to the built-in reference (`get_api_reference`, `list_steps` surface filter). Documents the full `FlutterDesktopDriver` public API — lifecycle (`launch`, `connect`, `close`), finders, gesture/interaction methods (`tap`, `doubleTap`, `longPress`, `enterText`, `clearText`, `scroll`, `scrollIntoView`), query methods (`getText`, `getOffset`, `isVisible`), wait methods (`waitFor`, `waitForAbsent`, `waitForCondition`), and advanced utilities (`requestData`, `setFrameSync`, `takeScreenshot`). Also documents the `@flutter-desktop` tag hook and `FlutterDesktopConfig`. Updated the `world` surface to include the `flutterDesktop` and `isFlutterDesktopLaunched` getters.
139
+
140
+ ## [conductor-mcp 0.1.2] — 2026-06-19
141
+
142
+ ### Changed
143
+
144
+ - **`@nouhouari/conductor-mcp`**: Renamed package from `conductor-mcp` to `@nouhouari/conductor-mcp` and switched registry from npm to GitHub Packages. Consumers should update their install command to `npm install @nouhouari/conductor-mcp` and configure `@nouhouari:registry=https://npm.pkg.github.com` in their `.npmrc`.
145
+
146
+ ## [0.1.3] — 2026-06-19
147
+
148
+ ### Changed
149
+
150
+ - **`conductor-e2e`**: Renamed package to `@nouhouari/conductor-e2e` and switched registry from npm to GitHub Packages. Update installs to `npm install @nouhouari/conductor-e2e` with `@nouhouari:registry=https://npm.pkg.github.com` in `.npmrc`.
151
+
152
+ ### Added
153
+
154
+ - **`FlutterDesktopDriver`** — new TypeScript driver that launches a Flutter macOS `.app` binary, connects to its Dart VM service via WebSocket, and issues `ext.flutter.driver` JSON-RPC commands. Public API: `launch()`, `close()`, `tap(finder)`, `enterText(finder, text)`, `getText(finder)`, `waitFor(finder)`, `waitForAbsent(finder)`, `requestData(message)`, `takeScreenshot(name)`.
155
+ - **`requestData()` action dispatch pattern** — primary mechanism for invoking app-side actions (toggle, edit, delete, etc.) via `enableFlutterDriverExtension`. Bypasses `hitTestable()` which never resolves for widgets inside a `ListView` on macOS desktop.
156
+ - **`@flutter-desktop` tag** — new tag-driven hook that logs driver availability before the scenario and takes a failure screenshot + closes the driver after. Lives in `src/hooks/flutterDesktop.hooks.ts`.
157
+ - **`FlutterDesktopConfig`** — new config key controlling the macOS `.app` binary path, Dart VM service port, and screenshot output directory.
158
+ - **`apps/mobile/lib/main_test.dart`** — Flutter test entry point that wires `enableFlutterDriverExtension` to the action registry via JSON dispatch.
159
+ - **`apps/mobile/lib/driver_actions.dart`** — app-side action registry for `toggleTodo`, `editTodoTitle`, `deleteTodo`, `setDialogText`, `refresh`, and `waitUntilLoaded`.
160
+ - **macOS `DebugProfile.entitlements`** — adds `network.client` entitlement so the sandboxed profile build can reach the local API server.
161
+ - **Flutter Desktop example scenarios** — feature file, step definitions, cucumber profile (`flutter-desktop`), and `npm run test:flutter-desktop` script covering home screen, create, toggle, edit, and delete (5 scenarios / 24 steps).
162
+ - **`flutter:build:macos` script** — builds the Flutter macOS app in profile mode with `main_test.dart` as the entry point and injects `API_BASE_URL` and `DISABLE_SWIPE_GESTURES` dart-defines.
163
+
164
+ ### Fixed
165
+
166
+ - macOS sandbox blocked outgoing HTTP from the profile build (missing `network.client` entitlement).
167
+ - Race condition between `initState _loadTodos()` and test setup — resolved via `waitUntilLoaded` requestData action.
168
+ - Flutter driver touch events do not fire `onPressed` on macOS desktop — bypassed via `requestData`.
169
+ - `TestTextInput` mock `_client` is null on macOS — text is now set directly on the controller.
170
+
171
+ ## [conductor-mcp 0.1.1] — 2026-05-29
172
+
173
+ ### Fixed
174
+
175
+ - **conductor-mcp**: Quote handling in `scaffold_page_object`, `scaffold_step_def`, and `scaffold_maestro_flow`. Locator selectors like `role=textbox[name='Title']`, step patterns containing apostrophes (`I don't see {string}`), and Maestro values containing `"` were dropped verbatim into single-quoted JS literals or YAML scalars, producing broken source. All three sites now use `JSON.stringify`, which selects the quote style and escapes special characters. Fixes #1.
176
+
177
+ ### Added
178
+
179
+ - **conductor-mcp@0.1.0** — Model Context Protocol (stdio) server for AI-assisted E2E test authoring. Exposes 12 tools across discovery (list steps, page objects, flows, features), scaffolding (bootstrap new projects, create features/steps/pages/flows), and validation (dry-run scenarios). Lets Claude Code, Cursor, and Continue users bootstrap a Conductor project or add tests without leaving their editor. Versioned independently on `mcp-v*` tag prefix.
180
+ - **conductor-mcp**: Discovery/scaffolding/validation tools now accept an optional `projectPath` argument so the AI can point the server at a specific Conductor project. When omitted, `resolveProjectContext` now also walks **down** one level through common subdirs (`tests/`, `e2e/`, `e2e-conductor/`, `qa/`, …) — makes the server usable in monorepos where the test project lives below the workspace root.
181
+ - **conductor-mcp**: Bootstrap template `cucumber.js` now includes the `summary` formatter alongside `progress-bar`, so a failing run prints the actual error instead of three opaque lines.
182
+ - **conductor-mcp**: Scaffolded `api.steps.ts` now ships a working `POST` example demonstrating the correct `ApiDriver.post(url, body, options?)` signature — preempts users reaching for the Playwright `{ data: ... }` shape.
183
+ - **conductor-mcp**: `scaffold_step_def` now derives parameter identifiers correctly via a three-tier strategy: (1) explicit `paramNames` if supplied, (2) **TypeScript AST walk** of the body — parses with `ts.createSourceFile` and classifies each `Identifier` by its parent node, so property keys in object literals (`{ email: ... }`), member-access names (`account.email`), declarations (`const`/`let`/`var`/parameters/destructuring), labels, and type-position references are all correctly excluded; shorthand property assignments (`{ password }`) are recognized as references; (3) generic `value`/`value2`/`count` as last resort. The earlier regex heuristic mistook property keys for references and dropped identifiers inside template-literal interpolations — both blockers reported in dogfood. `typescript` is now a runtime dep of `conductor-mcp` (added to the published package).
184
+ - **conductor-mcp**: `scaffold_page_object` accepts per-method `body` (in addition to `signature`), so users can ship working method implementations instead of `// TODO` stubs. The renderer no longer adds `async` to methods with non-Promise return types like `Locator`, fixing TS2326 errors on common page-object patterns.
185
+ - **conductor-mcp**: Scaffolded `tsconfig.json` now includes `"DOM"` in `lib`, so step definitions reaching `localStorage` / `Storage` / `Window` via `page.evaluate(...)` type-check correctly.
186
+ - **conductor-mcp**: Scaffolded `cucumber.js` now loads `support/**/*.ts` between the framework hooks and step definitions, and `init_project` scaffolds a `support/timeout.ts` that bumps Cucumber's default 5-second step timeout to 30 seconds — fixes spurious timeouts on real browser/app/HTTP steps.
187
+ - **conductor-mcp**: `init_project.includeSamples` now defaults to `false`. The previous `true` default left placeholder `example.feature` files in every project, surfacing as undefined-scenario noise in `npm test`. Real scenarios should come from `scaffold_feature` / `scaffold_step_def`. Set `includeSamples: true` explicitly only when the user wants a runnable demo.
188
+ - **conductor-mcp**: `init_project` accepts an optional `webBaseUrl` so the user's target URL ends up in `.env.example` directly. The tool description teaches the AI to ask the user for this during setup; if no URL is provided, the project uses `http://localhost:3000` as a safe default.
189
+ - **conductor-mcp**: New tool `remove_samples` — deletes the bootstrap placeholder files (`example.feature`, sample step-defs, `ExamplePage.ts`, sample Maestro flows). Only deletes files whose content is byte-equivalent to the original sample, so user edits are preserved (pass `force: true` to override). Optional `platforms` arg restricts the scope. Empty directories left behind are removed too. Total tool count is now **13**.
190
+
191
+ ## [0.1.2] — 2026-05-29
192
+
193
+ ### Changed
194
+
195
+ - **`conductor-e2e`**: `loadConfig()` now calls `import 'dotenv/config'` at module load, so a project's `.env` file is read automatically. Previously the scaffold wrote `.env.example` and the README referenced it, but nothing actually loaded it.
196
+ - **`conductor-e2e`**: Default `api.baseUrl` is now `http://localhost:3000` (no `/api` suffix). Step definitions write the full path including any `/api/...` prefix, avoiding the previous `/api/api/...` collision. `.env.example` updated accordingly. **Migration**: if your step defs wrote `${baseUrl}/todos` expecting `/api/` to be baked into baseUrl, prepend `/api/` to those URLs (or set `API_BASE_URL=http://localhost:3000/api` in your `.env` to keep the old behavior).
197
+
198
+ ### Added
199
+
200
+ - **`conductor-e2e`**: `dotenv` is now a runtime dependency.
201
+
202
+ ## [0.1.1] — 2026-05-29
203
+
204
+ ### Changed
205
+
206
+ - **Renamed npm package from `conductor` to `conductor-e2e`.** The name `conductor` is taken on the npm registry by an unrelated project; v0.1.0 was tagged but could not be published. v0.1.1 is the first version published to npm. Consumers should `npm install conductor-e2e` and import from `'conductor-e2e'`.
207
+
208
+ ## [0.1.0] — 2026-05-29
209
+
210
+ ### Added
211
+
212
+ - `ConductorWorld` — Cucumber `World` subclass that lazily instantiates web/api/maestro/desktop/database drivers
213
+ - `WebDriver` — Playwright browser lifecycle (chromium / firefox / webkit), failure screenshots
214
+ - `ApiDriver` — Playwright `APIRequestContext` wrapper, optional cookie sharing with web context
215
+ - `MaestroDriver` — spawns Maestro CLI for Flutter / native mobile testing; live stdout streaming via `DEBUG_MAESTRO`; auto-retry with `--reinstall-driver` on gRPC `UNAVAILABLE`; adb-based screenshots
216
+ - `JavaFxDriver` integration via `javafx-driver@^0.2.2` for desktop JavaFX app automation
217
+ - `DatabaseDriver` — abstract class; users register their own adapter via `world.setDb(adapter)`
218
+ - `BasePage` — Playwright page object base class with `navigate()`, `waitForLoad()`, `getTitle()`
219
+ - Tag-driven hooks: `@web`, `@mobile`, `@desktop`, `@database`, `@cross-platform`
220
+ - Environment config system with overlays (`default` / `dev` / `staging`) and env var overrides (`WEB_BASE_URL`, `API_BASE_URL`, `HEADLESS`, `BROWSER`, `MAESTRO_DEVICE`)
221
+ - Pino-based structured logger
222
+ - `retry()` helper with fixed/exponential backoff
223
+ - Allure reporting integration via `allure-cucumberjs`
224
+ - Example project (`example/`) demonstrating web + API + mobile + desktop + cross-platform scenarios
225
+ - Sample apps under test (`apps/mobile`, `apps/desktop`, `apps/server`)
226
+ - GitHub Actions CI (build, type-check, dry-run scenarios)
227
+ - GitHub Actions release pipeline (tag-triggered, builds, creates GitHub release, publishes to npm with provenance)
228
+ - [User Guide](docs/USER_GUIDE.md) covering project bootstrap, configuration, all platforms, Allure, CI/CD, troubleshooting
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nourreddine Houari
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,139 @@
1
- # Temporary Holding Version
1
+ # Conductor
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![CI](https://github.com/nouhouari/conductor/actions/workflows/ci.yml/badge.svg)](https://github.com/nouhouari/conductor/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/conductor-e2e.svg?label=conductor-e2e)](https://www.npmjs.com/package/conductor-e2e)
5
+ [![npm version](https://img.shields.io/npm/v/conductor-mcp.svg?label=conductor-mcp)](https://www.npmjs.com/package/conductor-mcp)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
+
8
+ A multi-platform E2E test framework where **one Cucumber scenario** can drive a **web browser**, a **REST API**, a **Flutter mobile app**, a **Flutter desktop app** (macOS), a **JavaFX desktop app**, and a **database** — all from TypeScript.
9
+
10
+ ```gherkin
11
+ @cross-platform
12
+ Scenario: Todo created on web appears on the Flutter mobile app
13
+ Given I am on the todo web application
14
+ When I log in as "user@example.com" with password "secret"
15
+ And I create a todo titled "E2E Cross Platform"
16
+ Then the todo "E2E Cross Platform" appears on the web dashboard
17
+ And the API should return the todo "E2E Cross Platform" with status "open"
18
+ And the Flutter app should display "E2E Cross Platform" in the todo list
19
+ ```
20
+
21
+ ## Stack
22
+
23
+ | Concern | Technology |
24
+ |---|---|
25
+ | BDD runner | [`@cucumber/cucumber`](https://github.com/cucumber/cucumber-js) v11 |
26
+ | Web automation | [Playwright](https://playwright.dev) |
27
+ | API testing | Playwright `APIRequestContext` |
28
+ | Mobile automation | [Maestro CLI](https://maestro.mobile.dev) (Flutter / native) |
29
+ | Desktop automation (Flutter) | Dart VM service / `ext.flutter.driver` JSON-RPC (macOS) |
30
+ | Desktop automation (JavaFX) | [`javafx-driver`](https://www.npmjs.com/package/javafx-driver) |
31
+ | Database | Plugin interface (bring your own adapter) |
32
+ | Reporting | [Allure](https://allurereport.org/) (`allure-cucumberjs`) |
33
+
34
+ ## Quick Start
35
+
36
+ ```bash
37
+ npm install conductor-e2e
38
+ ```
39
+
40
+ See the [**User Guide**](docs/USER_GUIDE.md) for a step-by-step walkthrough of bootstrapping a new E2E project from scratch.
41
+
42
+ ## Why Conductor?
43
+
44
+ Most E2E frameworks pick one platform. When your product lives on multiple platforms — a web dashboard, a mobile app, a REST API, a desktop client — you end up with **N parallel test suites** that can't share scenarios, page objects, or data lifecycle.
45
+
46
+ Conductor unifies them behind a single [`ConductorWorld`](src/world/ConductorWorld.ts):
47
+
48
+ ```typescript
49
+ async function (this: ConductorWorld) {
50
+ await this.web.launch(); // Playwright browser
51
+ await this.page.goto('/login'); // active page
52
+ await this.api.post('/todos', { title: ... }); // shared HTTP client
53
+ await this.maestro.runOrThrow('verify-todo'); // Flutter mobile flow
54
+ await this.flutterDesktop.tap('addButton'); // Flutter desktop (macOS)
55
+ await this.fx.locator('#save-btn').click(); // JavaFX desktop
56
+ await this.db.query('SELECT ...'); // your adapter
57
+ }
58
+ ```
59
+
60
+ Drivers are lazily instantiated. Tag-driven hooks manage their lifecycle:
61
+
62
+ | Tag | Effect |
63
+ |---|---|
64
+ | `@web` / `@cross-platform` | Launches browser, screenshots failures, closes |
65
+ | `@mobile` / `@cross-platform` | Targets the configured Maestro device |
66
+ | `@flutter-desktop` | Launches Flutter macOS app, screenshots failures, closes |
67
+ | `@desktop` / `@cross-platform` | Launches JavaFX app via agent JAR, closes |
68
+ | `@database` / `@cross-platform` | Connects DB before, disconnects after |
69
+
70
+ ## Project Structure
71
+
72
+ ```
73
+ conductor/
74
+ ├── src/ Framework library
75
+ │ ├── drivers/ WebDriver, ApiDriver, MaestroDriver, DatabaseDriver
76
+ │ ├── hooks/ Tag-driven Before/After hooks
77
+ │ ├── pages/ BasePage to extend
78
+ │ ├── world/ ConductorWorld (Cucumber World subclass)
79
+ │ └── support/ Logger, retry helpers
80
+ ├── config/ Environment configs (default/dev/staging)
81
+ ├── example/ Working multi-platform example project
82
+ ├── apps/ Sample apps under test
83
+ │ ├── mobile/ Flutter todo app (Android + macOS desktop)
84
+ │ ├── desktop/ JavaFX todo app
85
+ │ └── server/ Express server + web UI + REST API
86
+ ├── docs/ User guide, API docs
87
+ └── docker-compose.yml PostgreSQL for the example server
88
+ ```
89
+
90
+ ## Running the Example
91
+
92
+ ```bash
93
+ # 1. Start PostgreSQL + Express server
94
+ docker compose up -d
95
+ cd apps/server && npm start &
96
+
97
+ # 2. Run all scenarios except mobile (no device required)
98
+ cd example
99
+ npx cucumber-js --tags 'not @mobile' \
100
+ --require-module ts-node/register \
101
+ --require-module tsconfig-paths/register \
102
+ --require '../src/hooks/index.ts' \
103
+ --require 'step-definitions/**/*.ts' \
104
+ --format progress --format allure-cucumberjs/reporter \
105
+ features/**/*.feature
106
+
107
+ # 3. Open the Allure report
108
+ npm run report && npm run report:open
109
+ ```
110
+
111
+ For mobile, Flutter Desktop, and JavaFX desktop, see [docs/USER_GUIDE.md](docs/USER_GUIDE.md).
112
+
113
+ ### Flutter Desktop (macOS)
114
+
115
+ ```bash
116
+ # Build the test entry point (from repo root)
117
+ npm run flutter:build:macos
118
+
119
+ # Run Flutter Desktop scenarios
120
+ cd example
121
+ npm run test:flutter-desktop
122
+ ```
123
+
124
+ The build uses `lib/main_test.dart` as the entry point (which wires `enableFlutterDriverExtension`) and sets `DISABLE_SWIPE_GESTURES=true` to enable the AppBar Add button and the app-side action registry used by `requestData()`.
125
+
126
+ ## Documentation
127
+
128
+ - [**User Guide**](docs/USER_GUIDE.md) — bootstrap a new E2E project, write scenarios, run tests
129
+ - [**conductor-mcp**](mcp/README.md) — AI-assisted test authoring for GitHub Copilot CLI, Claude Code, Cursor, Continue
130
+ - [**Architecture**](CLAUDE.md) — framework internals (driver lifecycle, hooks, config)
131
+ - [Example project README](example/README.md) — guided tour of the working example
132
+
133
+ ## Contributing
134
+
135
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
136
+
137
+ ## License
138
+
139
+ [MIT](LICENSE) © Nourreddine Houari
@@ -0,0 +1,41 @@
1
+ import type { EnvironmentConfig } from '../types';
2
+
3
+ export const defaultConfig: EnvironmentConfig = {
4
+ name: 'default',
5
+ web: {
6
+ baseUrl: 'http://localhost:3000',
7
+ headless: true,
8
+ browserName: 'chromium'
9
+ },
10
+ api: {
11
+ baseUrl: 'http://localhost:3000',
12
+ defaultCredentials: { username: 'test@example.com', password: 'password' },
13
+ timeoutMs: 30000
14
+ },
15
+ mobile: {
16
+ flowsDir: 'flows/mobile',
17
+ timeoutMs: 120000
18
+ },
19
+ database: {
20
+ enabled: false
21
+ },
22
+ desktop: {
23
+ agentJar: require('path').resolve(__dirname, '../../apps/desktop/agent/fxagent.jar'),
24
+ defaultTimeoutMs: 10000,
25
+ screenshotDir: 'reports/screenshots'
26
+ },
27
+ flutterDesktop: {
28
+ appPath: require('path').resolve(
29
+ __dirname,
30
+ '../../apps/mobile/build/macos/Build/Products/Profile/todoapp.app/Contents/MacOS/todoapp'
31
+ ),
32
+ defaultTimeoutMs: 10000,
33
+ launchTimeoutMs: 30000,
34
+ screenshotDir: 'reports/screenshots'
35
+ },
36
+ remoteScenarios: {
37
+ baseUrl: 'http://localhost:8788/api',
38
+ outputDir: '.remote-features',
39
+ filters: {}
40
+ }
41
+ };
@@ -0,0 +1,16 @@
1
+ import type { EnvironmentConfig } from '../types';
2
+
3
+ export const devConfig: Partial<EnvironmentConfig> = {
4
+ name: 'dev',
5
+ web: {
6
+ baseUrl: 'http://localhost:3000',
7
+ headless: false,
8
+ browserName: 'chromium',
9
+ slowMo: 100
10
+ },
11
+ api: {
12
+ baseUrl: 'http://localhost:3000/api',
13
+ defaultCredentials: { username: 'dev@example.com', password: 'devpassword' },
14
+ timeoutMs: 60000
15
+ }
16
+ };
@@ -0,0 +1,15 @@
1
+ import type { EnvironmentConfig } from '../types';
2
+
3
+ export const stagingConfig: Partial<EnvironmentConfig> = {
4
+ name: 'staging',
5
+ web: {
6
+ baseUrl: 'https://staging.example.com',
7
+ headless: true,
8
+ browserName: 'chromium'
9
+ },
10
+ api: {
11
+ baseUrl: 'https://staging.example.com/api',
12
+ defaultCredentials: { username: 'staging@example.com', password: 'stagingpassword' },
13
+ timeoutMs: 45000
14
+ }
15
+ };
@@ -0,0 +1,70 @@
1
+ import 'dotenv/config';
2
+
3
+ import { defaultConfig } from './environments/default';
4
+ import type { EnvironmentConfig } from './types';
5
+
6
+ function loadConfig(): EnvironmentConfig {
7
+ const env = process.env.TEST_ENV ?? 'default';
8
+ let base = defaultConfig;
9
+
10
+ if (env !== 'default') {
11
+ try {
12
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
13
+ const envModule = require(`./environments/${env}`);
14
+ const envConfig = envModule[`${env}Config`] as EnvironmentConfig;
15
+ base = deepMerge(base, envConfig);
16
+ } catch {
17
+ // fall back to default
18
+ }
19
+ }
20
+
21
+ // env-var overrides
22
+ if (process.env.WEB_BASE_URL) base.web.baseUrl = process.env.WEB_BASE_URL;
23
+ if (process.env.API_BASE_URL) base.api.baseUrl = process.env.API_BASE_URL;
24
+ if (process.env.HEADLESS) base.web.headless = process.env.HEADLESS !== 'false';
25
+ if (process.env.BROWSER) base.web.browserName = process.env.BROWSER as EnvironmentConfig['web']['browserName'];
26
+ if (process.env.MAESTRO_DEVICE) base.mobile.deviceId = process.env.MAESTRO_DEVICE;
27
+ if (process.env.FLUTTER_DESKTOP_APP_PATH && base.flutterDesktop) {
28
+ base.flutterDesktop.appPath = process.env.FLUTTER_DESKTOP_APP_PATH;
29
+ }
30
+ if (process.env.FLUTTER_DESKTOP_VM_PORT && base.flutterDesktop) {
31
+ base.flutterDesktop.vmServicePort = Number(process.env.FLUTTER_DESKTOP_VM_PORT);
32
+ }
33
+
34
+ if (base.remoteScenarios) {
35
+ const rs = base.remoteScenarios;
36
+ if (process.env.REMOTE_SCENARIOS_URL) rs.baseUrl = process.env.REMOTE_SCENARIOS_URL;
37
+ if (process.env.REMOTE_SCENARIOS_PROJECT) rs.project = process.env.REMOTE_SCENARIOS_PROJECT;
38
+ if (process.env.REMOTE_SCENARIOS_OUTPUT_DIR) rs.outputDir = process.env.REMOTE_SCENARIOS_OUTPUT_DIR;
39
+ rs.filters = rs.filters ?? {};
40
+ if (process.env.REMOTE_SCENARIOS_STORY) rs.filters.story = process.env.REMOTE_SCENARIOS_STORY;
41
+ if (process.env.REMOTE_SCENARIOS_REQUIREMENT) rs.filters.requirement = process.env.REMOTE_SCENARIOS_REQUIREMENT;
42
+ if (process.env.REMOTE_SCENARIOS_PHASE) rs.filters.phase = process.env.REMOTE_SCENARIOS_PHASE;
43
+ if (process.env.REMOTE_SCENARIOS_MODE) {
44
+ rs.filters.mode = process.env.REMOTE_SCENARIOS_MODE as 'cumulative' | 'strict';
45
+ }
46
+ if (process.env.REMOTE_SCENARIOS_TAGS) rs.filters.tags = process.env.REMOTE_SCENARIOS_TAGS;
47
+ if (process.env.REMOTE_SCENARIOS_FEATURE) rs.filters.feature = process.env.REMOTE_SCENARIOS_FEATURE;
48
+ if (process.env.REMOTE_SCENARIOS_Q) rs.filters.q = process.env.REMOTE_SCENARIOS_Q;
49
+ if (process.env.REMOTE_SCENARIOS_VALID) rs.filters.valid = process.env.REMOTE_SCENARIOS_VALID === 'true';
50
+ }
51
+
52
+ return base;
53
+ }
54
+
55
+ function deepMerge<T>(base: T, override: Partial<T>): T {
56
+ const result = { ...base };
57
+ for (const key of Object.keys(override ?? {}) as (keyof T)[]) {
58
+ const ov = override[key];
59
+ if (ov !== null && typeof ov === 'object' && !Array.isArray(ov)) {
60
+ result[key] = deepMerge(result[key] as object, ov as object) as T[typeof key];
61
+ } else if (ov !== undefined) {
62
+ result[key] = ov as T[typeof key];
63
+ }
64
+ }
65
+ return result;
66
+ }
67
+
68
+ export const config = loadConfig();
69
+ export { loadConfig };
70
+ export type { EnvironmentConfig };
@@ -0,0 +1,94 @@
1
+ export interface WebConfig {
2
+ baseUrl: string;
3
+ headless: boolean;
4
+ browserName: 'chromium' | 'firefox' | 'webkit';
5
+ slowMo?: number;
6
+ viewport?: { width: number; height: number };
7
+ }
8
+
9
+ export interface ApiConfig {
10
+ baseUrl: string;
11
+ defaultCredentials: { username: string; password: string };
12
+ timeoutMs?: number;
13
+ }
14
+
15
+ export interface MobileConfig {
16
+ deviceId?: string;
17
+ flowsDir: string;
18
+ timeoutMs: number;
19
+ maestroBin?: string;
20
+ }
21
+
22
+ export interface DatabaseConfig {
23
+ enabled: boolean;
24
+ }
25
+
26
+ export interface DesktopConfig {
27
+ agentJar: string;
28
+ javaBin?: string;
29
+ agentPort?: number;
30
+ agentHost?: string;
31
+ defaultTimeoutMs?: number;
32
+ pollIntervalMs?: number;
33
+ screenshotDir?: string;
34
+ jvmArgs?: string[];
35
+ }
36
+
37
+ export interface FlutterDesktopConfig {
38
+ /** Absolute path to the built executable (.app bundle on macOS, .exe on Windows). */
39
+ appPath: string;
40
+ /** Per-action timeout, ms. Default 10_000. */
41
+ defaultTimeoutMs?: number;
42
+ /** How long to wait for the VM service URL to appear on stdout. Default 30_000. */
43
+ launchTimeoutMs?: number;
44
+ /** Optional fixed VM service port (passed via --vm-service-port=). Default: ephemeral. */
45
+ vmServicePort?: number;
46
+ /** Extra CLI args appended after the executable. */
47
+ extraArgs?: string[];
48
+ /** Environment variables added to the spawned process. */
49
+ env?: Record<string, string>;
50
+ /** Where failure screenshots are written. Default 'reports/screenshots'. */
51
+ screenshotDir?: string;
52
+ }
53
+
54
+ export interface RemoteScenariosFilters {
55
+ /** Story id or comma-separated ids (match any), e.g. "US-007". */
56
+ story?: string;
57
+ /** Requirement id or comma-separated ids; resolved via its stories, e.g. "REQ-001". */
58
+ requirement?: string;
59
+ /** Phase id; restricts to in-scope scenarios, e.g. "P1". */
60
+ phase?: string;
61
+ /** Phase resolution mode. Default 'cumulative'. */
62
+ mode?: 'cumulative' | 'strict';
63
+ /** Cucumber tag expression, e.g. "@smoke and not @wip". */
64
+ tags?: string;
65
+ /** Exact feature name. */
66
+ feature?: string;
67
+ /** Case-insensitive substring over name/feature/content. */
68
+ q?: string;
69
+ /** Filter by gherkin validity. */
70
+ valid?: boolean;
71
+ }
72
+
73
+ export interface RemoteScenariosConfig {
74
+ /** Base URL of the requ scenario API, e.g. "http://localhost:8788/api". */
75
+ baseUrl: string;
76
+ /** Project slug (required when the API has >1 project loaded). */
77
+ project?: string;
78
+ /** Server-side filters passed to GET /api/scenarios. */
79
+ filters?: RemoteScenariosFilters;
80
+ /** Directory where reconstructed .feature files are written. Default '.remote-features'. */
81
+ outputDir: string;
82
+ }
83
+
84
+ export interface EnvironmentConfig {
85
+ name: string;
86
+ web: WebConfig;
87
+ api: ApiConfig;
88
+ mobile: MobileConfig;
89
+ database: DatabaseConfig;
90
+ desktop?: DesktopConfig;
91
+ flutterDesktop?: FlutterDesktopConfig;
92
+ /** Optional: source cucumber scenarios from the requ scenario API instead of local files. */
93
+ remoteScenarios?: RemoteScenariosConfig;
94
+ }
@@ -0,0 +1,3 @@
1
+ import type { EnvironmentConfig } from '../types';
2
+ export declare const defaultConfig: EnvironmentConfig;
3
+ //# sourceMappingURL=default.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default.d.ts","sourceRoot":"","sources":["../../../config/environments/default.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAElD,eAAO,MAAM,aAAa,EAAE,iBAsC3B,CAAC"}