29

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 "example1@mail.com".

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?

12 Answers12

12

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
Roland Studer
  • 4,315
  • 3
  • 27
  • 43
3

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', 'user@mail.com')

Now I had to change it by:

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

emailParts = 'user@mail.com'.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])
Gabriel Anglada
  • 191
  • 1
  • 8
  • Thx a lot for this input, I added an answer, that actually works with ruby in a system tests, but this can't be the solution as it is dependent on the OS / keyboard layout… – Roland Studer Feb 03 '22 at 09:24
  • Hey as your answer pertains to python (I think, it would be good to open a new question & answer specific to python and delete this answer here. Thanks you! – Roland Studer Feb 03 '22 at 11:43
  • Another thing, do you have a source on the change, is this intended or a bug? – Roland Studer Feb 03 '22 at 12:27
3

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_with_at@email.com"
selector = "input_selector"
safe_send_keys(driver, selector, email)
3

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

Nori
  • 2,340
  • 1
  • 18
  • 41
2

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

  • This explains why it was not a problem for me, but was a problem for my teammates who are Spanish speakers. – Rob G Feb 08 '22 at 22:09
2

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.

Eric
  • 673
  • 1
  • 7
  • 23
  • I can confirm that in a different setting: On Rails w/Capybara, Selenium and Webdrivers, I just had to set: Webdrivers::Chromedriver.required_version = '97.0.4692.71' – ulf_t Feb 10 '22 at 10:11
2

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.

Ozkan
  • 21
  • 2
1

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]);
  • I think it would be better to ask a new question specific to Java, the question is for Ruby on Rails, we don't questions with answers in several languages. You are free to write a new question and we can link to it, will be happy to upvote your answer and question – Roland Studer Feb 03 '22 at 11:40
1

Just use JavascriptExecutor, for example:

 JavascriptExecutor jse = (JavascriptExecutor) getDriver();
 jse.executeScript("arguments[0].setAttribute('value', arguments[1])", googleEmailWebElement, email);
ouflak
  • 2,458
  • 10
  • 44
  • 49
matias
  • 57
  • 5
1

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
Arctodus
  • 5,743
  • 3
  • 32
  • 44
1

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)
Håkan
  • 13
  • 6
0

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

Martin
  • 151
  • 1
  • 8
  • 2
    There is no need to downgrade your Chrome version. Downgrading the ChromeDriver is enough, a 97 ChromeDriver can drive a 98 Chrome version. – Roland Studer Feb 06 '22 at 00:01