Skip to content

POC: Support multiremote take 2 - #2172

Draft
dprevost-LMI wants to merge 5 commits into
webdriverio:mainfrom
dprevost-LMI:support-multiremote-take-2
Draft

POC: Support multiremote take 2#2172
dprevost-LMI wants to merge 5 commits into
webdriverio:mainfrom
dprevost-LMI:support-multiremote-take-2

Conversation

@dprevost-LMI

Copy link
Copy Markdown
Contributor

No description provided.

@dprevost-LMI
dprevost-LMI marked this pull request as ready for review August 4, 2026 10:23
@dprevost-LMI
dprevost-LMI marked this pull request as draft August 4, 2026 10:23
@greptile-apps

greptile-apps Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds multiremote support to toHaveTitle, including scalar, array, and instance-name map expectations, along with new public typings and playground coverage. It also switches WDIO dependencies to local yalc packages and adjusts root validation.

  • Routes multiremote title reads through selected browser instances and per-index comparisons.
  • Extends toHaveTitle typings for MultiRemoteBrowser.
  • Adds a multiremote Mocha playground suite and supporting local package locks.

Confidence Score: 4/5

The PR is not safe to merge until single-browser RegExp/asymmetric title assertions, multiremote array cardinality, and clean-install dependency resolution are fixed.

The new single-browser guard rejects supported matcher inputs, excess multiremote expectations can be silently ignored, and the committed manifests reference local packages unavailable in a clean checkout.

Files Needing Attention: src/matchers/browser/toHaveTitle.ts, package.json, playgrounds/multi-remote-mocha/test/specs/wdio-matchers.test.ts

Important Files Changed

Filename Overview
src/matchers/browser/toHaveTitle.ts Adds multiremote title comparison, but regresses supported single-browser object-valued matchers and can ignore excess array expectations.
types/expect-webdriverio.d.ts Extends the public toHaveTitle signature for multiremote scalar, array, and named-map expectations.
package.json Replaces installable WDIO versions with untracked local yalc paths and removes linting from the root test pipeline.
playgrounds/multi-remote-mocha/test/specs/wdio-matchers.test.ts Adds end-to-end multiremote title scenarios, but an exclusive test prevents most scenarios from running.
test/mocks/@wdio/globals.ts Adds a multiremote mock whose selected-browser object does not faithfully model command aggregation.
test/matchers/browserMatchers.test.ts Adapts title expectations while removing toHaveUrl from the shared behavioral test matrix.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A["expect(browser).toHaveTitle(expected)"] --> B{"isMultiremote"}
  B -- No --> C["getTitle()"]
  C --> D["compareText(actual, expected)"]
  B -- Yes --> E{"Expected map?"}
  E -- Yes --> F["select(map keys).getTitle()"]
  E -- No --> G["all browsers getTitle()"]
  F --> H["Pair actual and expected by index"]
  G --> H
  H --> I["All comparisons pass?"]
Loading

Reviews (1): Last reviewed commit: "Fixes + e2e" | Re-trigger Greptile

Comment on lines +35 to +36
} else if (typeof expectedValue === 'object' || Array.isArray(expectedValue) && !isAsymmetricMatcher(expectedValue)) {
throw new Error('Expected value object or array is not supported for a single browser instance. Use a string, RegExp or asymmetric matcher instead.')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Supported title matchers are rejected

When a single-browser assertion uses a RegExp or asymmetric matcher, the object check throws before comparison, causing previously valid toHaveTitle assertions to fail with the unsupported-value error.

Suggested change
} else if (typeof expectedValue === 'object' || Array.isArray(expectedValue) && !isAsymmetricMatcher(expectedValue)) {
throw new Error('Expected value object or array is not supported for a single browser instance. Use a string, RegExp or asymmetric matcher instead.')
} else if (Array.isArray(expectedValue) && !isAsymmetricMatcher(expectedValue) || typeof expectedValue === 'object' && !isAsymmetricMatcher(expectedValue) && !(expectedValue instanceof RegExp)) {
throw new Error('Expected value object or array is not supported for a single browser instance. Use a string, RegExp or asymmetric matcher instead.')

Knowledge Base Used: Element and Browser Matchers

Comment on lines +91 to +93
if (Array.isArray(actual)){
const results = actual.map((title, index) => compareText(title, Array.isArray(expectedValues) ? expectedValues[index] : expectedValues, options))
return { actual: results.map(r => r.actual), success: results.every(r => r.success), subject: browser }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Excess title expectations are ignored

When the expected array contains more entries than the multiremote result, the code iterates only over actual titles and reports success without checking the extra expectations.

Suggested change
if (Array.isArray(actual)){
const results = actual.map((title, index) => compareText(title, Array.isArray(expectedValues) ? expectedValues[index] : expectedValues, options))
return { actual: results.map(r => r.actual), success: results.every(r => r.success), subject: browser }
if (Array.isArray(actual)){
if (Array.isArray(expectedValues) && expectedValues.length !== actual.length) {
throw new Error('Expected value array length must match the number of browser instances.')
}
const results = actual.map((title, index) => compareText(title, Array.isArray(expectedValues) ? expectedValues[index] : expectedValues, options))
return { actual: results.map(r => r.actual), success: results.every(r => r.success), subject: browser }

Knowledge Base Used: Element and Browser Matchers

Comment thread package.json
Comment on lines +80 to +81
"@wdio/mocha-framework": "file:.yalc/@wdio/mocha-framework",
"@wdio/utils": "file:.yalc/@wdio/utils",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Local dependencies break clean installs

When CI, release automation, or consumers install this package, npm resolves the new file:.yalc/... dependencies against directories that are not tracked, causing dependency resolution and installation to fail.

})
})

