Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

browser.keys() is not working on Firefox 53.0 & webdriver.io

On firefox, browser.keys throwing error.

Os: MacOs
Firefox version: 53.0.3
Geckodriver: 0.16.1
Webdriver.io: 4.8

Please help me how to deal with this error.

Here are the logs

[17:11:35]  COMMAND POST     "/wd/hub/session/97804a03-d52a-4232-9e3c-41e1fac6a9c5/url"
[17:11:41]  COMMAND POST     "/wd/hub/session/97804a03-d52a-4232-9e3c-41e1fac6a9c5/refresh"
[17:11:45]  COMMAND GET      "/wd/hub/session/97804a03-d52a-4232-9e3c-41e1fac6a9c5/window/current/size"
[17:11:46]  COMMAND POST     "/wd/hub/session/97804a03-d52a-4232-9e3c-41e1fac6a9c5/elements"
[17:11:46]  COMMAND GET      "/wd/hub/session/97804a03-d52a-4232-9e3c-41e1fac6a9c5/element/0/displayed"
[17:11:46]  COMMAND GET      "/wd/hub/session/97804a03-d52a-4232-9e3c-41e1fac6a9c5/element/1/displayed"
[17:11:46]  COMMAND POST     "/wd/hub/session/97804a03-d52a-4232-9e3c-41e1fac6a9c5/elements"
[17:11:46]  COMMAND GET      "/wd/hub/session/97804a03-d52a-4232-9e3c-41e1fac6a9c5/element/0/displayed"
[17:11:46]  COMMAND GET      "/wd/hub/session/97804a03-d52a-4232-9e3c-41e1fac6a9c5/element/1/displayed"
[17:11:46]  COMMAND POST     "/wd/hub/session/97804a03-d52a-4232-9e3c-41e1fac6a9c5/elements"
[17:11:47]  COMMAND POST     "/wd/hub/session/97804a03-d52a-4232-9e3c-41e1fac6a9c5/element/0/value"
WARNING: the "keys" command will be depcrecated soon. Please use a different command in order to avoid failures in your test after updating WebdriverIO.
[17:11:47]  COMMAND POST     "/wd/hub/session/97804a03-d52a-4232-9e3c-41e1fac6a9c5/keys"
[17:11:47]  COMMAND GET      "/wd/hub/session/97804a03-d52a-4232-9e3c-41e1fac6a9c5/screenshot"
[17:11:48]      Saved screenshot: ERROR_firefox_2017-06-03T00-11-47.734Z.png
[17:11:48]  COMMAND DELETE   "/wd/hub/session/97804a03-d52a-4232-9e3c-41e1fac6a9c5/cookie"
Error: sendKeysToActiveElement
Build info: version: '3.4.0', revision: 'unknown', time: 'unknown'
System info: host: 'xxx.local', ip: '10.142.4.252', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.12.5', java.version: '1.8.0_131'
Driver info: driver.version: RemoteWebDriver
Error: The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource.
    at Object.wait (/Users/xxxx/c3web/xxxx/node_modules/fibers/future.js:449:15)
    at Object.keys (/Users/xxxxx/node_modules/wdio-sync/build/index.js:264:31)
    at Object.exports.customCommands.selector (/Users/xxx/c3web/xxxx/testlib/browser/customCommands.js:158:17)
    at /Users/xxxx/node_modules/wdio-sync/build/index.js:191:29
    - - - - -
    at keys("Enter") - index.js:244:37
    at elementIdValue("0", "xxxyyyzzz") - index.js:293:3
like image 814
LookAtSrc Avatar asked Jun 03 '17 00:06

LookAtSrc


2 Answers

As @iamdanchiv mentioned in his answer, the browser.keys() will be deprecated, but there is a workaround (and I should submit a PR for this).

What browser.keys() does under the hood is to call the /session/:sessionId/keys endpoint in the WebDriver JsonWire protocol. However, if you look at the list of endpoints in the W3C Webdriver's specification, this endpoint is not in the list. I believe it was previously part of the list, but has been dropped. Instead, to send keys, the specification states to use the /session/:sessionId/element/:elementId/value endpoint instead, which you can use webdriverio's browser.elementIdValue(ID, value) method to call.

Now, if you read up on the specifications of /session/:sessionId/keys mentioned in Selenium's documentation on the JsonWireProtocol it is pretty easy to do replicate the implementation using other WebDriver functionalities. The /session/:sessionId/keys endpoint simply does this:

Sends a sequence key strokes to the active element.

There is an endpoint we can call to grab the current active element, which is /session/:sessionId/element/active, which is mapped to webdriverio's browser.elementActive() method.

At such, all we need to do is to reimplement this browser.keys() is to find out first what's the active element, then send the keys to that element.

So this is the workaround solution, if you wanted to send browser.keys("hello world"):

var result = browser.elementActive();
var activeElement = result.value && (result.value.ELEMENT || result.value["element-6066-11e4-a52e-4f735466cecf"]);
// Newer versions of the webdriver like Gecko/IEDriver return the element as "element-6066-11e4-a52e-4f735466cecf" (which is documented in the W3C specs) instead of "ELEMENT".
if(activeElement){ 
     browser.elementIdValue(activeElement, "hello world");
}

Note this is does not replicate of the behaviour of /session/:sessionId/keys exactly, which also does this according to Selenium's documentation:

This command is similar to the send keys command in every aspect except the implicit termination: The modifiers are not released at the end of the call. Rather, the state of the modifier keys is kept between calls, so mouse interactions can be performed while modifier keys are depressed.

The above solution does implicitly release modifier keys such as "SHIFT", "CTRL" at the end of the key sequence. So if you want to hold a key and do mouse interactions, then tough luck buddy, perhaps we have to wait for the browsers to implement the Webdriver Actions API. But if all you wanted to do is to send "CTRL" + "C", you just can send an array of keys like this:

var result = browser.elementActive();
var activeElement = result.value && result.value.ELEMENT;
if(activeElement){ 
     browser.elementIdValue(activeElement, ["CTRL", "c"]);
}
like image 163
Shi Ling Avatar answered Oct 11 '22 19:10

Shi Ling


Well, that error pretty much explains that there is an issue with the implementation of the keys command: WARNING: the "keys" command will be depcrecated soon. Please use a different command in order to avoid failures in your test after updating WebdriverIO..

It is currently only working with chromedriver in my test cases too, but I'm also not able to chain commands with it. (simulate Ctrl+C, Ctrl+V).

See my answer on this question. You'll have to find another way to go around this, or wait for the drivers (chromedriver, geckodriver, etc.) to implement the new Selenium actions methods.

The answer I gave there pretty much covers the entire issue. Alternatively, you could try the codepoint approach: browser.keys("\uE007").

Hope this helps you!

like image 40
iamdanchiv Avatar answered Oct 11 '22 19:10

iamdanchiv