Selenium webdriver : How to get embedded image data using JavaScripts? - java

I have to get the src from below mentioned html, please let me know how can I get the embedded image data? Is this possible using JS? If there is any way to show to the hide elements? I am using Selenium web driver with Java.
<div id="sc859" class="atv4 alc sc-view c-image sc-hidden" style="left: 0px; right: 0px; top: 0px; bottom: 0px">
<img style="height: 100%; width: 100%;" src="data:image/gif;base64,R0lGODlhAQABAJAAAP///wAAACH5BAUQAAAALAAAAAABAAEAAAICBAEAOw==" class="alc-img"/>
</div>
My code:
JavascriptExecutor jse = (JavascriptExecutor)driver;
WebElement element = driver.findElement(By.cssSelector("#sc859"));
String imgeJs = (String) jse.executeScript("document.getElementsById('sc859')[0].getAttribute('src');", element);
System.out.println(imgeJs);

Try this:
WebElement div = driver.findElement(By.id("sc859"));
String image = div.findElement(By.className("alc-img")).getAttribute("src");
System.out.println(image);

I never had luck using document.getElementsById('sc859')[0].getAttribute('src');" before. I always execute script directly like the following. Hope this is what you wanted. And, src does not exist on div rather on following img tag so your selector was wrong.
String src = (String) ((JavascriptExecutor)driver).executeScript("return document.querySelector(\"#sc859>img\").getAttribute(\"src\");");
System.out.println(src);
Print
data:image/gif;base64,R0lGODlhAQABAJAAAP///wAAACH5BAUQAAAALAAAAAABAAEAAAICBAEAOw==

No need to use JavaScript, also, you can shorten Francesco's answer like this:
String src = driver.findElement(By.cssSelector("#sc859 > img.alc-img")).getAttribute("src");

There are 3 things u r doing wrong -
1 - getElementsById its getElementById which will return you only single element not a collection of it. There is no method getElementsById as far as i know.
2 - you are missing return in your executeScript method.
3 - There is no src attribute attached to div element whose id you have passed. src is attached to only img attribute.
So finally your code should be something like:
String imgeJs = jse.executeScript("return document.getElementById('sc859').childNodes[1].getAttribute('src')").toString();
or you can also achieve it by:
WebElement element = driver.findElement(By.cssSelector("#sc859" > img.alc-img));
String imgeJs = jse.executeScript("return arguments[0].getAttribute('src')", element).toString();
Or else follow rest of the answers where you can simply get it done by element.getAttribute("src") method of WebElement interface.

Related

How to create a list of the autocomplete <li> elements when parent <ul> element contains the attribute style="display: none;" through Java Selenium

I'm using Java selenium to create a automation project. Now in our web app, there is address input box and has autocomplete feature. The problem is after input a partial address, we need click one of the option from the list. Here is the html:
Now I have tried to get the list. But failed:
WebElement autoCompelet = driver.findElement(By.xpath("/html/body/ul[1]"));
List<WebElement> options = autoCompelet.findElements(By.tagName("li"));
logger.debug(options.size());
for (WebElement option1 : options) {
logger.debug(option1);
}
I can print out , but list is empty.
I've also tried to use wait method like:
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("/html/body/ul[1]/li[1]")));
Unfortunately, none of them works. Is anyone has any idea on this? Any input is appreciated. Thank you guys.
By.className("li") is invalid,the value should be the class name,need to use By.tagName("li") instead.
Also you can change your xpath to get ul by class and then get li directly
WebElement autoCompelet = driver.findElement(By.xpath("//ul[#class='af_list']"));
List<WebElement> options = autoCompelet.findElements(By.tagName("li"));
logger.debug(options.size());
for (WebElement option1 : options) {
logger.debug(option1);
}
You can try as below.
//wait is added in order to check the presence of autocomplete suggestion
WebDriverWait wait=new WebDriverWait(driver,20);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.className("af_list")));
List<WebElement> options = driver.findElements(By.xpath("//ul[#class='af_list']/li"));
logger.debug(options.size());
for (WebElement option1 : options) {
logger.debug(option1.getText());
}
Note: I have assumed af_list class name is used only in the autocomplete.If it is used in other section as well, then please share the full html detail
You can try something like this , after having all the <li> elements in a list, you can easily get the text of each web element by using getText() method which is available in selenium Java binding.
List<WebElement> options = driver.findElements(By.cssSelector("ul.af_list li"));
System.out.println(options.size());
logger.debug(options.size());
for(WebElement options1 : options)
{
logger.debug(options1.getText());
}
Note that it is always a good practice to use css selector over xpath.
You may want to introduce webDriverWait for your scenario. That would explicitly wait for all <li> elements to be present/available in list.
Hope this will help.
As per the HTML you have shared, the desired elements i.e. the <li> tags are within a <ul> tag which is having the attribute style="display: none;". So to access the <li> tags you can use the following solution:
WebElement autoCompelet = driver.findElement(By.xpath("//ul[#class='af_list']"));
((JavascriptExecutor)driver).executeScript("arguments[0].removeAttribute('style')", autoCompelet);
List<WebElement> options = autoCompelet.findElements(By.xpath("./li[#class='af_item']"));
for (WebElement option1 : options) {
System.out.println(option1.getText());
}
I have a similar feature in our web application. In this case, you can use sendKeys() method with Keys.DOWN to literally go to that element and then Keys.ENTER to select it. Normally once you sendKeys() part of the text, the others start populating below, so you basically type to an extent until which just the first option in the populated dropdown texts is the one which you want. Then do sendKeys(Keys.DOWN) followed by sendKeys(Keys.ENTER)

