Make CSS Selector (first-child) work in Behat 3 with Sahi Driver
Asked Answered
S

1

8

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!

Starve answered 26/11, 2014 at 16:16 Comment(6)
This github issue seems to be talking about the same thing. Does it help at all?Mazurek
The issue github.com/symfony/symfony/issues/11803 is relevant, but it doesn't make sense because the Xpath that is generated by Symfony seems correct.Starve
Have you tried "#the-list tr:nth-child(1) .row-title"?Budget
How about just doing it this way and positioning with css of necessary as a work around #the-list .row-titleWearisome
Sorry if a silly/patronising question but have you inspected the element through Firebug to rule out anything else overriding the rules and are you processing the CSS in any way - leading to, have you double checked the output CSS in additon to your development copy?Republicanize
I am no longer using Behat (switched jobs) so I am not able to comment on this anymore and don't have time to investigate possible solutions/answers. Thanks for your efforts.Starve
M
0

Sorry for being late to the party

Your problem here is the fact that Minks own step "I follow"/"clickLink" doesn't accept the following:

  1. "#"s for ID's
  2. Anything other than an ID, Text, Title or Alternate Value.

I suggest using a "click on the" step instead of a "follow", something like this:

    /**
     * @Then /^(?:|I )click (?:|on )(?:|the )"([^"]*)"(?:|.*)$/
     */
    public
    function iClickOn($arg1)
    {
        $findName = $this->getSession()->getPage()->find("css", $arg1);
        if (!$findName) {
            throw new Exception($arg1 . " could not be found");
        } else {
            $findName->click();
        }
    }

You're using CSS right here, which will allow for this to be written:

Then I click on the "#the-list tr:first-child .row-title" link

It is a mistake I also made, and this is the solution we decided on then, and we haven't had to look back.

Modality answered 8/3, 2016 at 10:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.