Native Automation support for Shadow DOM – with WebDriverIO and Cypress {Chapter 3}
The last stage of the Shadow DOM battle is yet to win – so be ready to handle it natively. After going through the previous chapters {Anatomy of Shadow DOM & W3C Webdriver support for Shadow DOM} of this series, now we have strong fundamentals about Shadow DOM. So let’s win the last stage and learn native Automation support for Shadow DOM by using few open-source frameworks.
For Shadow DOM, Which frameworks do we need to choose if we are starting automation from scratch?
If your Test Automation team is well known to JavScript then we can opt for any one of the following frameworks, because both support Shadow DOM natively.
- WebdriverIO framework v5.5.0+
- Cypress framework v5.2.0+
WebDriverIO {wrapper over W3C Webdriver} framework over Shadow DOM
WebdriverIO v5.5.0 introduced native Automation support for Shadow DOM via two new commands, shadow$ and shadow$$:
- shadow$ – Access single element inside a given element’s shadowRoot
- shadow$$ – Access more than one elements inside a given element’s shadowRoot
In our test application, we have multi-level shadow roots so we need to chain $ command and shadow$ commands as deeply as needed. First of all, with the help of $ command, we will reach out to Shadow Host element i.e. id=todo-app, then by using shadow$ commands, we will reach out to Shadow Root elements i.e. id=adds-item and then id=enter-text-area. For more clarity, have a look at below screenshot:
browser.$('#todo-app').shadow$('#adds-item').shadow$('#enter-text-area');
In our script, we will take two actions on Shadow DOM elements:
- Enter some text inside the element ‘enter-text-area’
- Click ‘btn-enter’ element
WebDriverIO JS code snippet {GitHub repo} >>
get inputTaskName () { return browser.$('#todo-app').shadow$('#adds-item').shadow$('#enter-text-area'); }
get enterButton () { return browser.$('#todo-app').shadow$('#adds-item').shadow$('.btn-enter'); }
enterTodayTaskName (todayTaskName) {
this.inputTaskName.setValue(todayTaskName);
this.enterButton.click();
}
[ Working demo of WebDriverIO JS scripts ]
Cypress framework over Shadow DOM
Cypress v5.2.0 introduced native Automation support for Shadow DOM via command shadow(selector), that traverse into the Shadow DOM to find the element:
- shadow() – Traverse into the shadow DOM of an element
In our test application, we have multi-level shadow roots so we need to chain the shadow() method as deeply as needed. First of all, with the help of get() method, we will reach out to Shadow Host element i.e. id=todo-app, then by using shadow() meethod, we will reach out to Shadow Root elements i.e. id=adds-item and then id=enter-text-area. For more clarity, have a look at below screenshot:
cy
.get('#todo-app')
.shadow().find('#adds-item')
.shadow().find('#enter-text-area');
Cypress JS code snippet {GitHub repo} >>
describe('Example to demonstrate the handling of Shadow Dom in Cypress', () => { before(() => { cy.visit('http://localhost:3000/') }) it('Input a text in the plan box and add it to todays list', () => { cy.get('#todo-app').shadow().find('#adds-
item').shadow().find('#enter-text-area')
.type('Shadow DOM') cy.get('#todo-app').shadow().find('#adds-
item').shadow().find('.btn-enter') .click() }) })
[ Working demo of Cypress JS scripts ]
📍📍 Special case – What if Shadow DOM resides inside iFrame? Handling would be still the same but Webdriver needs to switch context before taking any action on iFrame’s Shadow DOM elements.
Key Takeaways
- Aware of JS based frameworks that natively support Shadow DOM.
- Got to know the way of native handling of Shadow DOM by using WebDriverIO.
- Better known in-built of handling Shadow DOM by using WebDriverIO.
- Understood – handling of Shadow DOM, if they reside inside the iFrame.
So it’s time to bring down the curtain – the Shadow DOM automation series ending here. Let’s get your hands dirty with Shadow DOM and its elements!!
For further discussion or any doubts – please comment below and start open collaboration over Shadow DOM 👍👍👍👍