2

I am using Selenium WebDriver wrapped in PHPUnit and Sausage to test clicking a button in a specific row in a table that's laid out similar to:

<tr id="dynamically generated 1">
    <td class="foo">
        <div class="bar"></div>
    </td>
    <td class = "mybutton">
        <span class = "icon clickable"></span>
    </td>
</tr>
<tr id="dynamically generated 2">
    <td class="foo">
        <div class="baz"></div>
    </td>
    <td class = "mybutton">
        <span class = "icon clickable"></span>
    </td>
</tr>

In particular, I want to click a specific element #mybutton > span.icon.clickable whose sibling is .foo with child .baz. The "whose sibling is .foo with child .baz" requirement is the only way I can currently identify the correct element, as other rows in the same table have element #mybutton > span.icon.clickable, and the ids for those rows are dynamically generated.

At the moment I am using XPath, but as you might expect, performance on FF and IE is horrendous. Is there a method for retrieving the value of tr#id from the element tr#id div.bar? If I can get this, I can use the id to use CSS to find the element I am looking for. I am using PHP, but a solution in any language would be useful.

Alternatively, a more straightforward CSS3 solution would work, but after quite a bit of reading, I've all but concluded that using a standard CSS3 selector is not an option for this case. Just in case there is something I'm missing, is there a CSS3 solution for this? I know there is a CSS4 solution, but I need full browser support, so until all the browsers I am testing support CSS4, I'll have to rely on CSS3.

Thanks in advance.

EDIT: Until there is better cross-browser support for CSS4, I need to use CSS3

Clandestine
  • 1,449
  • 1
  • 13
  • 30

3 Answers3

2

The only way I can think to do this is to find a List<WebElement> generated by By.cssSelector(".foo~span.icon.clickable") and on each element do a findElement(By.cssSelector(".baz")) surrounded by try/catch (catching NoSuchElementExceptions).

When there isn't an error thrown, then you know that you have found your element.

Note: The ~ selects it if it has ANY proceeding .foo siblings. If you want it to be the immediately previous sibling, use +

Nathan Merrill
  • 7,648
  • 5
  • 37
  • 56
  • Works great. For anyone interested in the php solution: – Clandestine Aug 03 '13 at 19:03
  • For anyone interested in the php solution: To get all elements that match some criteria: `$elements = $this->elements($this->using('css selector')->value('tr'));` To get the value of some attribute of one of the elements in that list of elements: `$id = $elements[0]->attribute('tr#id');` – Clandestine Aug 03 '13 at 19:14
2

There is no CSS way to select this, because it would require a selector that looks at previous elements, which is not available in CSS3.

However, this would be quite simple in jQuery. I made a selector for your situation

$(".foo").has(".baz").siblings(".mybutton").find("span.icon.clickable").addClass('red');
  • $(".foo") - selects elements with a class of foo
  • .has(".baz") - only returns elements that has a sibling with a class of baz. In this case, .foo with a .baz element
  • .siblings(".mybutton") - looks for an element with the class of mybutton on the same level as the previous element. Since we used has() instead of .foo .baz, this will still target the .foo element
  • .find("span.icon.clickable") - looks for a descending span from the previous element with classes of icon and clickable
  • .addClass('red'); - just a function to finish the example

Fiddle

Cody Guldner
  • 2,888
  • 1
  • 25
  • 36
1

There is a sibling selector in css called ~ and there are some css4 selectors which might help.

Perhaps this would work, if I understood the requirement correctly:

#mybutton > .foo ~ span.icon.clickable! > .baz 

This should work in chrome, but its css4 so, it probably wont work in a lot of browsers.

Hint: It selects the span.icon.clickable which has a child .baz

user1721135
  • 6,864
  • 8
  • 34
  • 63
  • Thanks. I need a solution that will work with browsers not yet supporting css4, so I'm afraid this won't work for me quite yet. I'll edit my question to specify css3. – Clandestine Aug 02 '13 at 21:41
  • You could use jquery. – user1721135 Aug 02 '13 at 21:50
  • Also @user1721135, the actual selector I'm looking for is `span.icon.clickable` whose parent `.mybutton` has a sibling `.foo` with child `.baz`. Isn't the CSS4 expression for that `.foo! baz ~ .mybutton > span.icon.clickable`? – Clandestine Aug 02 '13 at 22:00