Failure/Error: expect { click_button submit } - ruby-on-rails

I testing with rspec, Im still learning, I guess I'm on the right way... but when I test my rspec file I got this error:
Failures:
1) UsersController signup with valid information should create a user
Failure/Error: expect { click_button submit }.to change(User, :count).by(1)
count should have been changed by 1, but was changed by 0
# ./spec/controllers/user_controller_spec.rb:31
Finished in 1.16 seconds
2 examples, 1 failures
I know what this mean, but I don't know how to fix it, can anyone help me with this trouble please...Also I put my rspec file
require 'spec_helper'
describe UsersController do
describe "signup" do
before { visit new_user_registration_path }
let(:submit) { "Sign up" }
describe "with invalid information" do
it "should not create a user" do
expect { click_button submit }.not_to change(User, :count)
end
end
describe "with valid information" do
before do
fill_in "Email", :with=> "user#example.com"
fill_in "Password", :with=> "foobar"
#fill_in "password_confirmation", :with=> "foobar"
end
(here is that the error appears...below line)
it "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
end
end
end
thanks for your attention

So, you have a failing spec. The spec itself looks ok. So I would check on
is the implementation in place? You can try out the scenario in your browser. Does it work there? If not, you have a failing test (which is good) and need to add the implementation.
if the implementation works, check the spec again carefully. Is the provided information
fill_in "Email", :with=> "user#example.com"
fill_in "Password", :with=> "foobar"
sufficient to create a user?
if you still haven't found the cause, you could use capybaras save_and_open_page (install launchy gem for that) and peek at the page during your test.
ADDITION:
ok, as I said, this should be an integration test - move it from the spec/controllers to the spec/requests folder (and do change the first line, as you're not describing the UsersController! but that should not lead to the problem).

Related

Undefined method "Get" and "Let" with Rspec 3 - rails 4

I've decided to start a new project using the new Rspec 3 (+ capybara/factory_girl) and am having trouble learning the new syntax. Right now I have
user_pages_spec.rb (Feature)
scenario "Signing Up" do
let(:submit) { "Sign up" }
scenario "With valid information" do
background do
fill_in "Username", with: "example"
fill_in "Email", with: "example#example.com"
fill_in "Password", with: "foobar123"
fill_in "Password confirmation", with: "foobar123"
end
scenario "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
end
end
Fails with undefined method 'let'. And:
static_pages_spec.rb (controller)
describe StaticPagesController do
describe "GET 'home'" do
it "returns http success" do
get :home
expect(response).to be_success
end
end
end
with "undefined method 'get'. (This is just the default controller spec)
When upgrading existing project from RSpec 2.x to 3.0 had same problem.
It was fixed for me with an explicit setting of the type.
Could you try this:
describe StaticPagesController, type: :controller do
EDIT:
I found now that the more structural cause and solution is that
in RSpec 3, I needed to add:
config.infer_spec_type_from_file_location!
in the config block in spec_helper.rb
You are getting undefined method let because capybara defines scenario an alias of it and feature as alias of describe. However, let is available in an example group context (a describe or context block) but not an individual example (and it block). So your example is equivalent to:
it "Signing Up" do
let(:submit) { "Sign up" }
it "With valid information" do
background do
fill_in "Username", with: "example"
fill_in "Email", with: "example#example.com"
fill_in "Password", with: "foobar123"
fill_in "Password confirmation", with: "foobar123"
end
it "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
end
end
...but should be:
feature "Signing Up" do
let(:submit) { "Sign up" }
context "With valid information" do
background do
fill_in "Username", with: "example"
fill_in "Email", with: "example#example.com"
fill_in "Password", with: "foobar123"
fill_in "Password confirmation", with: "foobar123"
end
scenario "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
end
end
Or, if you want to stick with pure RSpec constructs (rather than the capybara aliases):
describe "Signing Up" do
let(:submit) { "Sign up" }
context "With valid information" do
before do
fill_in "Username", with: "example"
fill_in "Email", with: "example#example.com"
fill_in "Password", with: "foobar123"
fill_in "Password confirmation", with: "foobar123"
end
it "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
end
end

Keeping user in the database between tests using Capybara?

My issue is that I have to create a new user and login for each individual capybara test.
An example is below:
require 'spec_helper'
describe "users" do
describe "user registration" do
it "should create a new user and log in" do
# Register a new user to be used during the testing process
visit signup_path
fill_in 'Email', with: 'testuser'
fill_in 'Password', with: 'testpass'
fill_in 'Password confirmation', with: 'testpass'
click_button 'Create User'
current_path.should == root_path
page.should have_content 'Thank you for signing up!'
end
end
describe "user login" do
it "should log in" do
# log in
visit login_path
fill_in 'Email', with: 'testuser'
fill_in 'Password', with: 'testpass'
click_button 'Log In'
current_path.should == root_path
page.should have_content 'Logged in!'
end
end
end
The login test fails because the user no longer exists in the database for that test.
This could be fixed simply by putting both in one test, but I believe that is bad practice.
Also I have another file which currently is registering and logging in between each test using a before_do, which also seems to be quite bad... you can see that code here.
For the record this is my first rails app so perhaps I am trying to do this the wrong way. I would like to dry it up as much as possible..
Is capybara really this bad to use on pages that require user login?
I have done it this way.
require "spec_helper"
describe "Users" do
subject { page }
describe "User Registration" do
before { visit signup_path }
let(:submit) { "Sign up" }
describe "with invalid information" do
it "should not create a user" do
expect { click_button submit }.not_to change(User, :count)
end
end
describe "with valid information" do
before do
fill_in "Email", with: "user#example.com"
fill_in "Password", with: "foobar12"
fill_in "Password confirmation", with: "foobar12"
end
it "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
describe "after registration" do
before { click_button submit }
it { should have_content 'Thank you for signing up!' }
end
describe "after registration signout and login" do
let(:user) { User.find_by_email('user#example.com') }
before do
click_button submit
visit signout_path
sign_in user # sign_in is a method which u can define in your spec/support/utilities.rb . Define once and use at multiple places.
end
it { should have_content 'Logged In!' }
it { should have_link('Logout') }
end
end
end
end
# spec/support/utilities.rb
def sign_in(user)
visit sign_path
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Log in"
end
your every describe and it block will run after the before block in parent that's why we need to click_button in every block in above test cases.

How to organise integration specs

With rspec, it's quite clear how you should organise your unit specs. The directory structure inside spec is very similar to that found in the app directory, so model specs go in the model directory, controller specs go in the controller directory and so on.
But it's not so clear with integration testing. I have just one file pertaining to integration testing: spec/features/integration.rb
Is the idea to create one elaborate spec that tests every faculty of your application? Something like this:
require 'spec_helper'
describe "Everything", js: true do
before do
#user_0 = FactoryGirl.build(:user_0)
#user_1 = FactoryGirl.build(:user_1)
#user_2 = FactoryGirl.build(:user_2)
#user_3 = FactoryGirl.build(:user_3)
end
it "can create a user" do
visit root_path
click_link 'Sign In'
ap #user_0
fill_in('Email', with: #user_0.email)
fill_in('Password', with: #user_0.password)
click_button 'Sign in'
visit('/user_friendships')
end
it "can create a user" do
end
it "can create a user" do
end
it "can create a user" do
end
it "GET /root_path" do
visit root_path
page.should have_content("All of our statuses")
click_link "Post a New Status"
page.should have_content("New status")
fill_in "status_content", with: "Oh my god I am going insaaaaaaaaane!!!"
click_button "Create Status"
page.should have_content("Status was successfully created.")
click_link "Statuses"
page.should have_content("All of our statuses")
page.should have_content("Jimmy balooney")
page.should have_content("Oh my god I am going insaaaaaaaaane!!! ")
end
end
But a lot longer?
Should I use more than one file? How should I use the describe blocks? I'm only using one at the moment and that doesn't feel right.
The short answer is: No, it's not meant to go into one file.
Bigger projects split their acceptance test-suite into files based on feature sets. If you have a lot of tests, they are often split up into different directories. The way that you organize those tests is up to you. I have seen a lot of different approaches here. I tend to group spec with similar requirements on database setup, aka test-data.
If you want to have great guide for your rspec tests, go and have a look at this site: http://betterspecs.org/
It's usually desirable to split integration tests per page or flow in your application.
For example, you could try:
# spec/users/sign_in_spec.rb
RSpec.describe 'Users Sign In', js: true do
let!(:user) { FactoryGirl.build(:user_0) }
it "can sign in" do
visit root_path
click_link 'Sign In'
fill_in('Email', with: user.email)
fill_in('Password', with: user.password)
click_button 'Sign in'
page.should have_content('Signed In')
end
end
# spec/statuses/manage_status.rb
RSpec.describe 'Statuses', js: true do
it "should be able to post a status" do
visit root_path
page.should have_content("All of our statuses")
click_link "Post a New Status"
fill_in "status_content", with: "Everything is Alright"
click_button "Create Status"
page.should have_content("Status was successfully created.")
click_link "Statuses"
page.should have_content("All of our statuses")
page.should have_content("Everything is Alright ")
end
end
If you are looking for a way to organize your specs, you could use Capybara Test Helpers to encapsulate the code and make the tests more readable. For example:
# spec/users/sign_in_spec.rb
RSpec.describe 'Users Sign In', js: true, test_helpers: [:login] do
let!(:user) { FactoryGirl.build(:user_0) }
it "can sign in" do
visit root_path
login.enter_credentials(email: user.email, password: user.password)
current_page.should.have_content('Signed In')
end
end
# spec/statuses/manage_status.rb
RSpec.describe 'Statuses', js: true, test_helpers: [:statuses] do
it "should be able to post a status" do
visit root_path
current_page.should.have_content('All of our statuses')
statuses.post('Everything is Alright')
statuses.should_now.have_status('Everything is Alright')
end
end

Simple rspec test failing

I would have thought this test would have passed. Any ideas why it isnt?
it 'should create an account' do
visit new_user_registration_path
fill_in 'user_email', with: 'newtest#test.com'
fill_in 'user_password', with: 'testing123'
fill_in 'user_password_confirmation', with: 'testing123'
expect{
click_button 'Sign Up'
}.to change{User.count}.by(1)
end
I just get
result should have been changed by 1, but was changed by 0
It is a counter cache problem, see this:
Rails counter_cache not updating correctly
Silly mistake. I had a validation on user for name!

Correct way to write rspec/capybara test?

I'm new to Ruby and Rails and I'm trying to implement tests the correct way. I'm currently working on having users sign up. I would like the first user to sign up to be an admin and then every user after that to be a regular user.
I'm currently thinking I need to write my test as a feature but I'm wondering if this should actually be a model test.
My current code is right here
require 'spec_helper'
describe "User pages" do
subject { page }
describe "Sign up page" do
before { visit signup_path }
it { should have_button('Create!') }
end
describe "Creating an account" do
before { visit signup_path }
let(:submit) { "Create!" }
describe "with invalid information" do
it "should not create the user account" do
expect { click_button "Create!"}.not_to change(User, :count)
end
describe "it should display errors" do
before { click_button submit }
it { should have_content('Failed signup') }
end
end
describe "with valid information" do
before do
fill_in "Name", with: "Example User"
fill_in "Email", with: "user#example.com"
fill_in "Password", with: "password"
fill_in "Confirm Password", with: "password"
end
it "should create the user" do
expect { click_button submit }.to change(User, :count).by(1)
end
# User sign in not implemented at this point
describe "the first user" do
User.all.count.should == 0
click_button submit
User.all.count.should == 1
#firstUser = User.first
#firstUser.is_admin?.should == true
describe "the second user" do
before do
visit signup_path
fill_in "Name", with: "Example User2"
fill_in "Email", with: "user2#example.com"
fill_in "Password", with: "password"
fill_in "Confirm Password", with: "password"
end
click_button submit
#secondUser = User.all.last
#secondUser.is_admin?.should == false
end
end
end
end
end
I'm mostly concerned with the "with valid information" part and would like to clean that up so it fits in with rspec/capybara correctly.
you can try this great tutorial by michael hartl , he use Rspec in this tutorial you can learn from it :)
i am a beginner too and i started with it :D

Resources