I was just wondering if you could point out where the problem is here, if it's Behat, the CSS selector, or the Sahi Driver.
We have just upgraded to Behat 3 and are using Sahi Driver (most recent open source version). We have found that any Behat test that uses the pseudo-element first-child
now seems to break.
Example:
Step:
And I follow "#the-list tr:first-child .row-title"
(which contains an anchor element with the class row-title on it, see HTML)
Error:
Link with id|title|alt|text "#the-list tr:first-child .row-title" not found. (Behat\Mink\Exception\ElementNotFoundException)
HTML:
<tbody id="the-list">
<tr id="post-162382" class="post-162382 type-post status-publish format-standard hentry category-uncategorized alternate iedit author-other level-0">
<th class="check-column" scope="row"></th>
<td class="post-title page-title column-title">
<strong>
<a class="row-title" title="Edit “Post Title”" href="https://domain.com"></a>
</strong>
<div class="locked-info"></div>
<div class="row-actions"></div>
<div id="inline_162382" class="hidden"></div>
</td>
CSSSelector.php (override we used with our old Behat, we left this file in)
/**
* Makes all of the form field related steps allow CSS selectors.
*/
class CSSSelectorContext extends MinkContext
{
/**
* Finds an element via CSS or fails with a given error
*
* @param $element string A CSS selector string
* @param $error Exception An error to throw in case the element can not be found
* @return object An Element object
*/
protected function findOrFail($element, $error){
$element = $this->getSession()->getPage()->find('css', $element);
if (!isset($element)){
throw $error;
}
return $element;
}
public function clickLink($link) {
try {
parent::clickLink($link);
return;
}catch (Exception $error){
$link = $this->fixStepArgument($link);
$link = $this->findOrFail($link, $error);
$link->press();
}
}
When using the css selector in the Chrome console with jquery it selects the appropriate element. I went through the code and looked at the css -> xpath translations and then validated the xpath against the html that is produced on the site we are testing and it seems to be valid as well. The css selector also works with Goutte driver.
Generated XPath:
find(function(){
var count = 0;
while (_sahi._byXPath("("+"\/\/html\/descendant-or-self::*[@id = 'the-list']\/descendant-or-self::*\/*[name() = 'tr' and (position() = 1)]\/descendant-or-self::*\/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' row-title ')]"+")["+(count+1)+"]")) count++;
return count;
})()
descendant-or-self::*[@id = 'the-list']/descendant-or-self::*/*[name() = 'tr' and (position() = 1)]/descendant-or-self::*/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' row-title ')]
//html/descendant-or-self::*[@id = 'the-list']/descendant-or-self::*/*[name() = 'tr' and (position() = 1)]/descendant-or-self::*/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' row-title ')]
When I change the CSS to:
Step:
And I follow "#the-list tr .row-title"
It works because I believe it just picks the first tr from a list of them anyway, but we want to be able to use first-child of course.
Thanks for your help!