How to get links who follow a pattern within specific section using xpath?

Here is what I'm trying to do:
I have some links on a webpage with this pattern:
/html/body/div[4]/div/div/section/div[2]/div[3]/div/div1/div1/div/div[2]/a
/html/body/div[4]/div/div/section/div[2]/div[3]/div/div1/div[2]/div/div[2]/a
/html/body/div[4]/div/div/section/div[2]/div[3]/div/div1/div[3]/div/div[2]/a
/html/body/div[4]/div/div/section/div[2]/div[3]/div/div1/div[4]/div/div[2]/a
However, I also have other links within the same web page that have a similar path but not exactly following the same pattern:
/html/body/div[4]/div/div/section/div[2]/div[3]/div/div[3]/div/div1/div1/div/div[2]/a
How can I get just the links which follow the first pattern displayed and ignore the other ones?
Ps: I'm using Selenium Webdriver and Java and this is the update question with the html for the links
<div class="col-sm-6 half-tile">
<div class="outside-caro">
<div class="grey-overlay">
<div class="inside-caro" style="background-image:url(' https://resources/images/metabolism.jpg'")>
</div>
</div>
<div class="tile-content">
<h4 class="module title-long-card">Healthy Weight Loss</h4>
<p class="module line-clamp">This online eLearning programme is designed to help you make smart decisions when it comes to dieting and to be aware of the pitfalls.</p>
<a class="more-button" href="/application/res-courses/overview?id=23">Learn More<i style="font-size: 10px;padding-left: 5px; "class="fa fa-chevron-right" aria-hidden="true"></i></a>
</div>
</div>
</div>
Thanks very much.
I'm not quite following what you're really hoping for from your description, but I can make some guesses.
The quick answer is, just always give the full path.
But there are ways to make things a little easier to code. There are a couple ways you can create a pointer on the page and to only look for things beyond that point. The most straightforward is using simple string concatenation:
String pointer = "/html/body/div[4]/div/div/section/div[2]/div[3]/div/div[1]";
WebElement tag1 = driver.findElement(By.xpath(pointer + "/div[1]/div/div[2]/a"));
WebElement tag2 = driver.findElement(By.xpath(pointer + "/div[2]/div/div[2]/a"));
The other is to declare that pointer as a WebElement, and then use it as a base for all future findElements:
WebElement pointer = driver.findElement(By.xpath("/html/body/div[4]/div/div/section/div[2]/div[3]/div/div[1]"));
WebElement tag1 = pointer.findElement(By.xpath("./div[1]/div/div[2]/a"));
WebElement tag2 = pointer.findElement(By.xpath("./div[2]/div/div[2]/a"));
Note the dot at the beginning of the xpath to say "Use this node as your starting point".
Now, what I think you're really trying to accomplish to to make a list of all the anchors, not just pick them one by one. As in "get all the link that match one pattern but not a different but similar pattern". For that, you could just do a variation of either of the two above methods. For instance:
WebElement pointer = driver.findElement(By.xpath("/html/body/div[4]/div/div/section/div[2]/div[3]/div/div[1]"));
List<WebElement> tags = pointer.findElement(By.xpath("./div/div/div[2]/a"));
This will pull in all the links that match the pattern into a List. There are a couple things to take note:
The first element is just div, not div[1] and div[2]. since that seems to be the only thing changing in the pattern.
Most likely, the language you will use to script this is 0-indexed. So div[1] is tags.get(0).
I have a solution to problem and i hope it will help you.
You just have to identify a single parent for all 4 links that you mentioned above. And i feel you can use this locator as parent node /html/body/div[4]/div/div/section/div[2]/div[3]/div/div[1]/div[1].
Please find my code..
System.setProperty("webdriver.chrome.driver","Drivers/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://www.abodeqa.com/2015/08/26/finding-child-elements-in-webdriver-using-findelements/");
Thread.sleep(3000);
WebElement parent = driver.findElement(By.xpath("//section[#class='secondary clearfix']"));
List<WebElement>childernNodes = parent.findElements(By.xpath("./aside//a"));
System.out.println("Total: "+childernNodes.size());
for(WebElement value: childernNodes){
System.out.println(value.getAttribute("href"));
}
WebElement pointer = driver.findElement(By.xpath("/html/body/div[4]/div/div/section/div[2]/div[3]/div/div[1]"));
// Generic path to simulate the change in the xpath for the elements of the following pattern:
// WebElement tag1 = pointer.findElement(By.xpath("./div[1]/div/div[2]/a"));
// WebElement tag2 = pointer.findElement(By.xpath("./div[2]/div/div[2]/a"));
List<WebElement> linksList = pointer.findElements(By.xpath("./div/div/div[2]/a"));
for (WebElement link : linksList) {
System.out.println(link.getAttribute("href"));
}

