Question

I am new to Behat. I am currently using the Mink Extension and the Selenium2 driver and I would like to know how to specify that the test should hover over an element as part of the Scenario.

For example, here is my scenario:

Scenario: Testing that the Contact Us submenu appears
    Given I am on "/"
    When I hover over "About"
    Then I should see "Contact Us"
Was it helpful?

Solution

I figured it out, based on this answer https://stackoverflow.com/a/17217598 and just replaced the click() with mouseOver().

Here is my FeatureContext code:

/**
 * @When /^I hover over the element "([^"]*)"$/
 */
public function iHoverOverTheElement($locator)
{
        $session = $this->getSession(); // get the mink session
        $element = $session->getPage()->find('css', $locator); // runs the actual query and returns the element

        // errors must not pass silently
        if (null === $element) {
            throw new \InvalidArgumentException(sprintf('Could not evaluate CSS selector: "%s"', $locator));
        }

        // ok, let's hover it
        $element->mouseOver();
}

I have to pass the css selector when I use it, so usage looks like:

...
When I hover over the element ".about"
...

OTHER TIPS

Alternate hover over

/**
 * @Then /^I hover over "([^"]*)"$/
 */
public function iHoverOver($arg1)
{
    $page = $this->getSession()->getPage();
    $findName = $page->find("css", $arg1);
    if (!$findName) {
        throw new Exception($arg1 . " could not be found");
    } else {
        $findName->mouseOver();
    }
}
/**
 * works better with css, uses different method for css than xpath
 * @Then /^I mouse over "(?P<selector>[^"]*)"$/
 */



 public function iMouseOver($selector){
        $element = $this->find($selector);
        if($element == null){
            throw new Exception('Element '.$selector.' NOT found');
        }
        $this->iFocusOn($selector);
        if (strstr($selector, '//')) {
            $element->mouseOver();
        } else {
            $this->mouseOver($selector, '1');
        }
    }

I appreciate this question is 4 years old with an accepted answer but your example uses a phrase to identify which element to hover over rather than a CSS selector. I think is a good thing as I like my Behat scripts to be readable by the client and non-technical members of the project team.

So if I may offer an alternative answer:

The script:

...
When I hover over the "About" link
...

The step definition in your FeatureContext:

    /**
     * @Then I hover over the :phrase link
     */
    public function iHoverOverLink($phrase)
    {
        $session = $this->getSession();

        // Get all link elements on the page
        $links = $session->getPage()->findAll('css', 'a');

        foreach($links as $link) {
            if ($link->getText() == $phrase) {
                // ok, let's hover it
                return $link->mouseOver();
            }
        }

        throw new \InvalidArgumentException(sprintf('Could not find anchor element matching "%s"', $phrase));
    }

My example narrows the targetable items down to only anchor elements for speed and efficiency but if you did have non-clickable items in your navigation menu that you wanted to hover over then you could easily remove the word " link" from the end of the step template and change the CSS selector to match all text elements p, span, li, a.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top