Skip to content

feat: add --extension, --chrome-profile, --profile-directory options to test command#3317

Draft
shivamgupta021 wants to merge 2 commits into
mobile-dev-inc:mainfrom
shivamgupta021:260525-n8rz-web-extension-and-profile-flags
Draft

feat: add --extension, --chrome-profile, --profile-directory options to test command#3317
shivamgupta021 wants to merge 2 commits into
mobile-dev-inc:mainfrom
shivamgupta021:260525-n8rz-web-extension-and-profile-flags

Conversation

@shivamgupta021

Copy link
Copy Markdown

Summary

Adds three new web-only CLI options to maestro test:

Option Maps to Repeatable
--extension <path> Chrome's --load-extension yes
--chrome-profile <path> Chrome's --user-data-dir no
--profile-directory <name> Chrome's --profile-directory no (requires --chrome-profile)

Together these enable testing browser extensions and authenticated web apps without doing the OAuth dance inside every flow.

Addresses #2798 (which asked for --user-data-dir exposure in containerized environments). Same underlying gap — no way to configure ChromeOptions from the CLI — surfaces in both use cases.

Example

# Load an unpacked extension
maestro test --extension /path/to/unpacked-ext flow.yaml

# Run against a pre-authenticated profile
maestro test \
  --chrome-profile "/Users/me/Library/Application Support/Google/Chrome" \
  --profile-directory "Profile 1" \
  flow.yaml

# Combined: extension + authenticated profile (common when testing a
# Gmail/Slack/SaaS Chrome extension end-to-end)
maestro test \
  --extension /path/to/unpacked-ext \
  --chrome-profile /tmp/test-profile-snapshot \
  flow.yaml

Changes

Production code (4 files, +109/-30 LOC)

  • maestro-cli/.../TestCommand.kt — three new @Options + internal fun validateChromeProfileOptions() called from call() (mirrors the existing screenSize validation pattern).
  • maestro-cli/.../MaestroSessionManager.kt — threads the three params through newSession()createMaestro() → both Platform.WEB branches of pickWebDevice().
  • maestro-client/.../Maestro.ktMaestro.web() accepts and forwards the three params (all default null).
  • maestro-client/.../CdpWebDriver.kt — accepts the three new constructor params; extracted the inline ChromeOptions configuration into internal fun buildChromeOptions(): ChromeOptions so unit tests can inspect args without launching a real ChromeDriver. Empty-string flag values are treated as null.

Touched-but-trivial (2 files)

  • maestro-client/.../DeviceService.kt — 1-line comment noting that the existing CdpWebDriver() call site relies on default-null params for the new options. No behavior change.
  • maestro-web/.../ChromeSeleniumFactory.kt — non-goal comment explaining that the legacy Selenium driver intentionally does not receive these flags. No behavior change.

Tests (2 files, 17 new test cases)

  • maestro-client/.../CdpWebDriverTest.kt (new) — 11 unit tests for buildChromeOptions(): arg presence per flag, ordering when combined, empty-string handling, omitted---profile-directory case.
  • maestro-cli/.../TestCommandTest.kt — 6 new tests for validateChromeProfileOptions(): throws when --profile-directory set without --chrome-profile, throws when --extension path contains a comma (Chrome uses , as path separator with no escape), passes otherwise.

Docs

  • CHANGELOG.md — three bullets under ## Unreleased.

Validation rules

  1. --profile-directory requires --chrome-profileCliError("--profile-directory requires --chrome-profile to be specified.")
  2. --extension <path> rejected if path contains ,CliError("--extension path cannot contain commas (Chrome's --load-extension uses ',' as the path separator): <path>")

Both fire in TestCommand.call() before session creation, matching the existing --screen-size format check.

Compatibility

  • All new CLI params default to null / unset; behavior with flags unset is byte-identical to upstream main.
  • Existing positional/named call sites of Maestro.web(), MaestroSessionManager.newSession(), and CdpWebDriver(...) continue to compile and behave identically.
  • No new Maven/Gradle dependencies.
  • No edits to maestro-android/, maestro-ios/, maestro-orchestra/, maestro-studio/, or maestro-ai/ modules.

Test plan

  • ./gradlew :maestro-client:test --tests "maestro.drivers.CdpWebDriverTest" passes (11/11)
  • ./gradlew :maestro-cli:test --tests "maestro.cli.command.TestCommandTest" passes (incl. 6 new)
  • ./gradlew :maestro-cli:installDist builds cleanly
  • maestro test --help lists all three flags with (Web only) prefix; --profile-directory includes "Requires --chrome-profile"
  • Manual integration: load a real Chrome extension against a pre-authenticated profile, run a smoke flow against Gmail — verified locally on macOS 14, Chrome 144.

Happy to iterate on flag naming, validation edge cases, or scope.

…to test command

Three new web-only CLI options on `maestro test`:

- `--extension <path>` (repeatable) loads an unpacked Chrome extension via
  Chrome's `--load-extension`
- `--chrome-profile <path>` launches Chrome with a pre-existing user data
  directory (maps to Chrome's `--user-data-dir`)
- `--profile-directory <name>` selects a profile within the user data
  directory (e.g. `Default`, `Profile 1`); requires `--chrome-profile`

Together these enable testing browser extensions and authenticated web
apps without doing the OAuth dance inside every flow.

Implementation notes:

- `CdpWebDriver.createSeleniumDriver()`'s inline `ChromeOptions` block is
  extracted into `internal fun buildChromeOptions(): ChromeOptions` so
  tests can inspect args via `options.asMap()` without launching a real
  `ChromeDriver`.
- `TestCommand.call()` validates dependencies before session creation
  (mirroring the existing `screenSize` regex check). `--profile-directory`
  requires `--chrome-profile`; `--extension` paths cannot contain commas
  (Chrome uses `,` as a path separator with no escape mechanism).
- All new params default to `null`; behavior with flags unset is
  byte-identical to upstream.
- 11 unit tests in new `CdpWebDriverTest`, 6 new validation tests in
  `TestCommandTest`, CHANGELOG entry under `## Unreleased`.

Addresses mobile-dev-inc#2798
@shivamgupta021 shivamgupta021 marked this pull request as draft May 25, 2026 08:43
…ension-and-profile-flags

# Conflicts:
#	CHANGELOG.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant