Skip to content

[BUG-14514] - Switch frame to an iframe in a Shadow DOM#14589

Merged
christian-bromann merged 19 commits intowebdriverio:mainfrom
vishnuv688:bug-fix-14514
Jul 23, 2025
Merged

[BUG-14514] - Switch frame to an iframe in a Shadow DOM#14589
christian-bromann merged 19 commits intowebdriverio:mainfrom
vishnuv688:bug-fix-14514

Conversation

@vishnuv688
Copy link
Member

@vishnuv688 vishnuv688 commented Jun 25, 2025

Proposed changes

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 read the CONTRIBUTING doc
  • I have added tests that prove my fix is effective or that my feature works
  • I have added the necessary documentation (if appropriate)
  • I have added proper type definitions for new commands (if appropriate)

Backport Request

//: # (The current main branch is the development branch for WebdriverIO v9. If your change should be released to the current major version of WebdriverIO (v8), please raise another PR with the same changes against the v8 branch.)

  • This change is solely for v9 and doesn't need to be back-ported
  • Back-ported PR at #XXXXX

Further comments

Reviewers: @webdriverio/project-committers

vishnuv688 and others added 2 commits June 25, 2025 16:07
commit ed62250
Author: Vishnu Vardhan <vishnu.p@browserstack.com>
Date:   Wed Jun 25 16:04:25 2025 +0530

    Trigger EasyCLA

commit da54fcf
Author: Vishnu Vardhan <vishnu.p@browserstack.com>
Date:   Tue Jun 24 15:59:12 2025 +0530

    Comment

commit ad9316e
Merge: 97e851a ff2154c
Author: Vishnu Vardhan <vardhan688@gmail.com>
Date:   Tue Jun 24 13:44:09 2025 +0530

    Merge branch 'main' into bug-14514

commit 97e851a
Merge: 5bb2673 24855c2
Author: Vishnu Vardhan <vardhan688@gmail.com>
Date:   Mon Jun 23 16:02:41 2025 +0530

    Merge branch 'main' into bug-14514

commit 5bb2673
Merge: ac1ad49 d80354d
Author: Vishnu Vardhan <vardhan688@gmail.com>
Date:   Fri Jun 20 12:58:50 2025 +0530

    Merge branch 'main' into bug-14514

commit ac1ad49
Merge: 0471190 072e551
Author: Vishnu Vardhan <vardhan688@gmail.com>
Date:   Thu Jun 19 13:13:03 2025 +0530

    Merge branch 'main' into bug-14514

commit 0471190
Merge: d70b3b1 d344dd4
Author: Vishnu Vardhan <vishnu.p@browserstack.com>
Date:   Wed Jun 18 16:08:30 2025 +0530

    Merge branch 'bug-14514' of github.com:vishnuv688/webdriverio into bug-14514

commit d70b3b1
Author: Vishnu Vardhan <vishnu.p@browserstack.com>
Date:   Wed Jun 18 16:07:11 2025 +0530

    Fixes webdriverio#14514

commit d344dd4
Merge: 35af439 5818efe
Author: Vishnu Vardhan <vardhan688@gmail.com>
Date:   Wed Jun 18 15:52:47 2025 +0530

    Merge branch 'main' into bug-14514

commit 35af439
Merge: 44fe5f5 41ddf78
Author: Vishnu Vardhan <vishnu.p@browserstack.com>
Date:   Wed Jun 18 15:48:48 2025 +0530

    Merge branch 'bug-14514' of github.com:vishnuv688/webdriverio into bug-14514

commit 44fe5f5
Author: VishnuVardhan P <vishnu.p@browserstack.com>
Date:   Wed Jun 18 15:42:21 2025 +0530

    [BUG-14514] - Switch frame to an iframe in a Shadow DOM

commit 41ddf78
Author: Vishnu Vardhan P <vishnu.p@browserstack.com@Vishnus-MacBook-Air.local>
Date:   Wed Jun 18 15:42:21 2025 +0530

    [BUG-14514] - Switch frame to an iframe in a Shadow DOM
@vishnuv688 vishnuv688 marked this pull request as ready for review June 25, 2025 11:04
Copy link
Member

@christian-bromann christian-bromann left a comment

Choose a reason for hiding this comment

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

One suggestion

@christian-bromann christian-bromann added the PR: Bug Fix 🐛 PRs that contain bug fixes label Jul 1, 2025
@pkg-pr-new
Copy link

pkg-pr-new bot commented Jul 8, 2025

Open in StackBlitz

create-wdio

npm i https://pkg.pr.new/webdriverio/webdriverio/create-wdio@14589

eslint-plugin-wdio

npm i https://pkg.pr.new/webdriverio/webdriverio/eslint-plugin-wdio@14589

@wdio/allure-reporter

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/allure-reporter@14589

