I am new to automation and am practicing on the flipkart website.
On the page:
http://www.flipkart.com/mobiles/pr?sid=tyy,4io&otracker=clp_mobiles_CategoryLinksModule_0-2_catergorylinks_11_ViewAll
... when I try to click an element that is not in view of the page by scrolling to it, I get the exception: Element is not clickable
Below is the code:
WebElement mobile = driver.findElement(By.xpath ("//a[#title='Apple iPhone 6S (Silver, 128 GB) ']"));
JavascriptExecutor jse = (JavascriptExecutor) driver;
jse.executeScript("arguments[0].scrollIntoView();", mobile);
mobile.click();
I believe this issue is occurring because of the header available in flipkart: even though the window is getting scrolled to that particular element, the header is covering the element so it's not possible to click on it.
Can anyone help resolve this?
you can try like this
Case where you want to click on a element that is not in view of the page (without scrolling) try below
public static void main(String[] args) throws InterruptedException {
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get(
"http://www.flipkart.com/mobiles/pr?sid=tyy,4io&otracker=clp_mobiles_CategoryLinksModule_0-2_catergorylinks_11_ViewAll");
driver.manage().window().maximize();
// Take everything on the page in list first .
List<WebElement> completecalContent = driver.findElements(By.xpath("//*[#class='fk-display-block']"));
System.out.println(completecalContent.size());
// printing all elements
for (int i = 0; i < completecalContent.size(); i++) {
System.out.println("Print complete Content : " + completecalContent.get(i).getText());
if (completecalContent.get(i).getText().equals("Apple iPhone 5S (Space Grey, 16 GB)")) {
// move to a specific element
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView();",
completecalContent.get(completecalContent.size() - 1));
// move slightly up as blue header comes in the picture
((JavascriptExecutor) driver).executeScript("window.scrollBy(0,-100)");
// then click on the element
completecalContent.get(i).click();
}
}
}
Case where you want to scroll then in that case update above code with these lines.
A. if you want to scroll to the bottom of the page then
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, document.body.scrollHeight)");
B. if u want to scroll to a specific element then try this
WebElement element = driver.findElement(By.xpath("xpath to element"));
((JavascriptExecutor) driver).executeScript(
"arguments[0].scrollIntoView();", element);
C. if you want to scroll on the basis of coordinates then try this
((JavascriptExecutor) driver).executeScript("window.scrollBy(0,500)");
Instead of scrolling up to web element you can try scrolling to little bit down in page like
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("scroll(250, 0)"); //x value '250' can be altered
Else you can try scrolling to element which is good enough above to required element. It means in code you tried instead of taking required webelement just scroll upto web element above the required so that the header does not cover required element.
Thank You,
Murali
Hey if you are not certain about the element's position on the page, you can find the co-ordinates at run time and then execute your text.
You can get elements co-ordinate by using Point
Point point = element.getLocation();
int xcord = point.getX();
int ycord = point.getY();
You can also get the dimensions of a webelement like its Height and Width using Dimension
Once you have the x and y co-ordinates and you have its dimensions. You can write your code to scroll till that particular co-ordinates on the page.
Hope it helps!
Related
Below method i am using in order to click on the 2nd image in the image slider in the home page of the flipkart but i am getting "Selenium.Timeout.Exception". Xpath which is mentioned in the below method is written for the 2nd image. If you will inspect this xpath it will always highlight the 2nd image but irrespective of this with below method i am not able to click on the 2nd image, though i have verified that element does remains in the DOM for sometime and in that moment only it should be get clicked but anyhow it is not happening.
Could anyone please help me with this.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofSeconds(120))
.pollingEvery(Duration.ofMillis(500))
//.ignoring(ElementClickInterceptedException.class);
.ignoring(TimeoutException.class);
Boolean element = wait.until(new Function<WebDriver, Boolean>(){
public Boolean apply(WebDriver driver) {
return driver.findElement(By.xpath("(//div[#class='_3ZUwcz'])[3]//descendant::div//img[#class='_2VeolH _3I5S6S']")).isDisplayed();
}
});
System.out.println("Actual Element visibility " +element);
if(element==true) {
driver.findElement(By.xpath((//div[#class='_3ZUwcz[3]//descendant::div//img[#class='_2VeolH_3I5S6S']")).click();
}
Try this to click the element:
WebElement element = driver.findElement(By.xpath("(//div[#class='_3ZUwcz'])[3]//descendant::div//img[#class='_2VeolH _3I5S6S']"));
JavascriptExecutor js= (JavascriptExecutor)driver;
js.executeScript("arguments[0].click();", element);
How to scroll the horizontal bar in a grid using selenium. This should be repeated in multiple selections. I have to select the value and click submit. I have to check all the column headers. But, there are 46 columns. Please help. I am unable to move it.
List<WebElement> gridlabellist = driver.findElements(By.xpath(".//*[#id='gview_list']/div[3]/div/table/thead/tr/th"));
List<String> all_gridlabellist=new ArrayList<>();
Thread.sleep(1000);
int gl;
System.out.println(gridlabellist.size());
for(gl=0; gl<gridlabellist.size(); gl++)
{
String gridlabelname=gridlabellist.get(gl).getText();
boolean dislabel=gridlabellist.get(gl).isEnabled();
//System.out.println(labelname);
if((gridlabelname != null) && (gridlabelname.length()!=0) && dislabel)
{
System.out.println("\nGrid Label Names displayed: " + gridlabelname);
((JavascriptExecutor)driver).executeScript("window.scrollBy(2000,0)");
System.out.println("\nGrid Label Names displayed: " +gridlabelname);
}
all_gridlabellist.add(gridlabellist.get(gl).getText());
}
its a very old question but still relevant enough to answer with alternative ways, another way to solve this problem is to zoom, zoom to 50-30% or even 10%; this will load all the columns and then read them using xpath.
Try a different approach & test if it works for you
WebElement scroll = driver.findElement(By.xpath("//blah-blah"));
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript(
driver.execute_script("arguments[0].scrollIntoView()", scroll);
I'm playing around with selenium and just lately started to take a look at drop-downs and selecting elements.
For learning Selenium I'm using following site:
http://www.smartclient.com/smartgwt/showcase/?sc_selenium=true#featured_dropdown_grid_category
There is a drop-down Grid on which I'm trying to locate an element.
Since the drop-down is dynamic and has a scroll bar then I need to scroll down and locate an element.
Can anyone give me hints how I can locate and select an element on such drop-down?
Let's say I would like to select:
Item: contains "Envelopes"
Unit: "EA"
Unit Cost: gather then 0.2
Here is my code:
By itemPicker = ByScLocator.xpath("/html/body/div[2]/div/div/div/div/div[1]/div[2]/div/div/div[4]/div[1]/div/div/div/div[1]/div/div/div/form/table/tbody[2]/tr[2]/td[2]/table/tbody/tr/td[1]");
driver.findElement(itemPicker).click();
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.elementToBeClickable(itemPicker));
driver.findElement(itemPicker).sendKeys();
boolean find = false;
while (!find) {
By menuItems = ByScLocator.xpath("//tr[contains(#id, \"isc_PickListMenu_\")]");
List<WebElement> all = driver.findElements(menuItems);
try {
//Verify if all elements still exists in DOM
for (WebElement element : all) {
element.findElements(By.tagName("td"));
}
} catch (StaleElementReferenceException e) {
all = driver.findElements(menuItems);
}
for (WebElement element : all) {
List<WebElement> columns = element.findElements(By.tagName("td"));
String currenlyProcessedItem = columns.get(0).getText();
if (currenlyProcessedItem.matches(".*Envelopes.*")) {
if (columns.get(1).getText().equals("Ea")) {
if (Double.parseDouble(columns.get(2).getText()) > 0.2) {
find = true;
element.click();
break;
}
}
}
}
if (find) { //load another set of list items
driver.findElement(By.id("isc_3N")).sendKeys(Keys.PAGE_DOWN);
}
}
The problem is that I'm unable to scroll down the list and identify item I want to select.
Also I don't know if my aproach is optimal.
You can select only one item on this select list.
I think the problem is, that the item you trying to find isn't on the list.
The scroll bar doesn't mater as long as the select list is open.
If you trying just to select an item then this works for the item "Glue UHU Clear Gum 250ml"
public class selectItem {
#Test
public void selectItem(){
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("http://www.smartclient.com/smartgwt/showcase/?sc_selenium=true#featured_dropdown_grid_category");
// Open select list
driver.findElement(By.id("isc_1Y")).click();
// Select row based on a string present
driver.findElement(By.xpath("//div[contains(text(), 'Glue UHU Clear Gum 250ml')]")).click();
driver.quit();
}
}
Using the solution below I was able to get elements in the dropdown to resolve. There are obvious dependencies on timing in the implementation to account for StaleElementExceptions when scrolling the content, but I'm hopeful those can be filtered out with a little more effort.
If the test doesn't pass for you right away try increasing the
'pollingEvery' time to 1/second. I'm pretty sure that's going to be
based on the machine it's being run on, and that will probably need
addressing.
/** Desired text to find in the dropdown.*/
String text = "Envelopes Kraft 305 x 255mm (12 x 10) (84GSM)";
//String text = "Pens Stabiliner 808 Ballpoint Fine Black";
/**
* Test to try to find a reference inside a scrollable gwt dropdown container.
* <p/>
* Behavior is heavily timing dependent and will take progressively longer as the content in the dropdown increases.
* <p/>
* I'm sure this can be optimized, but as a proof it does the job.
*/
#Test
public void gwtDropdownWithScrollContent() {
WebDriver driver = new FirefoxDriver();
try {
driver.get(
"http://www.smartclient.com/smartgwt/showcase/?sc_selenium=true#featured_dropdown_grid_category");
WebDriverWait wait = new WebDriverWait(driver, 240);
By dropdownTwiddle = By.xpath(".//*[#id='isc_1Y']");
//Find the combo and hit the twiddle button to expand the options.
WebElement we = wait.until(ExpectedConditions.elementToBeClickable(dropdownTwiddle)); // Find the drop down
we.click();
/*
* Create a function to use with the webdriver wait. Each iteration it will resolve the table object, find
* all of the rows, and try to find the desired text in the first <td> field of each row.
*
* If the element is not found, the scroll bar is resovled and the Actions class is used to get a hold of
* the scroll bar and move it down. Then the wait loops and tries again.
*/
Function<WebDriver, WebElement> scrollFinder = new Function<WebDriver, WebElement>() {
By optionTable = By.xpath(".//*[#id='isc_3A']");
By scrollElement = By.xpath(".//*[#id='isc_3N']/table/tbody/tr/td/img");
public WebElement apply(WebDriver arg0) {
WebElement table = arg0.findElement(optionTable);
List<WebElement> visibleEntries = table.findElements(By.xpath(".//tr"));
WebElement reference = null;
for (WebElement element : visibleEntries) {
if (ExpectedConditions.stalenessOf(element).apply(arg0)) {
//This happens if the scroll down happens and we loop back too quickly and grab the contents of the table before it refreshes.
//Seems to be tied directly to the poll configuration for the web driver wait.
continue;
}
WebElement firstColumn = element.findElement(By.xpath(".//td"));
String colVal = firstColumn.getText();
if (!Strings.isNullOrEmpty(colVal)) {
if (text.equalsIgnoreCase(firstColumn.getText())) {
reference = element;
break;
}
}
}
if (reference == null) {
//If the element wasn't found then scroll down and retry the effort.
WebElement scrollBar = arg0.findElement(scrollElement);
Actions actions = new Actions(arg0);
//The offset below may be increased to make a larger scroll effort between iterations.
actions.moveToElement(scrollBar).clickAndHold().moveByOffset(0, 5).release().build().perform();
}
return reference;
}
};
//XXX: THIS is the time to increase if the test doesn't seem to "work".
wait.pollingEvery(500, TimeUnit.MILLISECONDS); // Setting too low can cause StaleElementException inside the
// loop. When scrolling down the Object can be refreshed and
// disconnected from the DOM.
Assert.assertNotNull(wait.until(scrollFinder));
} finally {
driver.close();
}
}
Best of Luck.
I need to copy the contents of a page except header and footer only using mouse select+drag+mouseup+ctrl+C kind of copy.
I am using Selenium Actions class.
FirefoxDriver driver = new FirefoxDriver();
Actions builder = new Actions(driver);
driver.get("http://connectatgrace.org/im-new/what-to-expect");
builder.click(driver.findElement(By.className("block-holder")))
.keyDown(Keys.CONTROL).keyDown(Keys.SHIFT)
.click(driver.findElement(By.id("footer")));
System.out.println("CLICKED");
Is it possible?
Experts please help.
If all you want is the text, you can get it by using .getText() on the right element.
WebDriver driver = new FirefoxDriver();
driver.get("http://connectatgrace.org/im-new/what-to-expect");
String text = driver.findElement(By.id("main")).getText().trim();
EDIT
I understand now what you are looking for. I was able to get it to work with the code below.
Basically the code moves the mouse to the bottom-right corner of the element that contains all the desired text, <div id="content full-width">. Click and hold the mouse button down, move to the top-left corner of the element, and then CTRL+C. I've also validated that the correct text gets into the clipboard.
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("http://connectatgrace.org/im-new/what-to-expect");
WebElement content = driver.findElement(By.id("content full-width"));
Actions builder = new Actions(driver);
builder.moveToElement(content, 0, 0).clickAndHold().moveToElement(content,
content.getSize().getWidth(), content1.getSize().getHeight()).release();
builder.build().perform();
content.sendKeys(Keys.chord(Keys.CONTROL, "c"));
System.out.println("CLICKED");
NOTE: If you use moveToElement(), it moves to the center of the element. That's why there's code to get the width/height and divide by 2.
EDIT 2
After OP noticed that I had a typo, I went back and did some investigations on the .moveToElement() methods. From the docs,
moveToElement(WebElement toElement)
Moves the mouse to the middle of the element.
moveToElement(WebElement toElement, int xOffset, int yOffset)
Moves the mouse to an offset from the top-left corner of the element.
So corrected the code to use .moveToElement(e, 0, 0) to start the selection at the top left of the element and then moved the selection to the bottom right using .moveToElement(content, content.getSize().getWidth(), content1.getSize().getHeight()). This should work correctly now.
This works!!!
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("http://connectatgrace.org/im-new/what-to-expect");
WebElement content = driver.findElement(By.id("content full-width"));
Actions builder = new Actions(driver);
builder.moveToElement(content, content.getSize().getWidth() / 2, content.getSize().getWidth() / 2).clickAndHold().moveToElement(content, -content.getSize().getHeight() / 2, -content.getSize().getHeight() / 2);
builder.build().perform();
Basically you forgot to place height i.e. getHeight() instead of getWidth().
Now its working fine.
I have a problem using Selenium Webdriver (version 2.32.0) and Firefox (21.0), trying to change the values on a slider.
I wrote a Java code like this:
private void selectGiftCardPrice() throws TestingException {
try {
WebElement slider = getDriver().findElement(
By.cssSelector("div.sliderHandle"));
Actions move = new Actions(getDriver());
move.dragAndDropBy(slider, 90, 0);
move.build().perform();
sleep(4000);
} catch (Exception e) {
log.info(e);
throw new TestingException("e");
}
I tried out every code I found on the Web, every change, and it still does not work. It does not show any problem, just finds the element, and does nothing. Any idea what it is, or what can I do?
EDIT from comment:
I finally made it working with jQuery slider demo
driver.get("http://jqueryui.com/resources/demos/slider/multiple-vertical.html");
WebElement slider = driver.findElement(By.xpath("//div[1]/a[contains(#class,'ui-slider-handle')]"));
But it is still not working for me with jQuery UI Slider demo page using Xpath //div[#id='slider']/a. What is the problem?
This code works absolutely fine for me.
program handles slider of website : Homeshope18.com
Check it out:
WebDriver driver = new FirefoxDriver();
driver.get("http://www.homeshop18.com/fashion-jewellery/category:15143/filter_Theme:%28%22Traditional+Wear%22+%22Cuff+%26+Kada%22+%22Daily+Wear%22+%22Maang+Tikka%22+%22Openable+Round%22+%22Round%22+%22Openable+Oval%22%29/sort:Popularity/inStock:true/?it_category=HP&it_action=JW-HPSP01&it_label=HP-HPSP01-131021235900-PD-JW-ZC-VK-SC_DiwaliFestWeddingJewellery&it_value=0");
WebElement slider = driver.findElement(By.xpath("//*[#id='slider-range']/a[1]"));
Thread.sleep(3000);
Actions moveSlider = new Actions(driver);
Action action = moveSlider.dragAndDropBy(slider, 30, 0).build();
action.perform();
Using Actions class, firs use clickAndHold("WebElemnt");
Then to move horizontally we need to move in the Y direction of the screen so we can use movebyoffset, i.e X-axis: 0 & Y axis: 40px
To move vertically we need to move in the X direction of the screen so we can use movebyoffset, i.e X-axis: 40px & Y axis: 0
The sample code would be :
Actions slider=new Actions(driver);
slider.clickAndHold("WebElemnt");
slider.movebyoffset(0,40).build.perform();