it.only('should verify browser title contains text for one browser', async () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Exclusive test skips new scenarios

The committed it.only restricts this playground suite to one case, so the scalar, asymmetric, array, and full-map multiremote title scenarios are not exercised.

Suggested change
it.only('should verify browser title contains text for one browser', async () => {
it('should verify browser title contains text for one browser', async () => {

Comment thread package.json
@@ -61,7 +61,6 @@
"tsc:root-types": "node types-checks-filter-out-node_modules.js",
"test": "run-s test:*",
"test:tsc": "tsc --project tsconfig.json --noEmit --rootDir .",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Root lint validation is removed

Deleting test:lint removes ESLint from the wildcard npm test pipeline used by checks:all, allowing root validation to pass despite new lint violations.

@dprevost-LMI

Copy link
Copy Markdown
Contributor Author

@greptileai, do you understand why we have the below, despite pulling yalc build of webdriverio/webdriverio#15459

[MultiremoteBrowser on chrome and firefox #0-0] browser.select is not a function
[MultiremoteBrowser on chrome and firefox #0-0] TypeError: browser.select is not a function
[MultiremoteBrowser on chrome and firefox #0-0]     at compareMultiRemoteTitles (file:///Users/dprevost/Git/expect-webdriverio/lib/matchers/browser/toHaveTitle.js:54:50)
[MultiremoteBrowser on chrome and firefox #0-0]     at waitUntil.wait (file:///Users/dprevost/Git/expect-webdriverio/lib/matchers/browser/toHaveTitle.js:12:2

@greptile-apps

greptile-apps Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Yes, I can see the likely cause. There are two potential issues:

1. The select override in the commandList loop

In the webdriverio PR's multiremote.ts, propertiesObject.select is defined before the commandList loop:

propertiesObject.select = {
    value: (instanceNames: string | string[]) => { ... },
    configurable: true,
    writable: true
}

for (const commandName of wrapperClient.commandList) {
    propertiesObject[commandName] = {    // <-- could override select
        value: this.commandWrapper(commandName),
        ...
    }
}

If 'select' ends up in wrapperClient.commandList for any reason, the loop silently overwrites the hand-crafted select with this.commandWrapper('select'). The commandWrapper returns a wrapCommand(...) result, not something you can synchronously chain .getTitle() on.

2. Monorepo yalc build gap

The PR also touches packages/wdio-utils/src/shim.ts (adding 'select', 'filter' to ELEMENT_QUERY_COMMANDS and 'instances' to ELEMENT_PROPS). If you yalc'd only the webdriverio package but not @wdio/utils, the old shim is still in play. While that shouldn't directly block browser.select on the multiremote browser, it can cause subtle initialization issues depending on how the packages load.

Quick way to diagnose: add a console.log(typeof browser.select) right before the call in compareMultiRemoteTitles.

  • undefined → the yalc build is picked up, but the commandList loop is clobbering the select property
  • function → the yalc build isn't being resolved at runtime; run yalc push from packages/webdriverio/ and yalc update webdriverio in expect-webdriverio

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