Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selenium-chromedriver: Cannot construct KeyEvent from non-typeable key

I updated my Chrome and Chromedriver to the latest version yesterday, and since then I get the following error messages when running my Cucumber features:

....
unknown error: Cannot construct KeyEvent from non-typeable key
        (Session info: chrome=98.0.4758.80) (Selenium::WebDriver::Error::UnknownError)
      #0 0x55e9ce6a4093 <unknown>
      #1 0x55e9ce16a648 <unknown>
      #2 0x55e9ce1a9866 <unknown>
      #3 0x55e9ce1cbd29 <unknown>
      .....

I try to fill a text field with Capybara's fill_in method. While debugging I noticed that Capybara has problems especially with the symbols @ and \. Every other character can be written into the text field without any problems.

The code that triggers the error looks like this

def sign_in(user)
  visit new_sign_in_path
  fill_in 'Email', with: user.email
  fill_in 'Password', with: user.password
  click_button 'Sign in'
end

user.email contains a string like "[email protected]".

I work with Rails 6.1.3.1, Cucumber 5.3.0, Chromedriver 98.0.4758.48, capybara 3.35.3

The error only occurs on features that are tagged with @javascript

Do you have any ideas what causes this error or how to fix it?


2 Answers

For now the easiest is to pin to an earlier version of the chrome driver, so add this to your capybara config

In ruby

# /test/support/system/capybara_config.rb
require 'webdrivers/chromedriver'
Webdrivers::Chromedriver.required_version = '97.0.4692.71'

Hopefully this issue will be addressed in future chromedriver releases, it has been raised and is discussed here

I also played around with overriding the fill_in method.

This is less than ideal, and actually OS dependent, so please provide better solution or update this answer. I will try to update as my research progresses.


class ApplicationSystemTestCase < ActionDispatch::SystemTestCase

  # overriding the `fill_in` helper for filling in strings with an `@` symbol
  def fill_in(locator = nil, with:, currently_with: nil, fill_options: {}, **find_options)
    return super unless with.include? "@"

    find_options[:with] = currently_with if currently_with
    find_options[:allow_self] = true if locator.nil?
    element = find(:fillable_field, locator, **find_options)
    email_front, email_back = with.split("@")

    element.send_keys(email_front)
    page.driver.browser.action
        .key_down(Selenium::WebDriver::Keys[:alt])
        .send_keys('g')
        .key_up(Selenium::WebDriver::Keys[:alt])
        .perform
    element.send_keys(email_back)
  end
end
like image 61
Roland Studer Avatar answered Sep 07 '25 19:09

Roland Studer


It seems something has changed in the new version of ChromeDriver and it is no longer possible to send some special chars directly using send_keys method.

In this link you will see how it is solved (in C#) --> Selenium - SendKeys("@") write an "à"

And regarding python implementation, check this out --> https://www.geeksforgeeks.org/special-keys-in-selenium-python/

Specifically, my implementation was (using MAC):

driver.find_element('.email-input', '[email protected]')

Now I had to change it by:

from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains

emailParts = '[email protected]'.split('@')
emailElement = driver.find_element('.email-input')

emailElement.send_keys(emailParts[0])
action = ActionChains(driver)
action.key_down(Keys.ALT).send_keys('2').key_up(Keys.ALT).perform()
emailElement.send_keys(emailParts[1])
like image 30
Gabriel Anglada Avatar answered Sep 07 '25 21:09

Gabriel Anglada