Can I send raw keyboard input using Mink and Selenium2? Can I send raw keyboard input using Mink and Selenium2? php php

Can I send raw keyboard input using Mink and Selenium2?


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.


The easiest answer I have found is to trigger the key event in javascript and write a specific behat step to send the js to the browser and trigger it.

We have been using YUI so we use the YUI event simulate but jquery or native js handles it. The concept is what matters. It's the best solution I've found until the native behat support is there.

hope this helps.

public function press_key_in_the_ousupsub_editor($keys, $fieldlocator) {        // NodeElement.keyPress simply doesn't work.        if (!$this->running_javascript()) {            throw new coding_exception('Selecting text requires javascript.');        }        // We delegate to behat_form_field class, it will        // guess the type properly.        $field = behat_field_manager::get_form_field_from_label($fieldlocator, $this);        if (!method_exists($field, 'get_value')) {            throw new coding_exception('Field does not support the get_value function.');        }        $editorid = $this->find_field($fieldlocator)->getAttribute('id');        // Get query values for the range.        $js = '    function TriggerKeyPressBehat() {    // http://www.wfimc.org/public/js/yui/3.4.1/docs/event/simulate.html    YUI().use(\'node-event-simulate\', function(Y) {        var id = "'.$editorid.'";        var node = Y.one("#" + id + "editable");        node.focus();        var keyEvent = "keypress";        if (Y.UA.webkit || Y.UA.ie) {            keyEvent = "keydown";        }        // Key code (up arrow) for the keyboard shortcut which triggers this button:        var keys =  ['.$keys.'];        for(var i=0; i<keys.length;i++) {            node.simulate(keyEvent, { charCode: keys[i] });        }    });    }    TriggerKeyPressBehat();';        $this->getSession()->executeScript($js);    }