Skip to content

feat(providers): add Digital.ai Testing cloud provider#120

Merged
Winify merged 1 commit into
webdriverio:mainfrom
Arundoss-digitalai:feat/digitalai-provider
Jun 16, 2026
Merged

feat(providers): add Digital.ai Testing cloud provider#120
Winify merged 1 commit into
webdriverio:mainfrom
Arundoss-digitalai:feat/digitalai-provider

Conversation

@Arundoss-digitalai

Copy link
Copy Markdown
Contributor

Proposed changes

Adds Digital.ai Testing (formerly Experitest/SeeTest) as a cloud provider, at parity with the existing BrowserStack / Sauce Labs / TestMu / TestingBot integrations — covering web (Selenium) and mobile (Appium) sessions plus app management.

Sessions connect to <DIGITALAI_CLOUD_URL>/wd/hub over https:443; authentication rides in the access-key capability (no WebDriver basic auth).

Web (Selenium) — flat digitalai:* capabilities:

  • digitalai:accessKey, digitalai:testName, and digitalai:osName (combined from os/osVersion).
  • The flat form is what activates the reporter — the cloud returns digitalai:reportUrl, which is surfaced in the start_session output.
  • Browser names map edgeMicrosoftEdge.

Mobile (Appium) — nested digitalai:options object:

  • accessKey, testName, and a deviceQuery for dynamic device selection (explicit, or built from deviceName/platformVersion).
  • The Appium server/version is selected at the Digital.ai project level (configure the project for Appium-server execution), not pinned here.
  • Native apps are referenced as cloud:<package-or-bundle>.

Pass/fail reporting — marked via onSessionClose using the seetest:client.setReportStatus automation command, for both web and mobile (consistent with how the other providers mark status).

App managementlist_apps / upload_app wired through the Applications REST API (GET /api/v1/applications, POST /api/v1/applications/new) using Bearer auth with the access key. The shared cloud-provider tool gains a Bearer path; the other providers' auth and behaviour are unchanged.

