1

I am new to selenium and I am writing tests for an existing web app. I am trying to select an option from a dynamically generated list. The following HTML is an example of the list:

<table id="selectChannelForm">
<tbody id=""></tbody>
<tbody id="">
<tr rowtype="container">
<td colspan="3" class="second">
<ul>   
    <li>
        <a href="selectChannel.php?selectedChannelId=103">
        <span>Sales Channel</span>
        </a>
    </li>
    <li>
        <a href="selectChannel.php?selectedChannelId=108">
        <span>Demo channel</span>
        </a>
    </li>
    <li>
        <a href="selectChannel.php?selectedChannelId=112">
        <span>Finance Channel</span>
        </a>
    </li>
    <li>
        <a href="selectChannel.php?selectedChannelId=121">
        <span>HR Channel</span>
        </a>
    </li>
    <li>
        <a href="selectChannel.php?selectedChannelId=156">
        <span>Management Channel</span>
        </a>
    </li>
</ul>
</td>
</tr>
</tbody>
</table>

I need to select one of these channels for a test, but the problem is that I can't do a direct CSS or XPath reference because both the tbody and the channel list changes based on certain criteria. How would I use either the channelId or span text to select the correct option? The following is a direct CSS reference to the fourth option.

WebElement channelBtn = driver.findElement(By.cssSelector("#selectChannelForm > tbody:nth-child(2) > tr > td > ul > li:nth-child(4) > a"));

Is it at all possible to put some logic in these statements? Or some other means of selecting an nth-child?

adohertyd
  • 2,689
  • 19
  • 58
  • 78

4 Answers4

2

You can use an xpath like this to find the link with the channel you're looking for:

//a[@href='selectChannel.php?selectedChannelId=108']

Then, just replace 108 with whatever channel number you need.

James Dunn
  • 8,064
  • 13
  • 53
  • 87
  • Thanks for your answer but I was looking for a CSS response rather than XPath. It works but I have taken a more CSS based approach – adohertyd Dec 07 '14 at 11:46
1

To use 'Channel ID'

xpath = //a[@href='selectChannel.php?selectedChannelId=108']

css = a[href='selectChannel.php?selectedChannelId=108']

Second to use 'span text' to select the correct option you can use

xpath = //span[contains(text(),'Demo channel')]

css = span:contains('Demo channel')
Rupesh Shinde
  • 1,933
  • 12
  • 22
  • Thanks for your comment but `span:contains` doesn't work. Gives an `invalid selector exception` – adohertyd Dec 07 '14 at 11:45
  • 2
    If your application has a library which extends CSS it might have something which allows you to search for elements by the text value but standard CSS selectors do not allow you to select by the text between the tags. XPath is good for locating an element by the visible text – Rupesh Shinde Dec 07 '14 at 11:59
0

So after a lot of searching I have come up with the following solution for a CSS based approach. Works perfectly

List<WebElement> channels = driver.findElements(By.tagName("span"));
        for(WebElement channel : channels){
            String selectedChannel = channel.getText();
            if (selectedChannel.equalsIgnoreCase(channelId)){
                channel.click();
                break;
            }
        }
adohertyd
  • 2,689
  • 19
  • 58
  • 78
  • 2
    This is incredibly inefficient. What could be achieved in 1 xpath request will now take several requests using CSS. If you use RemoteWebdriver(and especially if you use Saucelabs or BrowserStack rather than an internal grid), then reducing the number of selenium commands is really important to have fast test runs. And if anyone mentions XPath being slow, that is no longer true with modern IE versions and infact is shown ti be faster than CSS selectors – Robbie Wareham Dec 08 '14 at 01:10
  • @RobbieWareham very good point that I didn't consider. I'm just learning Selenium at the moment so performance isn't my first concern, but you are correct and the XPath is the better solution – adohertyd Dec 08 '14 at 14:25
0

You can also try the below way using CSS selector:

WebElement channelBtn = driver.findElement(By.cssSelector("td.second:nth-of-type(1) li:nth-of-type(4) span"));

This will navigate to the span tag under 4th li tag of first td element with class 'second' in the webpage, i.e.,"HR Channel"

Subh
  • 4,354
  • 1
  • 13
  • 32
  • That's correct but as I said in my question this list is dynamic so in some cases the 4th
  • could be Management Channel for example. I need to be able to find the span by text, and while the XPath solution provided by @RupeshShinde allows that, I need to use CSS selectors
  • – adohertyd Dec 07 '14 at 14:14
  • Oh! in that case xpath(s) are your best possible option. Or else, the way you have used is another. Also, [take a look here](http://stackoverflow.com/a/4811976/4193730). This might come in handy too. – Subh Dec 07 '14 at 15:01