WebElement p1 = (new FirefoxDriver()).findElement(By.xpath("//div[#class = 'site-title']")) ;
WebElement p2 = (new FirefoxDriver()).findElementByXPath("//div[#class = 'site-title']") ;
I m doing same thing: I select element by xpath, but in first line, I do it using findElement(By.xpath) and 2nd I use whole expression findElementByXpath.
and I still use same firefox driver object!
Is this because the By. is interface and accessed differently?
According to the source code of selenium java bindings, findElementByXPath() basically is just a shortcut to findElement(By.xpath, ...):
public WebElement findElementByXPath(String using) {
return findElement("xpath", using);
}
findElement() method -
Identify the one element (text field, label etc) from the web-page
WebElement p1 = (new FirefoxDriver()).findElement(By.xpath("//div[#class = 'site-title']")) ;
findElements() method -
Identify the multiple elements from webpage, like table rows and colums
List<WebElement> p1List = (new FirefoxDriver()).findElements(By.xpath("//div[#table='divTableData']")) ;
Related
I'm trying to click on all the search results with a loop and get the title strings from each of the results. So it would click on a result try to extract the string.
String title = null;
List <WebElement> links = driver.findElements(By.className("thumbnail"));
ArrayList<String> tabs = new ArrayList<String> (driver.getWindowHandles());
for(int i=0; i<1; i++){
links = driver.findElements(By.className("thumbnail")); // this step is must, because whenever you go to other page all store WebElements in a list will wash out
links.get(i).click();
//it opens the search result in a new tab and gains focus on that tab
WebDriverWait wait = new WebDriverWait(driver, 10);
By addItem = By.xpath("//*[#id=\"HEADING\"]");
// get the "Add Item" element
WebElement element1 = wait.until(ExpectedConditions.presenceOfElementLocated(addItem));
wait.until(ExpectedConditions.stalenessOf(element1));
if(!driver.findElements(By.xpath("//*[#id=\"HEADING\"]")).isEmpty()) {
title = driver.findElement(By.xpath("//*[#id=\"HEADING\"]")).getText();
}
else {
System.out.println("Title is missing");
}
System.out.println(title);
driver.switchTo().window(tabs.get(0)); //Switching to first tab
}
The code is extracting the title on the first page rather than the page it clicked on. I'm also trying to extract other strings such as address, email, etc but i'm just testing this out. How do I fix this? Any help would be appreciated, thank you!
There were a few things that I changed.
I moved all your locators (and some other declarations) to the top and outside of the loop so they aren't redeclared inside the loop and so that they can be referenced by the .findElement() calls.
Since you are only using the current window handle, changed the variable type to String and just got the current window handle (instead of the collection of handles) so that you can switch back to the main tab at the end of the loop.
Moved the staleness check right after the click since that's where you need it and changed it to wait for the thumbnail that was just clicked.
Changed the XPath locator to use ID since that's all you were referencing. It's faster, shorter, and easier to read.
The second wait now waits for the collection of elements and then uses that collection to test for empty and get the text of the first in the collection.
By addItemLocator = By.id("HEADING");
By thumbnailsLocator = By.className("thumbnail");
List<WebElement> links = driver.findElements(thumbnailsLocator);
String originalTab = driver.getWindowHandle();
Set<String> tabs = driver.getWindowHandles();
WebDriverWait wait = new WebDriverWait(driver, 10);
for(int i = 0; i < links.size(); i++)
{
links = driver.findElements(thumbnailsLocator); // this step is must, because whenever you go to other page all store WebElements in a list will wash out
links.get(i).click();
// it opens the search result in a new tab and gains focus on that tab
// switch to the new window
for(String handle : driver.getWindowHandles()){
if (!handle.equals(originalTab))
{
driver.switchTo().window(handle);
break;
}
}
// get the "Add Item" element
List<WebElement> addItems = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(addItemLocator));
if(!addItems.isEmpty())
{
System.out.println(addItems.get(0).getText());
}
else
{
System.out.println("Title is missing");
}
driver.close(); // close current tab
driver.switchTo().window(originalTab); // switch to original tab
}
The fields in question look like this
Each password character field is chosen randomly and the user is required to enter their corresponding password character in the specific field. For example if my password is swordfish, in the picture above I would be required to enter the letters s, d and s. So far I have an If statement for each element which is hardly ideal and only the input[] of the xpath changes with each field.
WebElement p1 = driver.findElement(By.xpath("/html/body/div[3]/div[3]
/div[2]/div/div[2]/div[1]/div[1]/div/div[2]/div[2]/div/form/table/tbody/tr[6]/td/input[1]
"));
if (p1.isEnabled()){
p1.click();
p1.sendKeys("s");
}
WebElement p2 = driver.findElement(By.xpath("/html/body/div[3]/div[3]
/div[2]/div/div[2]/div[1]/div[1]/div/div[2]/div[2]/div/form/table/tbody/tr[6]/td/input[2]
"));
if (p2.isEnabled()){
p2.sendKeys("d");
}
WebElement p3 = driver.findElement(By.xpath("/html/body/div[3]/div[3]
/div[2]/div/div[2]/div[1]/div[1]/div/div[2]/div[2]/div/form/table/tbody/tr[6]/td/input[3]
"));
if (p3.isEnabled()){
p3.sendKeys("s");
}
I have a solution in pseudocode but I don't know exactly how to do it in Java.
for i =0;i<10;i++
associate i with a field
if passworfield is enabled
set password letter based on xpath
If you take a look at the xPath you are using, they only differ on the index of the input.
For my suggested approach you would need to have a char array where you hold the password.
So, a possible approach would be to have a loop with an index more or less like this:
char[] password = new char[]{'p','a','s','s','w','o','r','d','1'};
for (int i = 0; i < 9; i++)
{
WebElement elem = driver.findElement(By.xpath("/html/body/div[3]/div[3]/div[2]/div/div[2]/div[1]/div[1]/div/div[2]/div[2]/div/form/table/tbody/tr[6]/td/input[" + (i + 1) + "]"));
if (elem != null && elem.isEnabled())
elem.sendKeys(Character.toString(password[i]));
}
Just notice that I'm using Character.toString because I'm not sure if sendKeys allows a char instead of a String. If there's any way that's possible I'd recommend you do so.
EDIT:
Another possibility that has been suggested is to get all the elements first (which would improve the performance as you'd not need to force Selenium to analyze the webpage over and over again.. where it would be simplified to (something approximately like):
char[] password = new char[]{'p','a','s','s','w','o','r','d','1'};
List<WebElement> elements = driver.findElements(By.xpath("/html/body/div[3]/div[3]/div[2]/div/div[2]/div[1]/div[1]/div/div[2]/div[2]/div/form/table/tbody/tr[6]/td/input"));
for (WebElement elem : elements)
{
if (elem.isEnabled())
elem.sendKeys(Character.toString(password[elements.indexOf(elem)]));
}
I'd go with Fernando's answer, but here's something that might help too.
String s1 = "0,p,a,s,s,w,o,r,d,1";
String[] array = s1.split(",");
for (int i = 1; i < 10; i++){
String xpath = "/html/body/div[3]/div[3]/div[2]/div/div[2]
/div[1]/div[1]/div/div[2]/div[2]/div/form/table/tbody/
tr[6]/td/input[" + i + "]";
WebElement passw = driver.findElement(By.xpath(xpath));
if (passw.isEnabled()){
passw.sendKeys(array[i]);
}
}
I have a for loop that constantly loops back a website to fill out and submit a search box with the next string from a list.
For example, if the list contains [abcd, efgh, ijkl....], the first loop would send abcd, the second loop would send efgh and etc.
Currently the loop sends the first string correctly, but on every loop afterwards, the string sent is added to the previous string. So instead of efgh on the second loop, it is abcdefgh.
How do I clear the keys so that I can just send the individual string? Here's what I have right now:
for(String value : List){
driver.get(Link);
Actions actions = new Actions(driver);
WebElement input_field = driver.findElement(By.id("txtBoxSearch"));
actions.moveToElement(input_field);
actions.click();
actions.sendKeys(value);
actions.build().perform();
WebElement submit_key = driver.findElement(By.xpath("//button[contains(#title, 'Search')]"));
actions.moveToElement(submit_key);
actions.click();
actions.build().perform();
}
You need to clear the content of textbox before write value to it
for(String value : List){
driver.get(Link);
Actions actions = new Actions(driver);
WebElement input_field = driver.findElement(By.id("txtBoxSearch"));
input_field.clear();
actions.moveToElement(input_field);
actions.click();
actions.sendKeys(value);
actions.build().perform();
WebElement submit_key = driver.findElement(By.xpath("//button[contains(#title, 'Search')]"));
actions.moveToElement(submit_key);
actions.click();
actions.build().perform();
}
Here is the Answer to your Question:
Once you call click() method on the on the desired element through action class instance, next use the action class instance to clickAndHold, send CONTROL A and then send the new text DebanjanB to the form control to overwrite the previous text as follows:
for(String value : List){
driver.get(Link);
Actions actions = new Actions(driver);
WebElement input_field = driver.findElement(By.id("txtBoxSearch"));
actions.moveToElement(input_field);
actions.click();
actions.clickAndHold(input_field).sendKeys(Keys.chord(Keys.CONTROL, "a"), "DebanjanB").build().perform();
WebElement submit_key = driver.findElement(By.xpath("//button[contains(#title, 'Search')]"));
actions.moveToElement(submit_key);
actions.click();
actions.build().perform();
}
Let me know if this Answers your Question.
I am facing problem while checking the clickable web element.
So i have to check the alphabetic series and some of the alphabet are clickable and some are not clickable.
i used for loop for it starting with xpath of alphabet 'A'
and going in loop till alphabet 'Z'.
but as soon as xpath of alphabet A is click & pass it goes to alphabet 'B'
which is not clickable and due to this whole script is getting fail.
here is the code
for(int j=3; j<=26;j++) {
String T1 =".//*[#id='twctvEl']/div/div/div[1]/ul/li[";
String T2 = "]/a";
String T12 = T1+j+T2;
chrome.findElement(By.xpath(T12)).click();
String alpha =chrome.findElement(By.xpath(T12)).getText();
System.out.println("checking the alphabet"+alpha);
}
Please advice here
NOTE: In the series of alpha bet from A-Z only B,Q,S,X,Y,Z are not clickable rest all are clickable.
You can add waits before element to become clickable:
for(int j=3; j<=26;j++)
{
String T1 =".//*[#id='twctvEl']/div/div/div[1]/ul/li[";
String T2 = "]/a";
String T12 = T1+j+T2;
WebElement el = chrome.findElement(By.xpath(T12));
WebDriverWait wait = new WebDriverWait(driver, timeout);
WebElement el= wait.until(ExpectedConditions.elementToBeClickable(element));
el.click();
String alpha =el.getText();
System.out.println("checking the alphabet"+alpha);
}
You can check if the element is visible and enabled before clicking on it
WebElement letter = chrome.findElement(By.xpath(T12));
if (letter.isDisplayed() && letter.isEnabled()) {
letter.click();
}
Well, it seems that when you click the element "A", it take you to another page or context and for this reason, during next iteration chrome driver is not able to find your Element "B" using xPath.
I have a problem to select from dropdown menu by using SelectByValue ignoring case sensitivity.
For example:
Japan
Albania
As it is seen value is Japan. However, the value which I have can be "japan" or "Japan".
I can able to select by using. However, it takes considerable amount of time if the list is huge.
// get dropdown elements
Select dropdown = new Select(findElementHelper(by));
// get elements based on options from dropdown menu
List<WebElement> myElements = dropdown.getOptions(); //because of listing takes time
// test until value of element and given value is equal
String tempValue = value.trim();
for (WebElement option : myElements) {
if (tempValue.equalsIgnoreCase(option.getAttribute("value").trim())) {
// tryClick(option,value) did not work on ie
/*if (!tryClick(option,value)){
System.out.println(value + " is not selected");
return false;
} option.click(); //worked one
break;
}
}
I have tried Select class with proper input and it works much faster than my code. Is there any way to ignore case sensitivity in selectByValue.
Thanks for help
The Selenium implementation of selectByValue() searches for the given value using xpath instead of looping through all of the options. You should be able to change the xpath search to be change everything to lowercase instead. If you know there will only be one option with the given value then you can simplify this further by removing the List and for loop.
WebElement dropdownElement = findElementHelper(by);
String tempValue = value.trim().toLowerCase();
List<WebElement> matchingValues = dropdownElement.findElements(By.xpath(
".//option[lower-case(#value) = '" + tempValue + "']"));
for(WebElement matchingValue : matchingValues)
{
/* Do what you want with the options
if (!option.isSelected()) {
option.click();
} */
}
I don't work with Selenium in Java so I'm not able to test this but it should be pretty close. Let me know if this is faster.