Capybara cannot fill Stripe Checkout.js fields - capybara

I am having a difficult time testing Stripe's Checkout.js product with Capybara. The problem is Stripe has some tricky client side validation that fools Capybara's javascript driver, so when I tell Capybara to fill in a field, like this:
fill_in "card_number", with: "4242424242424242"
Stripe field only fills up oly the first three digits then it automatically puts a space after those digits, and that breaks Capybara badly.
How can I fix this?

I don't know exactly but when i get into these situations i consider dropping directly into the browsers javascript, such as (in this case assuming jquery is present)
page.execute_script(%Q{ $('input#itsId').val('424242424242424242'); })

Related

RSpec/Capybara: Not detecting

I'm running feature test in my rails app with Rspec and capybara. I'm filling out a form, which includes the following code:
<%= f.collection_select(:model_id, Model.all, :id, :name) %>
This code works COMPLETELY fine when I actually go to the view, and it shows all of the expected name.
I'm trying to fill it out in my Rspec feature test like so:
select('Option', :from 'model[model_attributes][model_id]')
However, capybara always gives me the error
Capybara::ElementNotFound:
Unale to find option 'option'
When capybara gives me a screenshot and I go to the screenshot, the select element from that form just appears as a blank form (all the other ones besides the collection_select appear fine). Since it doesn't appear in the screenshot, does that mean Capybara simply doesn't support the collection_select at the moment?
Thank you in advance.
UPDATE: Solved my own question.
I simply had to initialize objects with FactoryGirl before visiting the page and submitting the form. That way, the collection select had something to look for.

How to test that a form successfully submitted using Rspec?

I'm writing feature specs for my Article form.
In one test, I have RSpec look for certain form inputs using the labels:
expect(find_field("Title")).to_not be_nil
Now I'd like to know if the form was submitted properly. How can I do this using RSpec, if you aren't supposed to check the database from a feature spec?
For example, what if I mistyped the name attribute on the Title input? The label would still be found by my find_field() call, and controller specs would have me specify the title in a hash.
In this case one would assume a Title would be required for an Article so if the name attribute was misspelled the creation of the Article would fail and you'd end up on an error page (Also an unpermitted parameter would raise in the creation by default in test mode with strong parameters). If its a field not required for creation of the Article then the assumption is that the info is displayed in the app somewhere and can be checked for on that page.
As an aside your sample expect would read much clearer if rewritten as
expect(page).to have_field('Title')
There are loads of way to approach this:
expect(page).to have_field('Title')
expect(page).to have_css('#someSelector')
expect(current_path).to eq article_path (for example)
expect(page).to have_content "ABC" (i.e. some content which will be rendered)
The Capybara readme on Github is a really good one full of easy to follow examples - https://github.com/jnicklas/capybara.

How to wait till an element appears after an AJAX call using capybara-webkit?

The capybara method, wait_until doesn't seems to work for capybara-webkit. Is there any alternate solution for that, or any Javascript implementations?
Intentionally need some replacement for sleep, e.g. sleep 2.
If your AJAX call results in a change to the DOM, Capybara will wait for it if you do
page.should have_selector?("some selector")
It is an intentional Capybara feature that it waits (up to Capybara.default_wait_time) for have_selector? and related methods to be true.
If your AJAX call does not result in a change to the DOM, there's no way to wait for it on the browser side using Capybara. You might be able to detect when the AJAX call is complete in Javascript and somehow communicate that to Capybara, but that would couple your test and implementation rather tightly. A common approach in this case is to wait for the server-side effect of your AJAX call (creation or update or deletion of a model object, sending of an email, etc.) to take place. Since Capybara can't see the server side you have to wait for the server-side change yourself.
In Capybara 1 you can use Capybara's wait_until to wait for the server-side change. wait_until was removed from Capybara 2. I posted an implementation of wait_until in my answer to Why does adding "sleep 1" in an after hook cause this Rspec/Capybara test to pass?
I didn't really need the expectation as it wasn't what I needed to test.
This worked for me:
page.has_css?('.my-selector')
# or
page.has_content?('Some text on the page')
# continue with test
Maybe something like this:
# AJAX BEGIN
expect(page).to have_selector('form#new_user_video .submit > .throbber')
expect(page).to_not have_selector('form#new_user_video .submit > .throbber')
# AJAX END
Manually in your js code set 'ajax:send' (append throbber) and 'ajax:success' (remove throbber). This way you'll be able to know when request is finished.
And you should set enough time for ajax to complete:
Capybara.default_max_wait_time = 5

Rspec with capybara facing issue with page.should have_content