@wdio/appium-service

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/appium-service@14589

@wdio/browser-runner

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/browser-runner@14589

@wdio/browserstack-service

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/browserstack-service@14589

@wdio/cli

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/cli@14589

@wdio/concise-reporter

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/concise-reporter@14589

@wdio/config

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/config@14589

@wdio/cucumber-framework

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/cucumber-framework@14589

@wdio/dot-reporter

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/dot-reporter@14589

@wdio/firefox-profile-service

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/firefox-profile-service@14589

@wdio/globals

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/globals@14589

@wdio/jasmine-framework

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/jasmine-framework@14589

@wdio/json-reporter

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/json-reporter@14589

@wdio/junit-reporter

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/junit-reporter@14589

@wdio/lighthouse-service

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/lighthouse-service@14589

@wdio/local-runner

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/local-runner@14589

@wdio/logger

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/logger@14589

@wdio/mocha-framework

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/mocha-framework@14589

@wdio/protocols

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/protocols@14589

@wdio/repl

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/repl@14589

@wdio/reporter

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/reporter@14589

@wdio/runner

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/runner@14589

@wdio/sauce-service

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/sauce-service@14589

@wdio/shared-store-service

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/shared-store-service@14589

@wdio/smoke-test-cjs-service

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/smoke-test-cjs-service@14589

@wdio/smoke-test-reporter

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/smoke-test-reporter@14589

@wdio/smoke-test-service

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/smoke-test-service@14589

@wdio/spec-reporter

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/spec-reporter@14589

@wdio/static-server-service

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/static-server-service@14589

@wdio/sumologic-reporter

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/sumologic-reporter@14589

@wdio/testingbot-service

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/testingbot-service@14589

@wdio/types

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/types@14589

@wdio/utils

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/utils@14589

@wdio/webdriver-mock-service

npm i https://pkg.pr.new/webdriverio/webdriverio/@wdio/webdriver-mock-service@14589

webdriver

npm i https://pkg.pr.new/webdriverio/webdriverio/webdriver@14589

webdriverio

npm i https://pkg.pr.new/webdriverio/webdriverio@14589

commit: da486d3

Copy link
Member

@christian-bromann christian-bromann left a comment

Choose a reason for hiding this comment

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

Can you please provide some information about the actual bug or problem you are trying to solve here?

@vishnuv688
Copy link
Member Author

Can you please provide some information about the actual bug or problem you are trying to solve here?

Thanks for the review! Just to clarify, this PR is actually fixing two separate bugs we ran into when working with switchFrame() in BiDi mode, especially in cases where the iframe is inside a Shadow DOM.

  1. elementId gets lost when using shadow$
    The first issue was with waitForExist() — when an element is found via a custom selector strategy like shadow$, it gets re-queried internally using this.parent.$(this.selector). The problem is that this re-query doesn't re-enter the shadow DOM, so the resolved element loses its elementId. That causes a BiDi error later during switchToFrame().

To fix this, I added a check so that we only re-resolve the element if elementId isn’t already set. That way, if we already have a valid element (from shadow$ or similar), we don’t overwrite it.

  1. BiDi can’t find iframes inside Shadow DOM
    The second issue is that browsingContextLocateNodes() doesn’t support searching inside shadow roots. So if your iframe lives inside a shadow DOM, BiDi just won’t find it with a regular locator.

To work around this, I added a fallback that uses browser.execute() to run a script (findIframeInShadowDOM) which manually traverses the DOM and any shadow roots to find the iframe based on its src.

@christian-bromann
Copy link
Member

@vishnuv688 in this case I would recommend to have an e2e test for this. We are having a test bed that is deployed to https://guinea-pig.webdriver.io/. It seems feasible to create little reproduction cases for this there and add some e2e tests for this.

@vishnuv688
Copy link
Member Author

@vishnuv688 in this case I would recommend to have an e2e test for this. We are having a test bed that is deployed to https://guinea-pig.webdriver.io/. It seems feasible to create little reproduction cases for this there and add some e2e tests for this.

@christian-bromann I’ve already tested this using the reproduction test provided in the bug report by linking my local changes.
If you'd still prefer a separate reproduction case using guinea-pig, I’m happy to create one.
Also, for adding an E2E test case in the WebdriverIO monorepo, could you please confirm where exactly I should place it?

And recently, I am facing an issue with the 'create-wdio' package Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'create-wdio' imported from webdriverio/packages/wdio-cli/build/index.js during pnpm run build or when trying to run a test case locally.

@christian-bromann
Copy link
Member

If you'd still prefer a separate reproduction case using guinea-pig, I’m happy to create one.

Yes, let's do that. This will help prevent regressing on this side in the future.

Also, for adding an E2E test case in the WebdriverIO monorepo, could you please confirm where exactly I should place it?

We have already some switchFrame tests here: https://github.com/webdriverio/webdriverio/blob/main/e2e/wdio/headless/test.e2e.ts#L549

And recently, I am facing an issue with the 'create-wdio' package Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'create-wdio' imported from webdriverio/packages/wdio-cli/build/index.js during pnpm run build or when trying to run a test case locally.

Mhm .. maybe try update your branch. We don't see these issues in main and in our pipelines.

@vishnuv688
Copy link
Member Author

@christian-bromann can you please provide me with access to the guinea-pig repo to raise a PR?

@christian-bromann
Copy link
Member

can you please provide me with access to the guinea-pig repo to raise a PR?

The repo is public, you can raise a PR to it.

@vishnuv688
Copy link
Member Author

can you please provide me with access to the guinea-pig repo to raise a PR?

The repo is public, you can raise a PR to it.

@christian-bromann I tried but I am getting error.

`git push --set-upstream origin bug-14514
ERROR: Permission to webdriverio/guinea-pig.git denied to vishnuv688.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.`

@christian-bromann
Copy link
Member

@vishnuv688 I've added the @webdriverio/browserstack team to the project, you should be able to push to the branch now

@vishnuv688
Copy link
Member Author

@vishnuv688 I've added the @webdriverio/browserstack team to the project, you should be able to push to the branch now

@christian-bromann, I have merged the e2e test in guinea-pig. Please do review the changes.

Copy link
Member

@christian-bromann christian-bromann left a comment

Choose a reason for hiding this comment

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

One question, code overall looks good to me, great work!

@christian-bromann
Copy link
Member

Mind taking a look at the unit tests as well?

@vishnuv688
Copy link
Member Author

Mind taking a look at the unit tests as well?

@christian-bromann Yes, I've already added unit tests for both key scenarios:

  • When the element has a valid elementId, switchFrame uses it directly.
  • When the element is unresolved (missing elementId), it re-resolves the selector and then switches.

I have already mentioned the reason for this change in the bug report.

@christian-bromann
Copy link
Member

Yes, I've already added unit tests for both key scenarios

I understand, however the patch seems to cause other unit test to fail, mind taking a look at these?

@vishnuv688
Copy link
Member Author

Yes, I've already added unit tests for both key scenarios

I understand, however the patch seems to cause other unit test to fail, mind taking a look at these?

@christian-bromann May I know which test case is failing, as I could see all the test cases in switchFrame.test have passed.
image

@christian-bromann
Copy link
Member


⎯⎯⎯⎯⎯⎯ Failed Tests 10 ⎯⎯⎯⎯⎯⎯⎯

 FAIL  packages/webdriverio/tests/commands/browser/action.test.ts > action command > resolves not resolved wdio elements in pointer action
SyntaxError: "undefined" is not valid JSON
 ❯ packages/webdriverio/tests/commands/browser/action.test.ts:213:21
    211|         const calls = vi.mocked(fetch).mock.calls
    212|         const [,,, [, performActionParam]] = calls as any
    213|         expect(JSON.parse(performActionParam.body)).toMatchSnapshot()

       |                     ^
    214|     })
  Snapshots  1 failed
    215| 
             2 obsolete

             ↳ packages/webdriverio/tests/commands/browser/action.test.ts
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/10]⎯
               · action command > resolves not resolved wdio elements in pointer action 1

               · action command > resolves not resolved wdio elements in wheel action 1
 FAIL  packages/webdriverio/tests/commands/browser/action.test.ts > action command > resolves not resolved wdio elements in wheel action

SyntaxError: "undefined" is not valid JSON
 Test Files  3 failed | 291 passed (294)
 ❯ packages/webdriverio/tests/commands/browser/action.test.ts:222:21
      Tests  10 failed | 3421 passed | 7 skipped (3438)
    220|         const calls = vi.mocked(fetch).mock.calls
   Start at  23:38:57
    221|         const [,,, [, performActionParam]] = calls as any
   Duration  111.86s (transform 3.88s, setup 1.70s, collect 36.06s, tests 148.52s, environment 1.54s, prepare 11.30s)
    222|         expect(JSON.parse(performActionParam.body)).toMatchSnapshot()

       |                     ^

    223|     })
Error: SyntaxError: "undefined" is not valid JSON
 ❯ packages/webdriverio/tests/commands/browser/action.test.ts:213:21


    224| })

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/10]⎯

 FAIL  packages/webdriverio/tests/commands/element/execute.test.ts > execute test > should execute the script
