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.
Related
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")?
i'm run into the problem with testing user sign in procces
here my test
require 'spec_helper'
include Warden::Test::Helpers
include Devise::TestHelpers
describe "UserSignin" do
it "should allow a registered user to sign in" do
user = FactoryGirl.create(:employer, :email => "email#email.com")
user.confirm!
visit "/users/sign_in"
fill_in "Email", :with => user.email
fill_in "Password", :with => "12345678"
click_button "Sign in"
current_path.should == '/employer'
expect(page).to have_content('My Account')
end
end
if it's improtant i'm using device for authentication
in factory i also have :employer factory
problem with authenticate
after clicking sign_in i'v got an error invalid email or password
UPDATE
there was problem with configs for test environment in spec helper
the solution is to set:
DatabaseCleaner.strategy = :truncation
I don't understand why the first of the following test passes while the second does not. Obviously, it's because I'm using a block in the first one, but what does it actually do compared to the second scenario?
require 'spec_helper'
feature "Edit user account" do
let(:user) { FactoryGirl.create(:user) }
before(:each) do
sign_in_as!(user)
visit '/settings'
end
scenario 'A user should be able to update their login info with current password' do
fill_in 'user_first_name', :with => 'Mario'
fill_in 'user_email', :with => 'mario#bross.com'
fill_in 'user_password', :with => 'goshrooms'
fill_in 'user_current_password', :with => 'ilovebananas'
click_button 'Update'
user.reload do |u|
u.first_name.should eq 'Mario'
u.email.should eq 'mario#bross.com'
u.password.should eq 'goshrooms'
end
current_path.should eq '/settings'
page.should have_content('You updated your account successfully.')
end
scenario "A user should be able to update their login info with current password" do
fill_in "user_password", :with => "magical"
fill_in "user_current_password", :with => 'ilovebananas'
click_button "Update"
current_path.should eq "/settings"
user.reload.password.should eq "magical"
end
end
When running the tests I get:
1) Edit user account A user should be able to update their login info with current password
Failure/Error: user.reload.password.should eq "magical"
expected: "magical"
got: "ilovebananas"
(compared using ==)
As mentioned in the comments above, password is not a field in the DB. So instead of testing on password, I tested on the encrypted_password field.
feature "* Edit user account:" do
let(:user) { FactoryGirl.create(:user) }
before(:each) do
visit "/login"
fill_in "user_email", :with => user.email
fill_in "user_password", :with => "ilovebananas"
click_button "Sign in"
visit '/settings'
#old_encrypted_password = user.encrypted_password
end
scenario 'A user should be able to update their info with current password' do
....
user.reload.encrypted_password.should_not eq #old_encrypted_password
end
end
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?
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.