I am new to Rspec and here I am trying to test one of the integration test. When I (Using Capybara) clicks button then page content gets replaced with post response. Now i am checking for page content, it present on the page but still my test is failing.
Below is the spec
it "get force check takeover1" do
visit('/las_xml')
select('Showroom', :from => 'urlVal')
fill_in('fpHeaderForce', :with => 'PSD.L.Syn')
fill_in('currentDate', :with => '2013-09-11')
click_button('submit')
page.should have_content('Buy 2013 Labor Law Posters')
end
But Result is,
1) las box get force check takeover1
Failure/Error: page.should have_content('Test page')
expected #has_content?("Buy 2013 Labor Law Posters") to return true, got false
# ./integration/las_box_spec.rb:19:in `block (2 levels) in <top (required)>'
and resulted response html contains,
<div class="las-link" id="">
<div class="laborLink_actual labor_01">
<span class="laborLink"></span>
Buy 2013 Labor Law Posters
</div>
</div>
Possible causes
Provided you're indeed testing a html page as your result excerpt seems to show, there may be several possibilities, here :
the text you're trying to test is not the actual one. Double check there's no typo and you use the same locale if multiple language website
the element containing the text may be hidden. Capybara won't consider the content to exist if it is not visible
the previous click on button may simply not work or may lead to an other page
Ways to isolate problem
As often with capybara since fails are just symptoms of real problem, we can deal with all problems using debugging features :
page.save_screenshot( filename ) : saves a screenshot to given file name (for example, 'shot.png')
save_and_open_page : open an inspectable html page in your browser
binding.pry : from pry gem, always useful to inspect context
For an example of screenshot creation through poltergeist, see this.
Edit : dynamic page problems
As mentioned in comments, problem seems to be tied to javascript content editing.
You should still use debugging mentioned before to be sure to isolate your problem. Once done, you can use capybara's #synchronize method to wait for your content :
page.document.synchronize( 10 ) do
result = page.evaluate_script %($(':contains("Post")').length)
raise Capybara::ElementNotFound unless result > 0
end
The synchronize method will be retried for 10 seconds, as long that the containing block raises a Capybara::ElementNotFound exception (any other exception is not catched). So basically, here, we check (using jQuery) if the "Post" content is present in page, and retry until it is or until ten seconds have passed.
If element was not found, test will fail by raising an uncaught exception.
If element is found, you can now proceed with your regular test. This allow to add timing condition in specs.

How to avoid hard coding values in cucumber features?

When writing my scenerios, is it possible to not have to hard code text in the steps?
Like say I am insert a username in a textbox field, and a password in the password field.
If I need to do this in many places, it would be a pain to fix.
Example:
Given I am the registered member "myusername"
And I am on the login page
When I fill in "email" with "email#example.com"
And I fill in "password" with "123"
And I press "Login"
Then I should see "Account Activity"
I don't want my username, email, and password hard-coded.
Okay, you're still using the older version of the cucumber-rails gem which comes with the training wheels installed by default. Read this post by Aslak Hellesøy "The training wheels came off".
The gist of the post is that using web_steps.rb, although it having been the "standard" for years is now terribly wrong and that we should feel bad for doing that.
The purpose of Cucumber is to use it to make readable / understandable features for all people.
Writing a scenario like this is long and boring:
And I am on the login page
When I fill in "email" with "email#example.com"
And I fill in "password" with "123"
And I press "Login"
Then I should see "Account Activity"
What you want to actually be testing is that you should be able to login and after that see something to do with being logged in. Whatever that something is shouldn't be written in the scenario.
So ideally, your Scenario (in a more exciting fashion) would look like this:
When I login successfully
Then I should see that I am logged in
Then the task of doing the legwork goes to some new step definitions. Those two steps aren't defined automatically for you, like web_steps.rb does, but rather need to have them written in a file within feature/step_definitions. What you call the file is up to you, but it'll contain content similar to this:
When /I login successfully/ do
visit root_path
click_link "Login"
fill_in "Email", :with => "you#example.com"
fill_in "Password", :with => "password"
end
Then /^I should see I am logged in$/ do
page.should have_content("Account Activity")
end
No more excessive web_steps.rb file and cleaner step definitions. Exactly what Cucumber should be.
Create a step to encapsulate the logging in behavior as described here
If this works for you, I would then suggest tweaking the Given /I am logged in/ step to capybara calls to get a slight boost to performance. Also, in the future it is recommended that you avoid using web_steps for reasons described here.
Ryan's example is a change from imperative steps to declarative. This is generally a better idea. It means that the implementation has been moved into step definitions which makes the feature more readable and focuses on the behavior instead of the details.
But if you need to be specific with your steps (imperative), you could try something like
Given I am a registered member
And I am on the login page
When I fill in the login form
And I submit the login form
Then I should see I am logged in
You could also combine those steps to make it even simpler. But still, Ryan's idea is probably better in most cases.
Edit: Ryan has written a book. It's quite good. Hi Ryan!
You can create csv file in framework under data folder,add your private values to csv file, then call it in your feature file

Resources