I have a td element with ID like "a:2:3:d:", and when i want to select it by id, my webdriver can not find it. Is there a way to search by part of ID, because I think, that the problem is at last ":" in the identifier.
First, you need to confirm that this really is the problem, and it's not just that the page isn't fully loaded, or is loaded asynchronously. I don't see any particular reason why Selenium should care about the trailing ":".
Update: From the comments, it's much more likely that the dynamic id that is the problem, but the solution is the same either way:
To find an element by partial id, you can use xpath. If you were trying to find a div by partial id, for example:
//div[contains(#id, 'a:2:3')]
You don't say what language you are using, but in python, this would be used as follows:
driver.find_element_by_xpath("//div[contains(#id, 'a:2:3')]")
and in Java:
driver.findElement(By.xpath("//div[contains(#id, 'a:2:3')]"))
Assuming you are using Java
WebElement el = driver.findElement(By.cssSelector("td[id*='a:2:3']"));
The above code gets the element of TD which starts with a:2:3 as we use * in the css Selector.
XPath is more powerful and can be sometimes difficult to understand. CSS Selector is easy.
Related
I am using Selenium WebDriver and I have number of items on a page and each item on page is a separate form type.
I have saved all of these form elements in a list and I am iterating over every item in an attempt to get the name of the element by using the "alt" attribute.
However when I try to get the "name" attribute from the input element it is always returning the first input tag found on that page, not the name attribute of the element I have currently selected.
The syntax I am using is:
((Webdriver imgtags.get(i)).findelement(By.xpath("//input[#name='qty']")).sendKeys ("100");
I have also tried to get the id from the tag by using:
((Webdriver imgtags.get(i)).getAttribute("id");
It's returning a blank value, but it should return the value of the id attribute in that input tag.
I also tried to get the id by using .bytagname but as id is an attribute it is not accessible
Try:
(driver) findElement(By.xpath("//*[contains(local-name(), 'input') and contains(#name, 'qty')]")).sendKeys("100");
To answer the comment by #rrd: to be honest, I have no idea why OP uses ((Webdriver imgtags.get(i)). I don't know what that is. Normally, I just use driver.findElement[...]
Hoping that he knows what works in his framework :D
Selenium Xpath handling is not fully compliant and it does not always treat // as a synonym of descendant-or-self.
Instead try tweaking your code to use the following Xpath:
((Webdriver imgtags.get(i)).findElement(By.xpath("./descendant-or-self::input[#name='qty']")).sendKeys("100");
This will base your search off the currently selected WebElement and then look for any descendants that have a name attribute with a value of "qty".
I would also suggest storing your imgtags array as an array of WebElement e.g.
List<WebElement> imgtags = new ArrayList<>();
This is a much better idea than casting to WebDriver to be able to use .findElement(). This will cause you problems at some point in the future.
I am using XPath to find exact value:
//h5[#class='familyName productFamilyName'][contains(text(),'Dozers ')]
but it was failing because in my application there are 2 elements with text values "Dozers " and "Dozers wheel" which is come under same class.
I can't use id locators,because it is dynamically generating in my application like //div[#id="482"]/div/div[1]/h5.
Please suggest me any solution.
If you want to match element with exact innerHTML value just use
//h5[#class='familyName productFamilyName'][text()='Dozers')]
or
//h5[#class='familyName productFamilyName'][text()='Dozers wheel')]
Depending on HTML structure you might need to use [.='Dozers'] or
[normalize-space(.)='Dozers'] instead of [text()='Dozers']
Below in my code
driver.switchTo().frame(driver.findElement(By.id("file")));
Above line is not running
There is various way to switch to frame. Please share the HTML code if you need a exact code to switch to your respective application. you can try with below method. Better use index if your frame do not any name etc
driver.switchTo().frame(index)
replace index with 0 first and if it not work then try with 1 and then 2 etc one by one
More details
driver.switchTo().frame() has multiple overloads.
driver.switchTo().frame(name or id)
Here your iframe doesn't have id or name, so not for you.
driver.switchTo().frame(index)
This is the last option to choose, because using index is not stable enough as you could imagine. If this is your only iframe in the page, try
driver.switchTo().frame(0)
driver.switchTo().frame(iframe_element)
The most common one. You locate your iframe like other elements, then pass it into the method.
Here locating it by title attributes seems to be the best.
driver.switchTo().frame(driver.findElement(By.cssSelector("iframe[title='Fill Quote']")));
// driver.switchTo().frame(driver.findElement(By.xpath(".//iframe[#title='Fill Quote']")));
most probably, your iframe is not visible or your window is not active.
in Python:
driver.switch_to_default_content()
wait.until(EC.frame_to_be_available_and_switch_to_it("yourFrame"))
in Java:
driver.switchTo().defaultContent();
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.tagName("yourFrame")));
I have recently started with Selenium, and I've decided to use only Selenium 2 / WebDriver.
In my test code, I often arrive at a WebElement without knowing where it is in the page.
I'd like to have code that, given an WebElement, constructs an XPath expression to uniquely select it.
FireFox recorder plugins for Selenium do this; what I want is code to do it in Selenium 2.
I can write such code myself by using WebElement's findElement to walk up the tree and findElements to find the child we came from, but it's nontrivial to come up with something fast (repeatedly calling By.xpath seems bad) and complete (e.g. due to namespaces).
(A related question suggests using CSS selectors instead - that's fine with me.)
Has anyone done this for me? What is the best approach?
Maybe this will help: I am testing a website where the id's are dynamically generated, so they change all the time. In order to get their xpath and work with it I use this function:
/**
* Gets the absolute xPath for elements with dynamic ids.
*
* #param driver - the current WebDriver instance
* #param element - the element for which the xPath will be found
* #return the absolute xPath for this element
*/
public static String getElementXPath(WebDriver driver, WebElement element) {
return (String)((JavascriptExecutor)driver).executeScript(
"gPt=function(c)" +
"{" +
"if(c.id!=='')" +
"{return c.tagName + '[#id=\"'+c.id+'\"]'}" +
"if(c===document.body)" +
"{return c.tagName}" +
"var a=0;" +
"var e=c.parentNode.childNodes;" +
"for(var b=0;b<e.length;b++)" +
"{var d=e[b];" +
"if(d===c)" +
"{return gPt(c.parentNode)+'/'+c.tagName+'['+(a+1)+']'}" +
"if(d.nodeType===1&&d.tagName===c.tagName)" +
"{a++}" +
"}" +
"};" +
"return gPt(arguments[0]);", element);
}
It's pretty straight forward: and btw yes css is the way to go; xpath should be only used as a measure of last resort. http://sauceio.com/index.php/2010/01/selenium-totw-css-selectors-in-selenium-demystified/ explains css locators in much more depth than I can in the space provided here.
Best approach: If you're using firefox download firebug, that will let you look at your html. Pres cmd+Shift+c and it'll open for you with an element highlighter. Find your html element, maybe it'll look something like this
<input type="submit" tabindex="110" value="Post Your Answer" id="submit-button">
Then you can find your element pretty simply
WebElement element = driver.findElement(By.cssSelector("input[id='submit-button']"))
Notice that we put the tagname first "input" followed by some kind of unique identifier in the brackets "input[id='submit-button']." For the most part this will cover 75% of all css locators you use. The other 25% require a little bit more tricky stuff covered in the link I placed at the top of the page.
You may ask "What kind of unique identifiers can I use besides id" well that is covered here: http://release.seleniumhq.org/selenium-remote-control/0.9.2/doc/dotnet/Selenium.html
Good luck starting out
EDIT
Well good luck finding your elements in the first place...If you need you can search elements by partial locator text like input[id*='submit']. Using that is helpful for dynamically generated elements, when you use the partial text as the part of the locator that doesn't vary from element to element.
You mentioned walking up the html tree perhaps I didn't see that when I first read the question. I think you hit the on issue at hand. Walking up the html tree isn't suggested as it makes your tests more fragile to html changes. It will also make your code unreadable in the long run as well. In general if your id's are missing or unpredictable I would suggest talking to proj. management about getting the developers to make code that can actually be automated (eg: getting identifiers implemented on critical elements). This will actually save both you and the developers alot of effort in the long run, and it will also increase the speed and reliability of your tests.
We can find the Submit Button using ID:
1.driver.findElement(By.id("submit-button"))
ID > NAME > CSS > XPATH
I have to test some complicated web service using Selenium.
Problem is that ids of elements are changing from session to session.
For example there is bunch of inputs each have id with prefix textf_id_DComboBox_ and ends with a consecutive numbers, starting number is random (session dependent).
Those inputs doesn't have a common parent so nth-child doesn't work.\
I can find first input by using selector: css=input[id^='textf_id_DComboBox_'] but I have no idea how to find next items (1-7) which match this selector.
I've found some suggestions on stackoverflow that xpath selector should be used, but I was unable to adopt examples for my use case.
Update:
I have also alternative selector which captures first input: css=td.DForm_treeGridNoWrap input.
You can use this XPath in order to select all inputs that contain a common id:
string comboBoxXPath = "//input[contains(#id, 'textf_id_DComboBox')]";
List<WebElement> comboBoxElements = driver.findElements(By.XPath(comboBoxXPath));
At this point, you can iterate through the entire collection, or you can select which one you'd like to interact with by using an index:
comboBoxElements[1]
comboBoxElements[2]
comboBoxElements[3]
etc...
Well, that descrption does not help that much. You can try these tricks:
You can call findElement on WebElement This trick will probably not work, because those IDs do not have common parent. But if they are wrapped, say, in table, you can find the table first:
WebElement table = driver.findElement(By.id("the-table"));
And then to find all input in such table:
List<WebElement> inputs = table.findElements(By.tagName("input"));
Install Selenium IDE to your firefox and try record testcase by using it. You can play with target in Selenium IDE.
Dirty approach
List<WebElement> allInputs = driver.findElements(By.tagName("input"));
Will find all inputs in such page.
Footnote: The code is Java and driver variable is considered as healthy instance of WebDriver