Generated reproduction code (wdio://session/current/code) emits the Digital.ai hub connection and scrubs the access key to a process.env reference (flat and nested forms) so secrets are never baked into generated output.

New start_session param: deviceQuery.
Credentials: DIGITALAI_CLOUD_URL / DIGITALAI_ACCESS_KEY.

Verified live against a Digital.ai cloud: web and mobile sessions (both generating reports with pass/fail status) plus list_apps.

Types of changes

  • Polish (an improvement for an existing feature)
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update (improvements to the project's docs)
  • Specification changes (updates to WebDriver command specifications)
  • Internal updates (everything related to internal scripts, governance documentation and CI files)

Checklist

  • I have squashed commits that belong together
  • I have tested with Claude Desktop (or another MCP-compatible client)
  • I have read the CONTRIBUTING doc
  • I have added the necessary documentation for new/changed tools (if appropriate)
  • I have added proper type definitions for new commands (if appropriate)

Further comments

Scope / design notes

  • New, self-contained provider (src/providers/cloud/digitalai.provider.ts) registered via providers/registry.ts; existing providers are untouched. The only shared-code change is an additive Bearer-auth path in cloud-provider.tool.ts (existing Basic-auth providers produce byte-identical requests).
  • Auth differs by surface by design: web uses flat digitalai:* capabilities (required to activate the Selenium reporter), mobile uses the nested digitalai:options object (Appium 2 convention), and the REST API uses Bearer.

Report status & BiDi (opt-in)

  • WebdriverIO defaults to BiDi, over which the cloud cannot observe command failures, so reports default to "Passed". To get accurate cloud-side pass/fail, opt in per session with capabilities: { 'wdio:enforceWebDriverClassic': true }. This is documented in the README and left to the user rather than forced (BiDi-dependent features otherwise stay available).

Testing

  • Unit tests added for the provider, registry resolution, list_apps/upload_app, and generated code (incl. secret scrubbing); full suite green, lint clean.
  • Verified end-to-end against a live Digital.ai cloud through the actual MCP tool path: web + mobile sessions, report generation, pass/fail status marking, and list_apps.

Reviewers: @webdriverio/project-committers

@linux-foundation-easycla

linux-foundation-easycla Bot commented Jun 15, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: Arundoss-digitalai / name: arundoss-digital.ai (cc82ba3)

@greptile-apps

greptile-apps Bot commented Jun 15, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds Digital.ai Testing (formerly Experitest/SeeTest) as a new cloud provider, following the same extension pattern as BrowserStack, Sauce Labs, TestMu, and TestingBot. It includes a self-contained provider class, registry registration, list_apps/upload_app support (via Bearer auth), code-generation, and a full unit-test suite.

  • New src/providers/cloud/digitalai.provider.ts handles both web (flat digitalai:* capabilities) and mobile (digitalai:options object); the resolveCloudHost helper is shared with the REST tool to strip schemes/paths from DIGITALAI_CLOUD_URL.
  • cloud-provider.tool.ts is refactored to support Bearer auth alongside existing Basic auth, with no change to the byte-level output for other providers.
  • code-generator.ts gains a Digital.ai block in both generateStep (hub connection) and generateCode (try/catch/finally wrapper with setReportStatus), and scrubs the access key to a process.env reference.

Confidence Score: 5/5

Safe to merge — the change is self-contained, all previous review issues are addressed, and the implementation is well-tested end-to-end.

The new provider is entirely additive: a fresh file registered in the provider map, an optional Bearer-auth path grafted onto the cloud tool, and additive blocks in the code generator. No existing provider logic, auth flow, or data path is altered. All previously flagged issues have been correctly resolved in this revision.

No files require special attention. The only nit is the upload fallback ref in src/tools/cloud-provider.tool.ts.

Important Files Changed

Filename Overview
src/providers/cloud/digitalai.provider.ts New provider; correctly handles web (flat caps), mobile (nested options), deviceQuery building with escaping, report-URL surfacing, and pass/fail marking via seetest:client.setReportStatus.
src/tools/cloud-provider.tool.ts Auth refactored from bare base64 in callers to a single authHeader value; Digital.ai added with Bearer scheme; all existing providers produce identical Authorization headers.
src/recording/code-generator.ts Adds Digital.ai blocks in both generateStep (hub connection with key scrubbing) and generateCode (try/catch/finally with seetest:client.setReportStatus); pattern is consistent with TestingBot/BrowserStack blocks.
src/tools/session.tool.ts Adds digitalai to provider enum, exposes deviceQuery param, and wires getStartNote for report URL injection in both browser and mobile session responses.
tests/providers/digitalai.provider.test.ts Thorough unit tests covering resolveCloudHost, buildCapabilities (web + mobile), deviceQuery building/escaping, onSessionClose pass/fail, and error resilience.
tests/tools/cloud-provider.tool.test.ts New Digital.ai sections cover Bearer auth header, cloud: ref parsing, cloud:undefined guard, upload response parsing, and missing-credentials errors.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant MCP as MCP Client
    participant ST as session.tool
    participant REG as registry.ts
    participant DAI as DigitalAiProvider
    participant HUB as Digital.ai Hub
    participant API as Digital.ai REST API

    MCP->>ST: "start_session(provider='digitalai', ...)"
    ST->>REG: getProvider('digitalai', platform)
    REG-->>ST: DigitalAiProvider
    ST->>DAI: getConnectionConfig(options)
    DAI-->>ST: "{protocol:'https', hostname, port:443, path:'/wd/hub'}"
    ST->>DAI: buildCapabilities(options)
    Note over DAI: Web: flat digitalai:accessKey
    Note over DAI: Mobile: nested digitalai:options
    DAI-->>ST: "capabilities{}"
    ST->>HUB: WebDriver session (accessKey in caps)
    HUB-->>ST: sessionId + digitalai:reportUrl
    ST->>DAI: getStartNote(browser)
    DAI-->>ST: Report URL string
    ST-->>MCP: Session started + reportUrl

    MCP->>ST: close_session(status)
    ST->>DAI: onSessionClose(sessionId, type, result, browser)
    DAI->>HUB: execute('seetest:client.setReportStatus', status, message)
    ST->>HUB: deleteSession()

    MCP->>API: GET /api/v1/applications
    Note over API: Authorization: Bearer DIGITALAI_ACCESS_KEY
    API-->>MCP: "[{name, applicationName, ...}]"
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant MCP as MCP Client
    participant ST as session.tool
    participant REG as registry.ts
    participant DAI as DigitalAiProvider
    participant HUB as Digital.ai Hub
    participant API as Digital.ai REST API

    MCP->>ST: "start_session(provider='digitalai', ...)"
    ST->>REG: getProvider('digitalai', platform)
    REG-->>ST: DigitalAiProvider
    ST->>DAI: getConnectionConfig(options)
    DAI-->>ST: "{protocol:'https', hostname, port:443, path:'/wd/hub'}"
    ST->>DAI: buildCapabilities(options)
    Note over DAI: Web: flat digitalai:accessKey
    Note over DAI: Mobile: nested digitalai:options
    DAI-->>ST: "capabilities{}"
    ST->>HUB: WebDriver session (accessKey in caps)
    HUB-->>ST: sessionId + digitalai:reportUrl
    ST->>DAI: getStartNote(browser)
    DAI-->>ST: Report URL string
    ST-->>MCP: Session started + reportUrl

    MCP->>ST: close_session(status)
    ST->>DAI: onSessionClose(sessionId, type, result, browser)
    DAI->>HUB: execute('seetest:client.setReportStatus', status, message)
    ST->>HUB: deleteSession()

    MCP->>API: GET /api/v1/applications
    Note over API: Authorization: Bearer DIGITALAI_ACCESS_KEY
    API-->>MCP: "[{name, applicationName, ...}]"
Loading

Reviews (2): Last reviewed commit: "feat(providers): add Digital.ai Testing ..." | Re-trigger Greptile

Comment thread src/recording/code-generator.ts Outdated
Comment thread src/tools/session.tool.ts Outdated
@Winify

Winify commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

@Arundoss-digitalai I have reviewed the PR, minor notes only

Decide if you want to resolve, then I can merge and publish a version 🚀

Adds Digital.ai (formerly Experitest/SeeTest) at parity with the other
cloud providers, covering both web (Selenium) and mobile (Appium) plus
app management. Connects to <DIGITALAI_CLOUD_URL>/wd/hub over https:443;
authentication rides in the accessKey capability.

Web (Selenium) sessions use flat digitalai:* capabilities — digitalai:accessKey,
digitalai:testName, and digitalai:osName (combined from os/osVersion). The flat
form is what activates the reporter: the cloud returns digitalai:reportUrl, which
is surfaced in the start_session output. Browser names map edge -> MicrosoftEdge.

Mobile (Appium) sessions use the nested digitalai:options object — accessKey,
testName, and a deviceQuery for dynamic device selection (explicit, or built from
deviceName/platformVersion). The Appium server/version is selected at the Digital.ai
project level (configure the project for Appium-server execution), not pinned here.
Native apps are referenced as cloud:<package-or-bundle>.

Pass/fail is reported via onSessionClose using the seetest:client.setReportStatus
automation command, for both web and mobile.

list_apps/upload_app are wired through the Applications REST API
(GET /api/v1/applications, POST /api/v1/applications/new) using Bearer auth with the
access key, leaving the other providers' auth and behaviour unchanged.

Generated reproduction code (wdio://session/current/code) emits the Digital.ai hub
connection and scrubs the access key to a process.env reference (flat and nested
forms) so secrets are never baked into generated output.

New start_session param: deviceQuery.
Credentials: DIGITALAI_CLOUD_URL / DIGITALAI_ACCESS_KEY.

Verified live against a Digital.ai cloud: web and mobile sessions (both generating
reports with pass/fail status) plus list_apps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Arundoss-digitalai Arundoss-digitalai force-pushed the feat/digitalai-provider branch from cc82ba3 to 76e4542 Compare June 16, 2026 12:34
@Arundoss-digitalai

Copy link
Copy Markdown
Contributor Author

Thanks @Winify! Addressed both your comments and greptile P1 and P2 in 76e4542:
It's all in the same commit. Ready for another look.

@Winify Winify merged commit bc620a2 into webdriverio:main Jun 16, 2026
3 checks passed
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.

2 participants