xpath does not get the web element which has multiple classes

I am very new at Java and Selenium so my apologies in advance if my question sounds a bit primary.
I am using Selenium and Java to write tests. But have issue with finding elements. I know some other ways to find this WebElement,
but why this:
WebElement we1 =driverChrome.findElement(By.xpath
("//div[contains(#class,'elfinder-cwd-filename ui-draggable') and #title='project.CPG']"));
can not get this:
<div class="elfinder-cwd-filename ui-draggable" title="project.CPG">project.CPG</div>
and shows this error:
Exception in thread "main" org.openqa.selenium.NoSuchElementException: no
such element: Unable to locate element:{"method":"xpath","selector":"
//div[contains(#class,'elfinder-cwd-filename ui-draggable') and #title='project.CPG']"}
this works:
WebElement we1 = driverChrome.findElement(By
.xpath("//div[contains(#class,'elfinder-cwd-filename') and #title='project.CPG']"));
but these ones do not work:
WebElement we1 = driverChrome.findElement(By
.xpath("//div[contains(#class,'ui-draggable') and #title='project.CPG']"));
WebElement we1 = driverChrome.findElement(By.
xpath("//div[#class='elfinder-cwd-filename ui-draggable' and #title='project.CPG']"));
Sounds weird, this:
WebElement we = driverChrome.findElement(By
.xpath("//div[contains(#class,'combine-red')]"));
just worked for this:
<div class="leaflet-marker-icon combine-red-off leaflet-zoom-hide leaflet-
clickable" tabindex="0" style="margin-left: -17px; margin-top: -19px; left:
149px; top: 302px; z-index: 10304; transform: rotate(450deg);"></div>
but why this:
WebElement we1 =driverChrome.findElement(By.xpath
("//div[contains(#class,'elfinder-cwd-filename ui-draggable') and #title='project.CPG']"));
can not get this:
<div class="elfinder-cwd-filename ui-draggable" title="project.CPG">project.CPG</div>
Its because of Selenium's Class selector does not support Compound class names. Its search for exact class name (any part of compound class name), but not compound class name.
This code:
WebElement we1 = driverChrome.findElement(By.
xpath("//div[#class='elfinder-cwd-filename ui-draggable' and #title='project.CPG']"));
possibly can not work if there is some extra spaces or if on page generation classnames was change its place... like:
'elfinder-cwd-filename ui-draggable''
'elfinder-cwd-filename ui-draggable '
or
'ui-draggable elfinder-cwd-filename'
and here...
WebElement we1 = driverChrome.findElement(By
.xpath("//div[contains(#class,'ui-draggable') and #title='project.CPG']"));
possibly you miss dot on the beginning. Try this:
WebElement we1 = driverChrome.findElement(By
.xpath(".//div[contains(#class,'ui-draggable') and #title='project.CPG']"));
When you write contains, try mentioning only one class without any space. IT should solve your issue. Here's how -
WebElement we1 =driverChrome.findElement(By.xpath
("//div[contains(#class,'elfinder-cwd-filename') and #title='project.CPG']"));
If you want to mention both the classes then give that without contains tag. Here's how -
WebElement we1 =driverChrome.findElement(By.xpath
("//div[#class='elfinder-cwd-filename ui-draggable' and #title='project.CPG']"));
Hope this helps.
just try "=" instead of contains:
WebElement we1 =driverChrome.findElement(By.xpath
("//div[#class='elfinder-cwd-filename ui-draggable' and #title='project.CPG']"));
If it still does not work, it is possible that the element is not yet in the DOM when you are trying to find it, then you should try to place an implicit wait in front of your commands:
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

Unable to use send keys for disabled Element in selenium

The input field for which I am trying to write the code in selenium:
input class="tt-hint" type="text" disabled="" spellcheck="off" autocomplete="off" style="position: absolute; top: 0px; left: 0px; border-color: transparent; box-shadow: none; background: none repeat scroll 0% 0% rgb(255, 255, 255);"
My code is:
WebElementy inp= driver.findElement(By.className("tt-hint"));
inp.sendKeys(new String[] { "mo" });
But the above code does not work. The error I keep getting is:
Exception in thread "main" org.openqa.selenium.InvalidElementStateException: Element is disabled and so may not be used for actions
Any help is appreciated.
I have modified my code to
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].removeAttribute('disabled')",inp);
inp.sendKeys("mo");
I get the output as
The exception says it all. The element is not ready to accept any interaction and DISABLED. JavaScript is only option here. I would remove the disabled attribute and then use sendKeys()
String script = "document.getElementsByClassName('tt-hint')[1].removeAttribute('disabled')";
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript(script);
WebElementy inp= driver.findElement(By.className("tt-hint"));
inp.sendKeys("Whatever");
Javascript is the only option as said by #Saifur.However you do like this also
Either remove the disabled attribute or go with javascript to set the value itself
WebElement inp = driver.findElement(By.className("tt-hint"));
//Option 1 remove the disabled attribute
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].removeAttribute('disabled')",inp);
inp.sendKeys("val");
//Option 2 go for javascript set value
js.executeScript("arguments[0].value=arguments[1]",inp,"val");
The below is the code for Selenium C#, for a hidden Textbox/TextArea
IWebElement element;
IJavaScriptExecutor js = (IJavaScriptExecutor)Driver;
js.ExecuteScript("arguments[0].value=arguments[1]", element, inputValueYouWantToPlace);
Some controls won't recognize the given text and gives error like 'please provide input value'- in this case Enable the element just before sending the value using SendKeys()
`
js.ExecuteScript("arguments[0].removeAttribute('disabled')", input);
js.ExecuteScript("arguments[0].click()", element);
element.SendKeys(inputValueYouWantToPlace);
`

