user16390406
user16390406

Reputation:

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?

Upvotes: 29

Views: 7980

Answers (12)

Nori
Nori

Reputation: 3002

This answer is for Java and WebDriverManager users.

You can specify chrome driver version like this before start chrome.

WebDriverManager.chromedriver().browserVersion("97").setup();

You can work around this problem.

Update

This ChromeDriver bug has fixed

Upvotes: 3

Ozkan
Ozkan

Reputation: 21

I am using Selenium with Java. I have been automating login functions without any problem until the Google Chrome update. After the update, I started getting the same error as well. I just changed my keyboard language to "US" and the problem is solved.

Update: Recently (mid-February) my ChromeDriver stopped giving the same error. I am not sure if there has been a fix as I didn't see a new release since I started having problems but my Java/Selenium automation codes run without any error regardless of the keyboard language and send characters like '@'. So, no need to switch the keyboard language to "US" anymore.

Upvotes: 2

Roland Studer
Roland Studer

Reputation: 4415

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

Upvotes: 12

Eric
Eric

Reputation: 793

I was getting the same error for python. If Google chrome automatically updated to version 98 don't update your chromedriver to 98 also, use 97 instead. This solved my issue.

Upvotes: 2

H&#229;kan
H&#229;kan

Reputation: 13

This issue affected me as well. This answer is for Python. This is how I currently set up my selenium tests in django. My chromium browser is snap version 98.0.4758.80.

@classmethod
def setUpClass(cls):
    super().setUpClass()

    options = webdriver.ChromeOptions()
    options.add_argument('--no-sandbox')  # Must be the very first option
    options.add_argument('--headless')
    options.add_argument('--disable-gpu')
    options.add_argument('--disable-software-rasterizer')

    options.add_argument('--disable-dev-shm-usage')
    options.add_argument("--remote-debugging-port=9222")
    options.add_argument("--no-default-browser-check")
    options.add_argument("--no-first-run")
    options.add_argument("--disable-default-apps")

    s = Service(
        ChromeDriverManager(
            # version='98.0.4758.80',
            # version='98.0.4758.48',
            version='97.0.4692.71',
            log_level=logging.WARNING,
            chrome_type=ChromeType.CHROMIUM).install())

    cls.selenium = webdriver.Chrome(
        service=s,
        options=options)
    cls.selenium.implicitly_wait(1)

Upvotes: 1

Arctodus
Arctodus

Reputation: 5847

This is hopefully a temporary problem that will be solved in a later release https://github.com/SeleniumHQ/selenium/issues/10318

A test macro using JS to fill in the field solved my needs (Ruby) for basic scenarios like

fill_in :user_email, with: user.email

Test macro:

def fill_in_chrome98_tmp_fix(locator, with:)
  element = find(:fillable_field, locator)
  dom_id = element.native.dom_attribute("id")
  raise "No DOM ID" if dom_id.blank?
  page.execute_script("document.getElementById('#{dom_id}').value = '#{with}'")
end

Upvotes: 1

Tomasz Buga
Tomasz Buga

Reputation: 21

We had the same issue with my co-worker today.

What worked for us was removing any language from the Chrome settings, but the English (I'm using the Polish language as well and it seems like it's not causing the issue).

Machine: MacBook Pro with macOS Monterey 12.1; Test Framework: Java 11/Selenium

Chrome v.98 - Language settings

Upvotes: 2

matias
matias

Reputation: 55

Just use JavascriptExecutor, for example:

 JavascriptExecutor jse = (JavascriptExecutor) getDriver();
 jse.executeScript("arguments[0].setAttribute('value', arguments[1])", googleEmailWebElement, email);

Upvotes: 1

Martin
Martin

Reputation: 171

Update of Google Chrome from the previous Version: 97.0.4692.99-1 to the newest one Version: 98.0.4758.80-1 also affect my code. I am using Python and I couldn't send any more characters as @, ^. For now, I simply downgrade the version of Google Chrome. It affected on such a structure: self.driver.find_element_by_id('id_password').send_keys(password), where e.g. password contains ^.

Link to a simple downgrade of chrome version on linux machines: https://makandracards.com/makandra/486433-how-to-downgrade-google-chrome-in-ubuntu

Upvotes: 0

I had the same problem with Python, and it seems that using only ActionChains solves the problem in an easy way.

from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By

def safe_send_keys(
    driver,
    input_selector: str,
    input_text: str,
    selector_type = By.CSS_SELECTOR
):
    driver.find_element(selector_type, input_selector).click()
    action = ActionChains(driver)
    action.send_keys(input_text)
    action.perform()

# Example
driver = webdriver.Chrome()
# ... Go to your web page
email = "[email protected]"
selector = "input_selector"
safe_send_keys(driver, selector, email)

Upvotes: 3

abarragancosto
abarragancosto

Reputation: 11

I have same problem. I solved it for Selenium java like:

 String arroba = Keys.chord(Keys.ALT, "2");

 String[] mailSplit = mail.split("@");

 userInput.sendKeys(mailSplit[0]);

 userInput.sendKeys(arroba);
 userInput.sendKeys(Keys.BACK_SPACE);

 userInput.sendKeys(mailSplit[1]);

Upvotes: 1

Gabriel Anglada
Gabriel Anglada

Reputation: 201

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])

Upvotes: 3

Related Questions