Testing signup form with rspec, capybara, and stripe - ruby-on-rails

I'm super new to testing, so I'm not really sure what I should be debugging here.
That said, I have two different user types: Authors and Readers, subclassed on Users.
They can both sign up fine in my app, and the tests for Readers works without any problems.
The signup form for Authors includes a stripe payment form - and makes a remote call to Stripe's API before submitting the form.
Here is what the test looks like:
require 'spec_helper'
feature 'Author sign up' do
scenario 'author can see signup form' do
visit root_path
expect(page).to have_css 'form#new_author'
end
scenario 'user signs up and is logged in' do
visit root_path
fill_in 'author[email]', :with => 'author#example.com'
fill_in 'author[password]', :with => '123456'
fill_in 'author[password_confirmation]', :with => '123456'
fill_in 'author[name]', :with => 'joe shmoe'
fill_in 'author[zipcode]', :with => '02021'
fill_in 'card_number', :with => '4242424242424242'
fill_in 'card_code', :with => '123'
select "1 - January", :from => 'card_month'
select "2014", :from => 'card_year'
find('.author_signup_button').click
expect(page).to have_css '.author_menu'
end
end
The only difference between this test and the Reader test are the credit card forms.
The controller which handles this account creation looks like this:
def create
#author = Author.new(params[:author])
if #author.save_with_payment
sign_in #author, :event => :authentication
redirect_to root_path, :notice => "Thanks for signing up!"
else
render :nothing => true
end
end
If I don't have the else in here, the test fails sooner, saying its missing templates. Which means its not passing the "save_with_payment" method, which supports the idea that the form never hits stripe.
The error simply says:
**Failure/Error: expect(page).to have_css '.author_menu'
expected css ".author_menu' to return something**
This worked before I integrated with stripe - so I'm convinced it has to do with the ajax call.
Is there something I should be doing to support ajax?

The answer, was to use :js => true in the test:
scenario 'user signs up and is logged in', :js => true do
This forces the test to run with selenium, and uses the browser.

Related

Why do I get the error in my acceptance test?

Tell me please,why does it happen?
I can't understand, if I write:
feature "Article Creation" do
#here i write (:all)
before(:all) do
sign_up_helper
end
I get the error:
Article Creation allows user to visit to creating article page
Failure/Error: fill_in :article_title, :with => 'test_title'
Capybara::ElementNotFound:
Unable to find field :article_title
or
1) Article Creation allows user to visit to article page
Failure/Error: expect(page).to have_content I18n.t('articles.articles_new')
expected to find text "New Article:" in "Toggle navigation Blog Rails New Contacts Sign in --- !ruby/hash:ActionController::Parameters controller: devise/sessions action: new {\"controller\"=>\"devise/sessions\", \"action\"=>\"new\"} nil You need to sign in or sign up before continuing. Sign in: Email Password Remember me Sign up Forgot your password?"
but, if I write:
feature "Article Creation" do
#here i write(:each)
before(:each) do
sign_up_helper
end
It's Ok. All tests works. My question -WHY?
This is my test:
*#before all test visitor signs up
#here I've changed :all and :each*
feature "Article Creation" do
before(:all) do
sign_up_helper
end
scenario "allows user to visit to article page" do
visit new_article_path
expect(page).to have_content I18n.t('articles.articles_new')
end
scenario "allows user to visit to created article page" do
visit new_article_path
fill_in :article_title, :with => 'test_title'
fill_in :article_text, :with => 'example_text'
click_button 'Save Article'
expect(page).to have_content 'example_text'
end
This is sign_up_helper method:
#spec/support/session_helper.rb
def sign_up_helper
visit new_user_registration_path
fill_in :user_email, :with => 'user#example.com'
fill_in :user_username, :with => 'mike'
fill_in :user_password, :with => 'secure123!##'
fill_in :user_password_confirmation, :with => 'secure123!##'
click_button 'Sign up'
end
This is html form:
<p>
<label for="article_title">Title</label><br/>
<input type="text" name="article[title]" id="article_title" />
</p>
<p>
<label for="article_text">Text</label><br/>
<textarea name="article[text]" id="article_text">
</textarea>
</p>
Environment for each test is set anew, I think. New session, cookies, etc. In many cases, even brand new users are generated. So one "global" login is not possible.
Even if it were possible, it would still be a problem, as it introduces spec order dependency which is bad. Imagine that one of your specs logs user out. Then each subsequent spec would fail, because user is not logged in anymore.
To prevent this, make sure that each spec sets its own environment as it needs it (user logins, method stubs, etc.), without relying on side-effects from previously executed specs (which may or may not persist).

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")?

Cucumber test on 'Devise sign in' fail with an erro RSpec::Expectations::ExpectationNotMetError (Rails 3.2/Rspec/Cucumber)

I run across problems when I execute the cucumber tests on devise.
The tests that are failing are just the default ones provided when you install devise (I just modified some words for "sign in" that became "login" on my website but I don't think it's the reason of the problem).
As I'm a beginner, I don't understand what is even wrong or what cucumber is telling me. Why is it mentioning rspec here? should I add the rspec-expectations gem ?
The error I get on my console when I run cucumber:
Scenario: User signs in successfully # features/users/sign_in.feature:12
Given I exist as a user # features/step_definitions/user_steps.rb:58
And I am not logged in # features/step_definitions/user_steps.rb:49
When I sign in with valid credentials # features/step_definitions/user_steps.rb:72
Then I see a successful sign in message # features/step_definitions/user_steps.rb:152
expected to find text "Signed in successfully." in "Mywebsite Follow us How it works More Login × Invalid email or password. Login * Email Password Remember me Not a member yet? Sign Up Now!Forgot your password?Didn't receive confirmation instructions? Rails Tutorial About Contact Help" (RSpec::Expectations::ExpectationNotMetError)
./features/step_definitions/user_steps.rb:153:in `/^I see a successful sign in message$/'
features/users/sign_in.feature:16:in `Then I see a successful sign in message'
When I return to the site # features/step_definitions/user_steps.rb:110
Then I should be signed in # features/step_definitions/user_steps.rb:136
The files the error is refering to:
/features/step_definitions/user_steps.rb
### UTILITY METHODS ###
def create_visitor
#visitor ||= { :name => "xxx", :email => "xxx#gmail.com",
:password => "xxx", :password_confirmation => "xxx" }
end
def find_user
#user ||= User.first conditions: {:email => #visitor[:email]}
end
def create_unconfirmed_user
create_visitor
delete_user
sign_up
visit '/users/sign_out'
end
def create_user
create_visitor
delete_user
#user = FactoryGirl.create(:user, email: #visitor[:email])
end
def delete_user
#user ||= User.first conditions: {:email => #visitor[:email]}
#user.destroy unless #user.nil?
end
def sign_up
delete_user
visit '/users/sign_up'
fill_in "Name", :with => #visitor[:name]
fill_in "Email", :with => #visitor[:email]
fill_in "user_password", :with => #visitor[:password]
fill_in "user_password_confirmation", :with => #visitor[:password_confirmation]
click_button "Sign up"
find_user
end
def sign_in
visit '/users/sign_in'
fill_in "Email", :with => #visitor[:email]
fill_in "Password", :with => #visitor[:password]
click_button "Login"
end
(....) and more below:
Then /^I see a successful sign in message$/ do
page.should have_content "Signed in successfully."
end
and /features/users/sign_in.feature
Scenario: User signs in successfully
Given I exist as a user
And I am not logged in
When I sign in with valid credentials
Then I see a successful sign in message
When I return to the site
Then I should be signed in
When i manually go on my website, it does display "Signed in successfully." when I sign in so what's the problem? I really don't understand.
Add the following step to debug:
Then /^show me the page$/ do
save_and_open_page
end
And add show me the page to the feature:
Given I exist as a user
And I am not logged in
When I sign in with valid credentials
Then show me the page
And I see a successful sign in message
It will help you to debug the error.
Put this into spec_helper, or support/devise.rb
config.include Devise::TestHelpers, :type => [:feature, :controller]

Why rails integration test does not check for proper user right?

In our integration test for rails 3.2.12 app, there is a test case to open the create new user page which only admin has the right to do. Here is our rspec case (with capybara) which passes:
it "should have login field in create new user page" do
ul = FactoryGirl.build(:user_level, :position => 'admin')
#user = FactoryGirl.create(:user, :login => 'test12', :password => 'password', :password_confirmation => 'password', :user_levels => [ul])
visit '/'
fill_in "login", :with => #user.login
fill_in "password", :with => 'password'
click_button 'Login'
visit new_user_path
page.body.should have_content("New User")
end
The user position "admin" is defined in user_levels which belongs to a user. What the rspec case above does is to log in and open the create new user page.
In user controller, there is a before_filter to check if the user is admin:
before_filter :require_admin
The odd thing is that if we assign non-admin position to the user in rspec case above, the case still passes. It seems that the before_filter require_admin fails to stop a non-admin user open the create new user page in integration test.
What could be wrong with the rpsec code above? Thanks for help.

Maintaining Session with Capybara and Rails 3

I have two capybara tests, the first of which signs in a user, and the second which is intended to test functions only available to a logged in user.
However, I am not able to get the second test working as the session is not being maintained across tests (as, apparently, it should be).
require 'integration_test_helper'
class SignupTest < ActionController::IntegrationTest
test 'sign up' do
visit '/'
click_link 'Sign Up!'
fill_in 'Email', :with => 'bob#wagonlabs.com'
click_button 'Sign up'
assert page.has_content?("Password can't be blank")
fill_in 'Email', :with => 'bob#wagonlabs.com'
fill_in 'Password', :with => 'password'
fill_in 'Password confirmation', :with => 'password'
click_button 'Sign up'
assert page.has_content?("You have signed up successfully.")
end
test 'create a product' do
visit '/admin'
save_and_open_page
end
end
The page generated by the save_and_open_page call is the global login screen, not the admin homepage as I would expect (the signup logs you in). What am I doing wrong here?
The reason this is happening is that tests are transactional, so you lose your state between tests. To get around this you need to replicate the login functionality in a function, and then call it again:
def login
visit '/'
fill_in 'Email', :with => 'bob#wagonlabs.com'
fill_in 'Password', :with => 'password'
fill_in 'Password confirmation', :with => 'password'
click_button 'Sign up'
end
test 'sign up' do
...
login
assert page.has_content?("You have signed up successfully.")
end
test 'create a product' do
login
visit '/admin'
save_and_open_page
end
Each test is run in a clean environment. If you wish to do common setup and teardown tasks, define setup and teardown methods as described in the Rails guides.

Resources