Selenium - unable to locate element by classname

I want to find a p tag with class = "big-number". Here is the code I wrote:
WebElement myDynamicElement = (new WebDriverWait(driver, 10)).until(ExpectedConditions.presenceOfElementLocated(By.className("big-number")));
System.out.println(driver.getTitle());
System.out.println(myDynamicElement);
Here is my output:
[[FirefoxDriver: firefox on MAC (fed46ad4-9ca9-9344-a57a-1d336db3927c)] -> class name: big-number]
I cannot identify the error, it is giving me an output but its makes no sense to me.
Any tips on how I can at least identify my error?
I am certainly sure the element is present, here is the HTML code:
<div id="users-online-container" style="">
<img class="big-number-icon" src="images/usersOnline.png">
<p class="big-number">228</p>
<p class="caption">Users Online</p>
</div>
<div id="users-online-loading"></div>
TimeOutException occurs because driver cannot find element in specific time. Problem in selector i think. If you sure that element always visible, and exists on the page so try next code:
//Select first paragraph in div
driver.FindElement(By.CssSelector("#users-online-container .big-number"));
//if you have several p with same classes you could access any of them using index. e.g.
driver.findElements(By.CssSelector(".big-number"))[index];
Selectors can be #users-online-container .big-number or .big-number. Both will work.
Try below code..
WebElement myDynamicElement = (new WebDriverWait(driver, 10)).until(ExpectedConditions.presenceOfElementLocated(By.className("big-number")));
// It will print the text of the Element:
system.out.println(myDynamicElement.getText());
Also you try to locate the element with the help of XPATH and make sure your locator is uniquely identify the element. Also check that IsDisplayed() and IsEnabled() returns True.
In your code you are printing the WebElement that will print the Hashcode.
In order to get the text of the Element, you'll have to use getText() method.
Hope it will help!

Categories

Resources