TypeError: Cannot read properties of undefined (reading '1')
 ❯ packages/webdriverio/tests/commands/element/execute.test.ts:26:56
     24|         expect((vi.mocked(fetch).mock.calls[1][0] as any).pathname)
     25|             .toBe('/session/foobar-123/element')
     26|         expect(JSON.parse(vi.mocked(fetch).mock.calls[4][1]?.body as s…
       |                                                        ^
     27|             script: expect.stringContaining('return ((elem, a, b, c) =…
     28|             args: [{ [ELEMENT_KEY]: 'some-elem-123', ELEMENT: 'some-el…

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/10]⎯

 FAIL  packages/webdriverio/tests/commands/element/execute.test.ts > execute test > should wait for element to exist
Error: Snapshot `execute test > should wait for element to exist 1` mismatched

- Expected
+ Received

  [
    "http://localhost:4321/session",
    "http://localhost:4321/session/foobar-123/element",
    "http://localhost:4321/session/foobar-123/elements",
-   "http://localhost:4321/session/foobar-123/element",
    "http://localhost:4321/session/foobar-123/execute/sync",
  ]

 ❯ packages/webdriverio/tests/commands/element/execute.test.ts:41:66
     39| 
     40|         await browser.$('#foo').execute((elem) => elem)
     41|         expect(vi.mocked(fetch).mock.calls.map(call => call[0])).toMat…
       |                                                                  ^
     42|           [
     43|             "http://localhost:4321/session",

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/10]⎯

 FAIL  packages/webdriverio/tests/commands/element/selectByVisibleText.test.ts > selectByVisibleText test > should select value by visible text
TypeError: Cannot read properties of undefined (reading '0')
 ❯ packages/webdriverio/tests/commands/element/selectByVisibleText.test.ts:45:45
     43|         )
     44|         // @ts-expect-error mock implementation
     45|         expect(vi.mocked(fetch).mock.calls[5][0]!.pathname)
       |                                             ^

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[9/10]⎯

 FAIL  packages/webdriverio/tests/commands/element/selectByVisibleText.test.ts > selectByVisibleText test > should convert number to string when selecting
TypeError: Cannot read properties of undefined (reading '0')
 ❯ packages/webdriverio/tests/commands/element/selectByVisibleText.test.ts:145:45
    143|             .toBe(`${optionSelection}|${optgroupSelection}`)
    144|         // @ts-expect-error mock implementation
    145|         expect(vi.mocked(fetch).mock.calls[5][0]!.pathname)
       |                                             ^
    146|             .toBe('/session/foobar-123/element/some-sub-elem-321/click…
    147|         expect(getElementFromResponseSpy).toBeCalledWith({

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[10/10]⎯


Error: SyntaxError: "undefined" is not valid JSON
 ❯ packages/webdriverio/tests/commands/browser/action.test.ts:222:21



Error: TypeError: Cannot read properties of undefined (reading '1')
 ❯ packages/webdriverio/tests/commands/element/execute.test.ts:26:56



Error: Error: Snapshot `execute test > should wait for element to exist 1` mismatched

- Expected
+ Received

  [
    "http://localhost:4321/session",
    "http://localhost:4321/session/foobar-123/element",
    "http://localhost:4321/session/foobar-123/elements",
-   "http://localhost:4321/session/foobar-123/element",
    "http://localhost:4321/session/foobar-123/execute/sync",
  ]

 ❯ packages/webdriverio/tests/commands/element/execute.test.ts:41:66



Error: TypeError: Cannot read properties of undefined (reading '0')
 ❯ packages/webdriverio/tests/commands/element/selectByVisibleText.test.ts:45:45



Error: TypeError: Cannot read properties of undefined (reading '0')
 ❯ packages/webdriverio/tests/commands/element/selectByVisibleText.test.ts:65:45



Error: TypeError: Cannot read properties of undefined (reading '0')
 ❯ packages/webdriverio/tests/commands/element/selectByVisibleText.test.ts:85:45



Error: TypeError: Cannot read properties of undefined (reading '0')
 ❯ packages/webdriverio/tests/commands/element/selectByVisibleText.test.ts:105:45



Error: TypeError: Cannot read properties of undefined (reading '0')
 ❯ packages/webdriverio/tests/commands/element/selectByVisibleText.test.ts:125:45



Error: TypeError: Cannot read properties of undefined (reading '0')
 ❯ packages/webdriverio/tests/commands/element/selectByVisibleText.test.ts:145:45


 ELIFECYCLE  Command failed with exit code 1.
Error: Process completed with exit code 1.

@vishnuv688
Copy link
Member Author

vishnuv688 commented Jul 23, 2025

@christian-bromann Resolved the issue

Copy link
Member

@christian-bromann christian-bromann left a comment

Choose a reason for hiding this comment

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

LGTM 👍

Great job!

@christian-bromann christian-bromann merged commit 1caf4b0 into webdriverio:main Jul 23, 2025
43 checks passed
@jeremiewtd
Copy link

Hey,
Is there a new release planned for this fix?
Thank you

@christian-bromann
Copy link
Member

Yes, we will put out a release soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR: Bug Fix 🐛 PRs that contain bug fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants