Chromedriver not filling all the whole password field in automated RSpec, Capybara, Feature Tests
This is such a lovely story. You will like it.
When using google chromedriver to run capybara tests sometimes, just sometimes, especially if the tests are run in parallel, when the test has to fill a text field like a password, it fills only part of it. Last time checked for chromedriver 2.45
TL; DR;
Solution – google does not care, or it seems it is too difficult for the chromedriver team to resolve so there simply is no solution.
What is the test?
We are using Rails, Rspec, Capybara, Google chromedriver. We are developing feature tests. Tests are run in parallel with
rake parallel:spec
Here is the test in question. Simply fill a password on the form for upgrading a subscription, click on Confirm and expect to be redirected to a page that says – “You’ve upgraded your subscription”
def submit_and_expect_success password
# dialog opens to confirm with password
fill_in "owner_password", with: password
click_on "Confirm"
expect_redirect_to "/subscriptions/#{subscription.to_param}"
# If it redirects to this page, it means that the change was successful
expect(page).to have_current_path "/subscriptions/#{subscription.to_param}"
end
And the tests are failing with timeout at expect_redirect_to. No, expect_redirect_to is a custom method, because we are using ActionCable to wait for subscription upgrade to finish. Because of the payment service at the back this sometimes takes a while and we want to show a nice progress and we need a websocket. But that being said the method is nothing special.
module ExpectRedirect
def expect_redirect_to url
# If the path doesn't change before the timeout passes,
# the test will fail, because there will be no redirect
puts "expect url: #{url}"
begin
Timeout.timeout(Capybara.default_max_wait_time) do
sleep(0.1) until url == URI(page.current_url).path
page.current_url
end
rescue Timeout::Error=>e
puts "Current url is still: #{page.current_url}"
puts page.body
raise e
end
end
end
If we are redirected to the url withing Capybara.default_max_wait_time than everything is fine. If not, we are raising the Timeout::Error.
Parallel execution
For some reason the test in question fails only when we are doing a parallel execution. Or at least mostly when we are doing parallel execution of the tests. So we moved through some nice articles to revise our understanding of Timeout again and again.
https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/
But nevertheless the tests were failing with Timeout::Error on waiting for a redirect and in the html we could see the error returned by the server:
<div><p>Invalid password</p></div>
How come the password is Invalid
No this took a while to debug and it seems rather mysterious but this is what we got:
User password in DB is: 10124ddeaf1a69e3748e308508d916b6
The server receives from the html form: 10124ddeaf1a69e3748e30850
User password in DB is: 74c2a3e926420e1a30363423f121fc1e
The server receives from the html from: 74c2a3e926420e1a3
and so on and so on.
Sometimes the difference is 8 symbols. Sometimes it is 2. Sometimes it is 16.
It seems to be a client side issue
Like. JavaScript. If there is an error this strange it has to be in the JavaScript. Right. There in the javascript we see:
let form_data = form.serializeObject();
this.perform('start_change', form_data);
The form gets serialized. Probably it is not serialized correctly. Probably the values that we are sending are just not the values on the form. So I revised my knowledge on serializing objects in JavaScript with
https://stackoverflow.com/questions/17488660/difference-between-serialize-and-serializeobject-jquery
So far so good. But the serialization was not the problem. Here is what I did. I fixed all the passwords to be 32 symbols.
let form_data = form.serializeObject();
if(form_data["owner_password"].lenght != 32) {
form_data["owner_password"] = "this was:" + form_data["owner_password"] + " which is less than 32 symbols"
}
this.perform('start_change', form_data);
It it happened. The value of the password field was simply not 32 symbols long. It was not filled during the test.
A little bit of search and we arrive at:
https://github.com/teamcapybara/capybara/issues/1890
and there in the bottom of the issue, there is the standard: “Not our problem resolution” with the link to:
It seems that google chromedriver is not filling all the characters in the password field. It is doing it on random and is completely unpredictable.
Issue still exists on:
Issue still exist for
Chrome: Version 71.0.3578.98 (Official Build) (64-bit)
Chromedriver chromedriver --version
ChromeDriver 2.45.615279 (12b89733300bd268cff3b78fc76cb8f3a7cc44e5)
Linux kireto-laptop3 4.4.0-141-generic #167-Ubuntu x86_64 GNU/Linux
Description: Ubuntu 16.04.5 LTS
Release: 16.04
Codename: xenial
Today we would try Firefox driver.
Reply
You must be logged in to post a comment.