Can I send raw keyboard input using Mink and Selenium2?

jcsanyi picture jcsanyi · Jun 27, 2013 · Viewed 7.5k times · Source

I am using Behat and Mink with the Selenium2 driver, and I'm trying to type directly into a form field (simulating raw keyboard input), instead of using the fillField() function.

This is what I'm trying:

$element = $this->getSession()->getPage()->find('css', '#questionName');
$element->focus();

$element->keyPress('a');

// also tried this, with no success
// $element->keyDown('a');
// $element->keyUp('a');

There is an <input type="text" id="questionName"> element on the page. It correctly receives the focus, but does not respond to any of the simulated keyboard input.

Is it possible to simulate raw keyboard input like this?
What am I doing wrong?

Answer

Tom picture Tom · Jul 8, 2013

There seems to be a lot of posts complaining about keyPress not working as intended and some drivers don't support it at all. e.g.:

Goutte - Keyboard manipulations are not supported by Behat\Mink\Driver\GoutteDriver

The Selenium driver in particular uses a custom js library to run it's commands, however it doesn't seem to work. I've tried using both the $this->getSession()->getDriver()->keyPress() and the $element->getPress() without luck.

https://github.com/Behat/MinkSelenium2Driver/blob/master/src/Behat/Mink/Driver/Selenium2Driver.php#L815

https://github.com/Behat/MinkSelenium2Driver/blob/master/src/Behat/Mink/Driver/Selenium2/syn.js

What is interesting is that there are no unit tests for the keyPress event in the Selenium2 code base yet (so I assume it's currently in development).

So, for the moment, an adequate solution is to use the javascript emulation of key events from Is it possible to simulate key press events programmatically? (see this for an alternative if you're not using jQuery) and Behat Mink's evaluateScript function.

If you're using straight PHPUnit to test:

$key = 'a';
$script = "jQuery.event.trigger({ type : 'keypress', which : '" . $key . "' });";
$this->getSession()->evaluateScript($script);

Or if you're using Cucumber, add this to your FeatureContext.php file you can add this function:

/**
 * @Given /^(?:|I ) manually press "([^"]*)"$/
 */
public function manuallyPress($key)
{
    $script = "jQuery.event.trigger({ type : 'keypress', which : '" . $key . "' });";
    $this->getSession()->evaluateScript($script);
}

And use it in your feature file like this:

Given I manually press "a"

As for using the javascript as the solution, some of the drivers use javascript to perform the required keyPress. E.g.:

https://github.com/Behat/MinkZombieDriver/blob/master/src/Behat/Mink/Driver/ZombieDriver.php#L819