Selenium nth match by id without common parent - selenium

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

Related

How to select one from duplicate tag in page in java in selenium webdriver

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.

how to identify an object with the same name with name property

I want to find out an object with same name with different value? Here i am interested to identify based on the name only. Do we have index like property provided in QTP. In QTP, if two buttons with same can be distinguished by index, first button with index 0 and second button with 1.
Is there way to do the same in WebDriver?
I want to identify object with name meaning "By.name". How can i do that?
Thanks,
Uday
There are multiple options to achieve it (examples in java):
using findElements and get the appropriate element from the list of resulting web elements:
List<WebElement> elements = driver.findElements(By.name("test"));
WebElement element = elements.get(0);
use xpath based approach (indexing starts from 1 here):
WebElement element = driver.findElement(By.xpath('//input[#name="test"][1]'));
You can also use jQuery style syntax in your search..
For example in Chrome tools $('css selector')[0] will get you the first occurrence of some element.
Selenium comes with a JavaScript driver so you could instantiate that and use that against your site to leverage jQuery.

How can i select element in selenium webdriver by part of ID.

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.

Select an nth matched node from a list of matching nodes

I'm working with selenium to perform some automation and I'm attempting to interact with my webpage using Selenium & CSS selectors.
My question is how do I select the nth matched node returned from a list of all matching nodes?
For example my CSS selector is ".contactName" which returns 2 matching nodes. Using Selenium I want to do something like
selenium.Click("css=.contactName the second match");
Any help is greatly appreciated.
This is what I ended up using in order to select the second input with the class name
selenium.Click("xpath=(//input[#class='contactName'])[2]");
Do these two nodes share the same parent? If so, you can try one of these, depending on where they are under their parent in the DOM and whether there are any other kinds of elements:
selenium.Click("css=.contactName:nth-child(2)");
selenium.Click("css=.contactName + .contactName");
selenium.Click("css=.contactName ~ .contactName");
If these two nodes don't share the same parent, you'll probably have to go with an XPath locator instead of CSS:
selenium.Click("xpath=//*[#class='contactName'][2]");

Is by.id better than by.tagname?

I was working on reading mails from gmail using webdriver and in between I hit upon this difference between By.id and By.tagname.
I am trying to get access to a "table" whose id is ":pg". So I could
Either use By.id(":pg")
OR use By.tagname("table") and search for an element with id :pg
Here is the code for both cases.
By.id:
WebDriver webDriver = new FirefoxDriver();
webDriver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
webDriver = webDriver.switchTo().frame("canvas_frame");
WebElement table1 = webDriver.findElement(By.id(":pg"));`
Above code, I directly get the element which has id ":pg"
By.tagname:
WebDriver webDriver = new FirefoxDriver();
webDriver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
List<WebElement> tables = webDriver.findElements(By.tagName("table"));
for(WebElement table2: tables){
String id = table2.getAttribute("id");
System.out.println("id: "+ id);
if(id != null && id.equals(":pg")){
System.out.println("FOUND IT!!!");
}
}
Above code, I find all elements with the tagname of table and then see which one has the id ":pg".
Both these code snippets are essentially doing the same but using different ways(By.id or By.tagname). However, the first snippet of code which uses By.id always succeeds while the second snippet of code which uses By.tagname fails almost always. (It will work with additional waiting however)
Why is this difference between By.id and By.tagname?
Thanks,
Chris.
The :pg element is not present on the page initially.
Using By.Tag, selenium will not wait for the :pg element.
Because By.Id example is more specific, selenium will continue checking if the :pg element exists until the implicit wait (5 seconds) times out.
By.Tag is not specific at all. On findElements(By.tagName("table"), Selenium will return an array of all the tables that are present immediately after the page loads. As the :pg element is not present yet, it will not be in the array.
To answer your question, yes it is better to use By.Id because:
1. It is more specific.
2. Saves lines of code
3. Forces selenium to wait for the element to exist.
It is better to use By.Id according to your question.
By.tag is not used for specific data, it actually will search and return an array of all the tables with the specified tag name. On the other hand using id you can get the appropriate output for identifying/locating element.
Go for tag only if id, name or class is not specified and the best way can be By.cssSelector if no element is found.
Thanks