Search This Blog

Breaking

Thursday, 23 December 2021

December 23, 2021

How to access shadow dom [Closed] element in selenium?

Recently someone posted a challenge in linked to fill value inside a field. It looks a simple problem as from UI page, it was just a normal input field. I tried to check the dom for the element, and got to know that this is inside closed shadow dom.

So if you also find an element inside shadow dom which is closed, it means it can not be interactable. So the first approach to solve such issue is to connect with your developer teams. Yes, they can provide you an alternate way to access that element (at least in lower environment.)

But if this is not possible, then use selenium keypress method by using a common use case of an end user.

The same way I solved that challenge also. :) 

So, Just think, that this field is not accessible from mouse. In this situation, usually we interact on the page items with keyboard "TAB" key. Same approach, we can take here as well.

We just need to find an element which is accessible from selenium usual locator finding techniques, bring focus to that element, sometimes just by clicking on it or if it is an input field, just by passing a empty string, then press tab key until you reach to that element.

Bingo, you are now inside that field, now if you need to perform:

1. Click on that element, press "Enter" key

2. If it is an input field, you can simply use "send_keys" method

To demonstrate it, I created a sample page having shadow root as closed in it.











In the above page, the "Age field " is not inside any shadow dom element. And the first name and last name fields are inside the shadow dom[closed].

So to enter value inside the firstname field, I entered value or bring my focus to "Age field " first. And then I used "Tab Key" which brought me to the "First name" field. 

Once, My focus is available in the first field, I used action class to send my input to that field.

driver.get('file:///C:/Users/username/Documents/shadowDom.html')

driver.maximize_window()

ageElement = driver.find_element(By.ID, 'age')

ageElement.send_keys(30)

ageElement.send_keys(Keys.TAB)

actions = ActionChains(driver)

actions.send_keys("My name")

actions.perform()

sleep(10)

driver.quit()


Check the other post, how to interact with an element which is inside shadow dom [Open] tag.

Wednesday, 22 December 2021

December 22, 2021

How to access shadow dom [Open] element in selenium?

Recently, I saw in stack overflow that many people were posting question that they are not able to get element which is inside a shadow DOM. So I tried to solve this problem. Below is my learning:


1. If the element is inside the shadow root, first check that is that shadow root is open or close. If it is Open, than you can directly access it by using java script executor.

2. If the element is inside the shadow root which is closed, you can not use it. If you need to interact with such element, you can use keyboard key press operations.


So the first application which I got was an application where the shadow root was open. So it became easy for me. My take here is, first check your locator in developer console. I will explain how we can do it.


So lets first open a page  where this issue occurs . And the easy to accessible page is your chrome download page. If you will inspect "Search Downloads"  element on that page, you will find that it is inside shadow root.












So if we try to find element by using xpath, the xpath value is : '//*[@id="searchInput"]

But if you will try to search this XPATH, you will find it is not highlighting the element. And if you use it in your code, then you will see below error:









So the reason for it's not working is not that your xpath is not correct, it's just that this element is present inside shadow root element.

And if any element is present inside shadow root [Open], you can not access it with normal locator strategies. 

So to access this element, you will have to first find css locator for the topmost element from where the shadow root starts. In this page, it is from the beginning. So just find the locator of the element which is before the shadow root.












Here it is : body > downloads-manager

Now, you will move to find the second shadow root and you need to find the locator of element before that element.

Here it is: #toolbar


















Similar way, when we reach to the input field, we see 2 more shadow root. When we find the css locator of elements before that shadow root, it's like:

Third element : #toolbar
Fourth element: #search

And then at the end, our element appears and it's css locator is : #search

So now, we have all the locators, let's test these locators in browsers console page.

So to execute the CSS locator in browser console page, we use below method:

document.querySelector()

So now we will give our first locator to this:

document.querySelector('body > downloads-manager')

After this, we have our first shadow root. So to navigate inside the shadow root, we use below method:
shadowRoot.querySelector()

So now our locator will become:

document.querySelector('body > downloads-manager').shadowRoot.querySelector('#toolbar')

Similarly, we will have to add all our shadow root locator.

The final output will be like:

document.querySelector('body > downloads-manager').shadowRoot.querySelector('#toolbar').shadowRoot.querySelector('#toolbar').shadowRoot.querySelector('#search').shadowRoot.querySelector('#searchInput')


Now when you will hit this element in your developer console, you will see it is highlighting the element.









Now this, entire locator, we will have to use in our selenium code. (Python)

driver.get('chrome://downloads/')
driver.maximize_window()

# Using java script executor

searchDownload = driver.execute_script("return document.querySelector('body > downloads-manager').shadowRoot.querySelector('#toolbar').shadowRoot.querySelector('#toolbar').shadowRoot.querySelector('#search').shadowRoot.querySelector('#searchInput')")

searchDownload.send_keys("Order_ID_2363900762.pdf")
sleep(10)
driver.quit()

And when you will run this code, it will enter your text inside the field.













So this is how you can enter text inside a shadow root element.

Wednesday, 8 December 2021

December 08, 2021

[Jenkins] Conditional statement in pipeline job

If we have a pipeline job and if we want to trigger build based on some conditions, we can use if -else statement in the pipeline. I faced this situation for my master parallel job which was used for calling other jobs. Now, I need to call those jobs based on the choices or environment, so I try to put an if- else condition there.

Below is one sample pipeline, which executes code based on your choice parameter.







    



 


pipeline {

    agent any

    tools {

        maven 'Maven3'

        jdk 'java8'

    }

    

     parameters {

        choice(choices: ['QA', 'stage', 'dev'], description: 'Which Env?', name: 'PickYourEnv')

    }

    

    stages {

        stage('Build') {

            steps {

                 script {

                     echo "This is environment name : " + String.valueOf(params.PickYourEnv)

                       currentBuild.description = "${params.PickYourEnv}"; 

                    if (String.valueOf(params.PickYourEnv) == 'QA') {

                        echo 'I only execute on the master branch'

                        git 'https://github.com/qamatters/KarateDemo.git'

                        bat "mvn clean test -DargLine='-Dkarate.env=e2e' -Dtest=CucumberReport -DfailIfNoTests=false"

                    } 

                    else {

                        echo 'I execute elsewhere'

                    }

            }

    }

            post {

                // If Maven was able to run the tests, even if some of the test

                // failed, record the test results and archive the jar file.

                success {

                    cucumber buildStatus: 'null', customCssFiles: '', customJsFiles: '', failedFeaturesNumber: -1, failedScenariosNumber: -1, failedStepsNumber: -1, fileIncludePattern: '**/target/karate-reports/*json', pendingStepsNumber: -1, skippedStepsNumber: -1, sortingMethod: 'ALPHABETICAL', undefinedStepsNumber: -1

                }

            }

        }

    }

}


Tuesday, 7 December 2021

December 07, 2021

[Jenkins] [Fix]Maven: WARNING Unable to autodetect 'javac' path, using 'javac' from the environment

Recently, I need to re-install Jenkin in my local machine because of some issues. I didn't save the local data copy, so I have to start freshly again when I re-installed Jenkin. One more issue I observed, that from my machine JDK is also removed.













As I was looking quickly toto trigger a job, So I thought to install java and maven from the Jenkin itself.

I installed Jenkin (it needs JRE/JDK), navigated to Global tool configurations from Manage Jenkin link, and added my (oracle) cred to download JDK (Oracle cred is needed to install Jenkin).

Then, I added maven.










I saved these changes. Then I create a new pipeline job.

When I ran that pipeline job, I started getting this issue, "Maven: WARNING Unable to autodetect 'javac' path, using 'javac' from the environment". As Java is installed from Jenkin itself, I was expecting it to figure out the path as well.

I checked my pipeline script and observed that, I missed the tools section in it.

Once I added it, it identified the installed java and removed the above mentioned error.