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?
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
I'm using Mink with Zombie.js and as it does not catching keyboard events natively, I both listen to focusout
and keyup
jQuery events.
$('form[name="order"]').find('input[id$="quantity"],input[id$="price"]').bind('keyup focusout', function(){
// [...] update order price
});
I has solved the problem for me but I didn't try it with Selenium2.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With