3

I have a problem how to select a desired option (e.g. From, To...etc.) from list if 'datalist id' and 'select name' are randomly generated. This means that the ID and name has another value after refresh page. Here is a code for a first row, and 1st Field list:

enter image description here

I tried the lower described solutions, but there is no text value, as shown in the following figure. enter image description here

6 Answers 6

0

It is a matter of proper xpath. You know the row and the column. You also know that the select is under datalist. The thing that is left to do is //table[@id='advFilter']/tbody/tr[N]/td[@class='field']/datalist/select. Where N is the row number. You can extend this xpath so that it captures the particular option if you need.

1
  • Sorry, I didn't understand how to extend this xpath. Can you explain this in the example, please ? And is there a need to add an N value, is there another way to define it?
    – Majkl
    Commented Sep 20, 2019 at 10:24
0

Assuming that the class name of the td = field is unique for the page, you can use the below code to set "To" value in the select dropdown

IWebElement option = driver.FindElement(By.XPath("//*[@class='field']/datalist/select"));
var selectElement = new SelectElement(option);
selectElement.SelectByText("To");
1
  • I tried this solution, but there is no text value. So, I still can not select desired option.
    – Majkl
    Commented Sep 20, 2019 at 16:45
0

Please use the below solution. Maybe it will help.

For example:

//*[contains(text(),'To')]

//*[contains(text(),'CC')]

//*[contains(text(),'Bcc')]

//*[contains(text(),'Subject')]

For more detail click on below and search for "Types of XPath Functions"

https://medium.com/edureka/xpath-in-selenium-cd659373e01a

Happy Testing :)

0

Instead of making "complex" XPaths I like to find a container I know the Id of. Then within that container search for in this case rows, within the second row search for a cell, within the cell find the dropdown.

var table = driver.FindElement(By.Id("advFilter"));
var rows = table.FindElements(By.TagName("tr"));
var cell = rows[1].FindElement(By.ClassName("field"));
var dropdown = new SelectElement(cell.FindElement(By.TagName("select")));
dropdown.SelectByText("YourOption");

Now, this might be slower, but I don't think you will notice it. It will be much easier to understand and read in the future.

4
  • I tried this solution, but there is no text value. So, I still can not select desired option.
    – Majkl
    Commented Sep 20, 2019 at 16:37
  • You found the Select element though. I am not sure how the SelectElement class works internally. Did you try by value or index? See the documentation: seleniumhq.github.io/selenium/docs/api/dotnet/html/… Commented Sep 20, 2019 at 18:09
  • While reading this answer stackoverflow.com/questions/9562853/… I would suspect the options to have the Text property filled. Your select has 14 options, that looks good, but maybe the page is still rendering? Maybe your test is to fast and the text hasnt been set yet? Commented Sep 20, 2019 at 18:12
  • During debugging, if test made a click on drop-down arrow I can see all options. But list is closed in the line var table = driver.FindElement(By.Id("advFilter")); And I got exception "OpenQA.Selenium.ElementNotInteractableException: 'element not interactable: Element is not currently visible and may not be manipulated" It is possible to write into the FIELD text box and search option in the list by letters, but I still can not select option.
    – Majkl
    Commented Sep 23, 2019 at 11:39
0

If you add a new condition in a condition builder the searching rule will be at the end of the list.

I'd find the last condition-builer-form by following XPath:

$x('(//datalist)[last()]')

After that, I'd try to navigate to the "To" field of the list:

$x('(//datalist)[last()]/select/option[@value="To"]')

Code:

const last_condition_form = find('(//datalist)[last()]')
const select_field = last_condition_form.find('/select')
select_field.select('To')
0

Work with your developers to either de-randomize the IDs or to add some other attribute you can target. Perhaps a CSS class, or another attribute so that you could do something along the lines of:

var dropdowns = driver.FindElements(By.XPath("//select[@custom='addressType']"));
// Do something with the first one.
dropdowns[0].SelectByText("To");

Use indexes to process more, or keep a list of IDs you've used and loop through as necessary.

If you can't get your development team to alter the DOM to make the various pieces more easily addressable, then you'll have to go through some of the other ways to do it that other people have outlined.

Not the answer you're looking for? Browse other questions tagged or ask your own question.