Selenium Java: Accept All Cookies in ShadowRoot - javascript

This is my web address:
DM :
This is my locator for button accept all:
#FindBy( xpath = "//button[#data-testid = 'uc-accept-all-button']")
WebElement cookies;
This is HTML:
I use selenium 4 and Java. I try solution like this :
public void acceptAllCookies( ) {
cookies = driver.executeScript("return document.querySelector('#usercentrics-root').shadowRoot.querySelector("cookies")");
cookies.click();
}
But it does not work. I have error like this:
Any help please. I am a beginner so i see this for first time
I try to add more " marks like in solution I find here but then I get whole executeScript like text.

You would need to use escape sequence in "cookies"
See below
cookies = driver.executeScript("return document.querySelector('#usercentrics-root').shadowRoot.querySelector(\"cookies\")");

You have to either use single quotes around cookie in js.executeScript method if your css selector is cookie not java variable. And Cookie defined above is WebElement which can not be directly used while calling executeScript method.
cookies = driver.executeScript("return document.querySelector('#usercentrics-root').querySelector(button[data-testid = 'uc-accept-all-button'])");
And this does not solve your problem, please explain your issue in details.

The element Prihvatite sve button is within #shadow-root (open)
Solution
To click on the desired element you need to use querySelector() and you can use the following locator strategies:
driver.get("https://www.dm.rs/?wt_mc=sea.google.ads_generic.15146192844.132927670207.558370268562");
Thread.sleep(5000);
WebElement element = driver.findElement(By.cssSelector("#usercentrics-root"));
SearchContext context = element.getShadowRoot();
WebElement cookieAcceptAll = context.findElement(By.cssSelector("button[data-testid='uc-accept-all-button']"));
cookieAcceptAll.click();
References
You can find a couple of relevant detailed discussions in:
How to automate shadow DOM elements using selenium?
How to locate the First Name element within #shadow-root (open) using Selenium4 and Java

Related

How to make a JS Slider work on Karate DSL UI [duplicate]

