How to target an element inside shadowRoot (user-agent) in Puppeteer - testing

could you please help me with targeting the concrete element in e2e test?
I´m using Jest and Puppeteer and I have this DOM structure (see in attachment below):
And I need to target the red underlined element. How would you target that element?
I tried it like this,
const inputContent = await page.findAll(
'usu-date-picker >>> .sc-usu-input >>> div',
);
console.log(inputContent[1]);
but what I got returned was element with type node "INPUT", which I don´t understand why.
Thank you for your help.

you can use this:
await page.evaluate( () =>
document.querySelector("#date-picker")
.shadowRoot.querySelector("usu-input > div > input")
.shadowRoot.querySelector("div:nth-child(2)").value
);
You should try the query in the devtools console to see if you are doing it right
Example from devtools console

Related

I want to trigger the text using mouseover in cypress with javascript?

cy.xpath("(//[local-name()='svg']//[name()='g' and #data-z-index='8'])[1]//*[name()='text']").wait(300)
.trigger('mouseover', { force: true }).then(($text1) => {
var textValue2 = $text1.text()
cy.log(textValue2)
})
This is code I'm using triggering to perform mouseover to get the text
facing error not finding the element showing "Timed out retrying after 4000ms: Expected to find element: (//[local-name()='svg']//[name()='g' and #data-z-index='8'])[1]//*[name()='text'], but never found it."
Note: But the xpath is correct, If I manually hover then retrieve the text.
Use trigger('mouseenter') it should works

Protractor getting DOM element and using their properties

I'm running e2e tests with Protractor and Selenium on a Polymer/Angular App.
Most of the elements are in the shadow DOM (I managed to handle it with custom css locators but it made my tests unstable as any change in the dom breaks them). The problem is that the devs have implemented a virtual scroll list :
Only a few items are loaded in the scroll list, next ones are loaded when you scroll.
I asked my devs how to deal with it and they told me I had to get the web-component and test it without protractor aka running commands like this :
document.querySelector('virtual-scroll').baseList
Where baseList is a public property of the tag.
I tried
var element = browser.executeScript('return document.querySelector("virtual-scroll")');
element.then(function (el){
console.log(el.$.baseList);
});
but the command above returns a WebElement. Is there any way to return the HTML DOM element as a javascript querySelector command does ?
EDIT : as requested the source code with the property of the scrollList that I want to get
If "virtual-scroll" is name of the shadow root element and baseList is an attribute of the element. You can get it with command below.
var baseList = browser.executeScript('return document.querySelector("virtual-scroll").baseList');
By the way, you can test the shadow DOM with Selenium. See an example below.
var shadowRootElement = browser.executeScript('return document.querySelector("virtual-scroll").shadowRoot');
var element = shadowRootElement.findElement(......);

Why using inbuilt webdriver wait yields an error "ReferenceError: until is not defined"?

Webdriverjs apparently has an inbuilt method which allows you to wait for an element.
var saveButton = driver.wait(until.elementLocated(By.xpath("//div[text() = 'Save']")), 5000);
driver.wait(until.elementIsVisible(saveButton), 5000).click();
Using this method results in an error "ReferenceError: until is not defined".
Why is this method not working?
The most common best practice is to require webdriver.By and webdriver.until at the top of your file right after you require webdriver.
then you don't have to do webdriver.By inside your tests, you can do driver(By.css())
I read the webdriverjs docs and the example given there is missing 'webdriver' keyword.
var saveButton = driver.wait(webdriver.until.elementLocated(webdriver.By.xpath("//div[text() = 'Save']")), 5000);
driver.wait(until.elementIsVisible(saveButton), 5000).click();
Adding 'webdriver' keyword before 'until' and 'By' solves the issue.
I am not sure the language binding you are using. Using Java bindings, in Selenium 3.x releases until must be accompanied by ExpectedConditions
So, to apply ExplicitWait on an element & click it, your code must look like:
WebDriverWait wait = new WebDriverWait(driver, 5);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[text() = 'Save']")));
element.click();
Let me know if this solves your Question.

How can i write my own xpath from the html code

I have followig HTML code and want X path for the text "Analytics & Research"
<div id="LLCompositePageContainer" class="column-wrapper">
<div id="compositePageTitleDiv">
<h1 class="page-header">Analytics & Research</h1>
</div>
I am getting following xpath using chrome, but that didnt work.
//*[#id="compositePageTitleDiv"]
this is my code
WebElement header = driver.findElement(By.xpath("//div[#id='LLCompositePageContainer']/div[#id='compositePageTitleDiv']/h1[#class='page-header']"));
String header2 = header.getText();
System.out.println(header2);
and following error I am getting
Exception in thread "main" org.openqa.selenium.NoSuchElementException:
Unable to find element with xpath ==
//div[#id='LLCompositePageContainer']/div[#id='compositePageTitleDiv']/h1[#class='page-header']
(WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 10.34 seconds For documentation on this
error, please visit:
http://seleniumhq.org/exceptions/no_such_element.html
Please try to use the below xpath:
driver.findElement(By.xpath(".//div[#id='compositePageTitleDiv']/h1")).getText();
If the element is inside the iframe. Then use the below code:
// Switching to the frame
driver.switchTo().frame(<name>);
// Storing the value of the Analytics & Research
String text = driver.findElement(By.xpath(".//div[#id='compositePageTitleDiv']/h1")).getText();
// Switching back to original window
driver.switchTo().defaultContent();
Hope this helps.
This is how it can be used :
WebElement element= driver.findElement(By.xpath("//*[#id='compositePageTitleDiv']"));
Or in case it is nested, can be accessed like this as well
WebElement element = driver.findElement(By.xpath("//html/body/div[3]/div[3]/"));
this is just a rough syntax.
No need to use Xpath here if you could simply locate the element using By.id(). Asuming are using Java, you should try as below :-
WebElement el = drive.findElement(By.id("compositePageTitleDiv"));
String text = el.getText();
Edited :- If element not found, may it is timing issues you need to implement WebDriverWait to wait for element until visible on the page as below :-
WebDriverWait wait = new WebDriverWait(webDriver, implicitWait);
WebElement el = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("compositePageTitleDiv")));
String text = el.getText();
Note :- if your element is inside any frame, you need to switch that frame before finding element as :- driver.switchTo().frame("your frame name or id");
Hope it helps..:)
You can also use
//div[#id='LLCompositePageContainer']/div[#id='compositePageTitleDiv']/
h1[contains(text(),'Analytics')]
This is the best way to reach to the specific web element, using contains minimize the chances of error.
The correct xpath is
//div[#id='LLCompositePageContainer']
/div[#id='compositePageTitleDiv']
/h1[#class='page-header']
But you could have find your answer easily with some researchs on google...

nightwatch selenium command "elements" returns error about first parameter, even when I pass in a css selector or xpath expression

I'm using nightwatch with selenium for automation testing. I'm trying to use the selenium command 'elements' which takes a css selector or xpath as the first parameter, but keep getting the following error :
Error while running elements command: Please provide any of the following using strings as the first parameter: class name, css selector, id, name, link text, partial link text, tag name or xpath
My use is like this:
module.exports = {
"My test" : function (browser) {
...
// want to get all the input elements from the document
browser.elements('input','name', function(els){
// of xpath like this
browser.elements('//input','name', function(els){
});
}
}
Any ideas why I'm getting this error? Thanks!
Ah I figured it out - the first param is a keyword which has to be one of these (from nightwatch selenium protocols.js)
var check = /class name|css selector|id|name|link text|partial link text|tag name|xpath/gi;
So the command needs to look like this :
browser.elements('tag name', 'input', function(el){
})