Rails by Example Tutorial Request Examples and Capybara - ruby-on-rails

In the Rails on Rails Tutorial by Michael Hartl, the Request Examples make assertions on the response. I installed the cabybara and steak gem to create acceptance tests. After installing capybara, the requests examples are configured to use capybara. capybara examples have a different syntax and don't recognize the response.
How do I reset the Request Examples to run as RSpec example?
Test Error:
4) Users signup failure should not make a new user
Failure/Error: click_button
wrong number of arguments (0 for 1)
# ./spec/requests/users_spec.rb:13
# ./spec/requests/users_spec.rb:7
Request Example
describe "failure" do
it "should not make a new user" do
lambda do
visit signup_path
fill_in "Name", :with => ""
fill_in "Email", :with => ""
fill_in "Password", :with => ""
fill_in "Confirmation", :with => ""
click_button
response.should render_template('users/new')
end.should_not change(User, :count)
end
end

This might have something to do with rspec-rails request_example_group.rb.
request_example_group.rb
If the capybara lines are commented out, then the Request Examples are not defaulted to capybara.
capybara do
include Capybara
end
In the Acceptance examples, include capybara.
require File.expand_path(File.dirname(__FILE__) + '/acceptance_helper')
feature "This Is My First Feature", %q{
In order to ...
As a ...
I want to ...
} do
include Capybara
scenario "Scenario name" do
visit signup_path
fill_in "Name", :with => ""
fill_in "Email", :with => ""
fill_in "Password", :with => ""
fill_in "Confirmation", :with => ""
click_button "Sign up"
page.has_content?('welcome to the sample app')
end
end
I ended up forking rspec-rails and commenting out the capybara lines.
In the Gemfile, the gem installed from the fork.
Why bother? We want both white box and black box testing.

As you correctly point out in your answer, rspec-rails will include Capybara if it is installed. I think they're assuming that it never hurts to include Capybara, just in case you need it. Is that a problem for you? In other words, what specifically is the Capybara DSL conflicting with?
(This might be also be worth bringing up on the RSpec mailing list.)
As for the error you posted, it seems that you are simply missing an argument to the click_button method.

Related

Testing Stripe works with js: true, but it makes other components work incorrectly

Testing the stripe framework requires Javascript to be turned on, but when I send js: true in it method, the other components like visit, fill_in stop working in the way they were working before.
Here is my code:
def sign_up(subdomain)
visit root_url(subdomain: false)
visit new_account_path
fill_in 'Name', with: 'Ryan'
fill_in 'Email', with: 'test#test.com'
fill_in 'Password', with: 'password'
fill_in 'Password confirmation', with: 'password'
fill_in 'Subdomain', with: subdomain
click_button 'Create Account'
end
In the sign_up method, visit new_account_path was working before js: true, but now it doesn't.
I'm turning js: true in the following method:
it 'shows the user can upgrade his account with valid card number, expiration and CVC', js: true do
fill_in "card_number", :with => "4242424242424242"
fill_in "card_expiry_month", :with => "05"
fill_in "card_expiry_year", :with => "2015"
fill_in "card_cvc", :with => "123"
click_button 'Upgrade Your Account'
expect(page).to have_content "Update Your Payment Information"
end
I've been searching the solution for quite a long time, but so far unable to resolve this.
As per your comment, you're getting an error from stripe's API: Stripe::InvalidRequestError.
According to their API (https://stripe.com/docs/api#errors):
Invalid request errors arise when your request has invalid
parameters.
I would wager that there is something actually wrong with your request to Stripe rather than the Capybara (?) spec you wrote.
I've written a blog post about writing acceptance tests with RSpec and Capybara for Stripe. You can view it here

Rails4.1, devise 3.2.4, rspec feature, How I get confirmation_token?

I am trying to write a feature-spec with the following steps:
visit "/users/sign_up"
fill_in 'user_email', :with => 'dan#dan.net'
fill_in 'user_password', :with => 'abc123'
fill_in 'user_password_confirmation', :with => 'abc123'
click_button "Sign up"
dan_confirmation_token = get_confirmation_token
visit "/users/confirmation?confirmation_token=#{dan_confirmation_token}"
In previous versions of devise,
I could get dan_confirmation_token directly from:
User.find_by_email('dan#dan.net').confirmation_token
But devise is more secure now.
What is the API call I use to get dan_confirmation_token?
I got this working :
visit "/users/sign_up"
fill_in 'user_email', :with => 'dan#dan.net'
fill_in 'user_password', :with => 'abc123'
fill_in 'user_password_confirmation', :with => 'abc123'
click_button "Sign up"
visit "/"
usr = User.find_by_email "dan#dan.net"
raw, enc = Devise.token_generator.generate(usr.class, :confirmation_token)
usr.confirmation_token = enc
usr.confirmation_sent_at = Time.now.utc
usr.save(validate: false)
visit "/users/confirmation?confirmation_token=#{raw}"
I should note that usr.save(validate: false) will not work like I want unless I configure rspec to avoid using transactions:
vi spec/spec_helper.rb
set:
config.use_transactional_fixtures = false
Since I'm using sqlite in my test-env, this is not a big deal.
At the end of each test-run I do this:
rm -f db/test.sqlite3
If I want to run my tests using Postgres, I will need to "clean my database" after each test-run.
To do that, I would depend on gem:
https://github.com/bmabey/database_cleaner
You might look at the Devise test suite for the Confirmable module to see how they do it. It appears you can call raw_confirmation_token; I don't know if that is appropriate for your situation.

Rspec/Capybara test cases are not working for multiple 'it' blocks

I am writing some integration test cases for an existing application. My test works fine if there is only one 'it' block. However, If I add more than one 'it' block it throws an error. Below is my code that works:
require 'spec_helper'
describe 'Group' do
before do
visit 'http://groups.caremonkey.com/users/sign_in'
fill_in "Email", :with => "email#example.com"
fill_in "Password", :with => "password"
click_button "Login"
page.should have_link('Account')
end
it 'Should check all the links and functionality of groups' do
#add new subgroup with valid data should save a new group
find("#group-squares").click_link("Add")
fill_in "Group Name", :with => "Melbourne futsal"
click_on("Save")
page.should_not have_content("can't be blank")
page.execute_script("parent.$.fancybox.close();")
page.should have_link('Account')
#test edit group: should be able to update group info provided valid data are given
first(".actual img").click
page.should have_content("Group")
page.should have_link("Cancel")
fill_in "Group name", :with => "Futsal club"
page.execute_script("$('#sub-group-color-options').find('.color23').click()")
click_button "Save"
click_on("Cancel")
page.should have_link('Account')
end
end
It works perfectly fine when I put all the 'it' block together in a single 'it' block. But when I split them in different 'it' block, it stops working. For example if I split this ("test edit group: should be able to update group info provided valid data are given") test case into separate 'it' block as follows
require 'spec_helper'
describe 'Group' do
before do
visit 'http://groups.caremonkey.com/users/sign_in'
fill_in "Email", :with => "email#example.com"
fill_in "Password", :with => "password"
click_button "Login"
page.should have_link('Account')
end
it 'add new subgroup with valid data should save a new group' do
find("#group-squares").click_link("Add")
fill_in "Group Name", :with => "Melbourne futsal"
click_on("Save")
page.should_not have_content("can't be blank")
page.execute_script("parent.$.fancybox.close();")
page.should have_link('Account')
end
it 'should be able to update group info provided valid data are given' do
first(".actual img").click
page.should have_content("Group")
page.should have_link("Cancel")
fill_in "Group name", :with => "Futsal club"
page.execute_script("$('#sub-group-color-options').find('.color23').click()")
click_button "Save"
click_on("Cancel")
page.should have_link('Account')
end
end
then rspec fails, it passes the first test, however second test gets failed throwing following error.
Failure/Error: visit 'http://groups.caremonkey.com/users/sign_in'
ActionController::RoutingError:
No route matches [GET] "/users/sign_in"
One more thing, I have to test all the features in remote(url: http://groups.caremonkey.com/). Because, I am writing integration tests for an existing application. In addition, I need to login to the system before I test rest of the features of my application. Thanks in advance for your help.
Have you followed the Capybara documentation for calling remote servers? It says you should have the following:
Capybara.current_driver = :selenium # Or anything but rack_test, probably
Capybara.run_server = false # Don't run your app in-process
Capybara.app_host = 'http://groups.caremonkey.com/'
My guess is that when you have visited the site once, future visit calls are trying to use relative routes, which then is routed to the default server. I can't think why you would get a ActionController::RoutingError if you don't have some kind of Rack server running. Are you running these tests in some other Rails application?
I guess something like this:
require 'spec_helper'
describe 'Group' do
before do
visit 'http://groups.caremonkey.com/users/sign_in'
fill_in "Email", :with => "email#example.com"
fill_in "Password", :with => "password"
click_button "Login"
page.should have_link('Account')
find("#group-squares").click_link("Add") #apperently both specs are "scoped" to this page
end
it 'Should check all the links and functionality of groups' do
fill_in "Group Name", :with => "Melbourne futsal"
click_on("Save")
page.should_not have_content("can't be blank")
page.execute_script("parent.$.fancybox.close();")
page.should have_link('Account')
end
it "test edit group: should be able to update group info provided valid data are given"
first(".actual img").click
page.should have_content("Group")
page.should have_link("Cancel")
fill_in "Group name", :with => "Futsal club"
page.execute_script("$('#sub-group-color-options').find('.color23').click()")
click_button "Save"
click_on("Cancel")
page.should have_link('Account')
end
end
My gut feeling tells me both test need the follow this: find("#group-squares").click_link("Add") so I added it to the before block This test however is cryptic, what is first(".actual img")?

error using rspec for devise

I am using rspec for testing devise authentication. Following is my code
require 'spec_helper'
describe User do
describe "user registration" do
it "allows new users to register with an email address and password" do
get "/users/sign_up"
fill_in "Email", :with => "abc#example.com"
fill_in "Password", :with => "abc123"
fill_in "Password confirmation", :with => "abc123"
click_button "Sign up"
response.should have_content("Welcome! You have signed up successfully.")
end
end
end
I am getting the following error.
"NoMethodError:undefined method `get' for #"
You are using controller methods and integration test methods (Capybara) in a Model spec. It will not work.
A model spec (UNIT test) will contain things like:
Test your validators/relationships
Test scopes
Methods of your model
Check out this series of Blog articles on testing with RSpec, it should help:
http://everydayrails.com/2012/03/12/testing-series-intro.html
This seems to be an model spec (describe User) which does not allow to run requests, but you probably want to write a controller spec (describe UsersController) or even an integration test.
If you are using the default rspec layout, just move your code to the appropriate directory (spec/controllers or spec/integration). I would do an integration test:
# In spec/integration/user_registration_spec.rb
require 'spec_helper'
describe "User registration" do
it "allows new users to register with an email address and password" do
get "/users/sign_up"
fill_in "Email", :with => "abc#example.com"
fill_in "Password", :with => "abc123"
fill_in "Password confirmation", :with => "abc123"
click_button "Sign up"
response.body.should have_content("Welcome! You have signed up successfully.")
end
end
Is this file in the spec/models directory? I'm guessing that's the case since you're describeing a User. The way you wrote your test is a mix between a controller-style test and an integration (acceptance) test. This is probably what you want:
require 'spec_helper'
describe User do
describe "user registration" do
it "allows new users to register with an email address and password" do
visit "/users/sign_up"
fill_in "Email", :with => "abc#example.com"
fill_in "Password", :with => "abc123"
fill_in "Password confirmation", :with => "abc123"
click_button "Sign up"
page.should have_content("Welcome! You have signed up successfully.")
end
end
end
Put this file in the spec/integration or spec/requests directory.
I would probably try something like this
require 'spec_helper'
describe User do
describe "user registration" do
it "allows new users to register with an email address and password" do
visit new_user_registration_path
current_path.should be(new_user_registration_path)
fill_in "user[email]", :with => "abc#example.com"
fill_in "user[password]", :with => "abc123"
fill_in "user[password_confirmation]", :with => "abc123"
click_button "Sign up"
expect { click_button submit }.to change(User, :count).by(1)
response.should be_redirect
response.should have_content("Welcome! You have signed up successfully.")
end
end
end
But I can highly recommend to using FactoryGirl for generating new values. Also check, which Devise modules do you use. For example if you are using a Confirmable modul, is obvious that this approach is wrong. Some useful article.

RSpec doesn't remove DB record so it fails the second time it runs

This is from Michael Hartl's book, section 8.4. RSpec is testing a successful signup but is fails because the email address isn't unique. So if I go into the code and update the email address in the spec, it works the first time I run it but not the second time. I have confirmed this because I can make the test pass by changing the email address or otherwise running rake db:test:clone.
Any thoughts on how to overcome this would be appreciated.
Code:
require 'spec_helper'
describe "Users" do
describe "signup" do
describe "failure" do
it "should not make a new user" do
lambda do
visit signup_path
fill_in :user_name, :with => "" #you can use CSS id instead of label, which is probably better
fill_in "Email", :with => ""
fill_in "Password", :with => ""
fill_in "Password confirmation", :with => ""
click_button
response.should render_template('users/new')
response.should have_selector("div#error_explanation")
end.should_not change(User, :count)
end
end
describe "success" do
it "should make a new user" do
lambda do
visit signup_path
fill_in "Name", :with => "Example User"
fill_in "Email", :with => "alex#example.com"
fill_in "Password", :with => "foobar"
fill_in "Password confirmation", :with => "foobar"
click_button
response.should have_selector("div.flash.success", :content => "Welcome")
response.should render_template('users/show')
end.should change(User, :count).by(1)
end
end
end
end
What does your spec/spec_helper.rb file look like? Do you have transactions turned on?
RSpec.configure do |config|
config.use_transactional_fixtures = true
end
This runs each of your specs within a database transaction, returning it back to its original state after each test run.
Once your spec helper looks something like that, run:
rake db:test:prepare
And try again. If that doesn't work, can you provide any more information? Which version of RSpec? Which version of Rails?

Resources