Firstly, Karate UI automation is really awesome tool. I am kind of enjoying it while writing the UI tests using Karate. I ran into a situation where in, i was trying to fetch the shadowRoot elements. I read few similar posts related to javascript executor with karate and learnt that it is already answered. it is recommended to use driver.eval. But in Karate 0.9.5 there is no eval, it has script() or scriptAll(). I have gone through documentation couple of times to figure out how i can fetch element inside an element but no luck.
Using traditional selenium+java, we can fetch shadowRoot like this way:
something like shadowRoot which sits inside a parent element like div or body.
//downloads-manager is the tagname and under that downloads-manager, a shadowRoot element exists
The HTML looks like this. it is from chrome://downloads.
<downloads-manager>
#shadow-root(open)
</download-manager>
WebElement downloadManager =driver.findElement(By.tagName("downloads-manager");
WebElement shadowRoot= (WebElement)((JavaScriptExecutor)driver)
.executeScript("return arguments[0].shadowRoot",downloadManager);
So i tried the following in Karate UI
script("downloads-manager","return _.shadowRoot"); //js injection error
script('downloads-manager', "function(e){ return e.shadowRoot;}"); // same injection error as mentioned above.
def shadowRoot = locate("downloads-manager").script("function(e){return e.shadowRoot};"); //returns an empty string.
I bet there is a way to get this shadowRoot element using Karate UI but i am kind of running out of options and not able to figure out this.
Can someone please look into this & help me?
-San
Can you switch to XPath and see if that helps:
* def temp = script('//downloads-manager', '_.innerHTML')
Else please submit a sample in this format so we can debug: https://github.com/intuit/karate/tree/develop/examples/ui-test
EDIT: after you posted the link to that hangouts example in the comments, I figured out the JS that would work:
* driver 'http://html5-demos.appspot.com/hangouts'
* waitFor('#hangouts')
* def heading = script('hangout-module', "_.shadowRoot.querySelector('h1').textContent")
* match heading == 'Paul Irish'
It took some trial and error and fiddling with the DevTools console to figure this out. So the good news is that it is possible, you can use any JS you need, and you do need to know which HTML element to call .shadowRoot on.
EDIT: for other examples of JS in Karate: https://stackoverflow.com/a/60800181/143475

Get dom element by ID in WebView UWP

I intend to get the content of a dom element from a website, I cant use
var html = await client.GetAsync("http://example.com/test.html");
as the specific dom element is populated after the JS is executed
I can use a webview to host the content but that won't solve the problem
I can't use HtmlDocument.GetElementById Method (String) either as it is under System.Windows.Forms namespace which isn't supported in Universal Windows Platform!
Another option would be InvokeAsync
await webView5.InvokeScriptAsync("doSomething", null);  
as seen in scenario 5 of XAML WebView control sample
but that just fires events and won't help in getting the dom element (or even the source code once the JS execution done).
//The app is a C# UWP, not Winjs
You can use HtmlAgilityPack library to query DOM you downloaded. See example here or search for more, there are plenty.
Alternatively, you can run javascript which does what you need and returns a string containing your ID. As you see, InvokeScriptAsync returns String which can contain anything your javascript returned. F.e., this is how to get DOM with javascript:
var result = await this.webView.InvokeScriptAsync("eval", new[] { "document.documentElement.outerHTML;" });

I need Selenium JavascriptExecutor to return an element via jquery

I am at my wits end with this and I'm sure the answer is simple but I just can't figure it out.
I've got a jquery selector that finds and element perfectly when I put this in the console of google Chrome:
$(".answer__label:contains('Yes')")
Now I want to use this to retrieve an element in a WebDriver test, so I'm using JavascriptExecutor in the following way:
private WebElement findByJSText(String text) {
String script = String.format("return ('.answer__label:contains('%s')')", text);
WebElement element = (WebElement) ((JavascriptExecutor)driver).executeScript(script);
return element;
}
This gives the error, "missing ) in parenthetical". I've seen references to this error all over, but none that seem to apply to my situation.
How do I massage this to return the element properly?
(please don't respond telling me to use driver.findElement(By.linkText), thanks)
ADDENDUM
Here's what my final working method looks like:
private WebElement findByJSText(String text) {
//String script = String.format("return $('.answer__label:contains('%s')')", text);
String script = String.format("return $(\".answer__label:contains('%s')\")[0]", text);
WebElement element = (WebElement) ((JavascriptExecutor)driver).executeScript(script);
return element;
}
I may add a 2nd parameter for a css string to make this more flexible.
Thanks all for the help!
In this line:
String script = String.format("return ('.answer__label:contains('%s')')", text);
Your javascript code is error, where is the jquery $ function? Correct js code should be:
String script = String.format("return $('.answer__label:contains('%s')')", text);
Edit:
You have the ' within another '. Thats the problem, I tried the following js code and its working fine for me:
String script = String.format("return $(\".answer__label:contains('%s')\")", text);

How to identify a hidden file element in selenium webdriver

Team,
I am trying to automate a file upload functionality but webdriver doesn't recognize the file object. Here is the thing:
The file object is in a modalbox (xpath is of the modal box is //*[#id='modalBoxBody']/div[1]). The type and name of the file object are file and url respectively.
When i see the html content, there are two objects with the same attributes. One of them is visible and another is invisible. But the hierarchy they belong to are different. So I am using the hierarchy where the element is visible.
Following is my code. I have tried all possible solutions provided in the stackoverflow (as much as I could search), but nothing worked. Commented out sections mean that they too are tried and failed.
wbdv.findElement(By.xpath("//*[#id='left-container']/div[4]/ul/li/ul/li[2]/a")).click();
wbdv.switchTo().activeElement();
System.out.println(wbdv.findElement(By.xpath("//*[#id='modalBoxBody']/div[1]")).isDisplayed()); **//This returns true**
List<WebElement> we = wbdv.findElement(By.xpath("//*[#id='modalBoxBody']/div[1]")).findElement(By.className("modalBoxBodyContent")).findElements(By.name("url")); **//There is only one element named url in this hierarchy**
System.out.println(we.isEmpty()); //This returns false meaning it got the element named url
//((JavascriptExecutor) wbdv).executeScript("document.getElementsByName('url')[0].style.display='block';"); **//This didn't work**
for(WebElement ele: we){
String js = "arguments[0].style.height='auto'; arguments[0].style.visibility='visible';";
((JavascriptExecutor) wbdv).executeScript(js, ele);
System.out.println(ele.isDisplayed()); **//This returns FALSE**
System.out.println(ele.isEnabled()); **//This returns TRUE**
System.out.println(ele.isSelected()); **//This returns FALSE**
ele.click(); **//This throws org.openqa.selenium.ElementNotVisibleException exception**
}
Now, if you look at the 3 methods above, it seems that the element is NOT displayed, NOT selected but IS enabled. So when it is not displayed, selenium cannot identify it. The java script to make it visible also came to no rescue.
Could anyone please help me solve this. It ate my entire day today?
In your last example, it looks to me like you have the right idea with using the 'style.visibility' tag. Another thing that I would recommend trying is using "ExpectedConditions.visibilityOfElementLocatedBy" method. Usually I use "presenceOfElementLocatedBy", but if you are talking about the css visibility property, I think using "visibilityOfElementLocatedBy" is the way to go. I think what might be happening for you is that you need the wait condition on the element object you are trying to get a hold of and the "ExpectedCondtions" method should give you what you need. I see that you have tried a few things but you haven't listed using a Wait condition. No guarantees, but you should try it:
WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.visibilityOfElementLocated(
By.xpath(".//whatever")))

Overwrite a javascript variable from webdriver

I'm not sure whether is there any solution for my issue but, unfortunately I haven't found any article or information about it.
The situation is the following. We have a site which uses jQuery heavily and there is a service which refreshes a part of the site in every 5th or 10th second. Due to this half of the time I got this error from WebDriver:
"Element not found in the cache - perhaps the page has changed since it was looked up"
According to the Internet I got this error when the DOM tree has changed between the moment when the WebElement has been initialized and when I want to use it to perform, for example, a click event.
According to our developers our jquery solution has a variable which controls whether the page will be refreshed or not. So, to solve my issue I have to overwrite this variable. I have to overwrite this variable in that way the jQuery will be able to understand it - I mean in the same instance if this definition is proper in this context.
So, I would like to ask whether is possible or not? If so, than I would like to ask a small example.
Thanks in advance!
András
I can only agree with Aleh.
Using JavaScriptExecutor is the only way to handle such issues.
I had a problem with jQuery jNice library and couldn't find any other solution.
Here is an example in Java for filling a text field:
JavascriptExecutor js = (JavascriptExecutor) webDriver;
js.executeScript("document.getElementsByName('<field_name_gets_here>')[0].value='" + your_value + "'");
If the JavaScript variable you mentioned is global, then yes - you can overwrite it by executing JavaScript from your Selenium. For example, if that variable is called doRefresh, you can overwrite it by executing JS like this: doRefresh = false; from Selenium.
If that variable is not global, the above won't work. However, it sounds like the elements in question might be dynamically loaded via ajax - in which case the xhr object is global and you can access it instead.
So, first you can make a local copy of the xhr object and then overwrite the original (effectively disabling it) by executing JavaScript from Selenium:
// create a copy of the xhr object for later use
var xhrHolder = window.XMLHttpRequest;
// overwrite the original object to disable it
window.XMLHttpRequest = {};
Then find your element via Selenium as you would normally. And proceed with your test.
When finished, you can put the xhr object back in place (so the page can continue refreshing and doing ajax) by executing JavaScript from Selenium:
// put the xhr object back
window.XMLHttpRequest = xhrHolder;
You can try my approach - I created my own wrapper for situations where page might be loading. The below part of code tries to search element in the loop, for three seconds (configurable). BTW the driver variable below is instance of WebDriver
private WebElement foundElement;
public WebElement find(By by){
for (int milis=0; milis<3000; milis = milis+200){
try{
foundElement = driver.findElement(by);
}catch (Exception e){
try {
Thread.sleep(200);
} catch (InterruptedException e1) {
e1.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
}
return foundElement;
}
And later in the code:
WebElement submitButton = find(By.id("submitNewBid"));
submitButton.click();
I believe it is possible. Example for c#:
((IJavaScriptExecutor)driver).ExecuteScript("window.$('.class').data('var') = 0;")

Categories