So I am trying to create a simple integration test in Rails. I want to test my login form. I just can't really figure out how to pass my params correctly. My .yml file is called agents.yml. My fixture file is:
one:
first_name: firstNameTest
last_name: lastNameTest
email: test#test.com
encrypted_password: <%= Devise::Encryptor.digest(Agent, '123456') %>
that should be ok.
Two tests I tried which both give me an error. The first one, following the Ruby.docs:
class FlowsTest < ActionDispatch::IntegrationTest
test "Login and navigate" do
get "/agents/sign_in"
post "/agents/sign_in", email: agents(:one).email, password:
agents(:one).password
follow_redirect!
end
end
the second version:
class FlowsTest < ActionDispatch::IntegrationTest
test "Login and navigate" do
get "/agents/sign_in"
post "/agents/sign_in", agent: {email: agents(:one).email, password: '123456'}
follow_redirect!
end
end
Both throw me an error:
Error:
FlowsTest#test_Login_and_navigate:
ArgumentError: unknown keywords: email, password
test/integration/Flows_test.rb:6:in `block in <class:FlowsTest>'
I guess I'm passing in the params in a wrong way. Because email and password should be taken from the fixtures, or am I wrong? Can anyone help? Would be very much appreciated. Thank you all in advance!
Solved by:
require 'test_helper'
class FlowsTest < ActionDispatch::IntegrationTest
fixtures :agents
def test_login
get "/agents/sign_in"
assert_equal 200, status
post "/agents/sign_in", params: { email: agents(:one).email,
password: agents(:one).password }
follow_redirect!
assert_equal 200, status
assert_equal "/", path
end
end
Related
I have two tests. The results of each depend upon the user count.
At the moment, I have no user fixtures. The second test introduces a user in its setup method. The first test would fail if there were users in the db.
But I want to introduce users in users.yml. As such, the first test will fail because of the existing users. Is there any way I can instruct this test to ignore fixtures/users.yml?
require 'test_helper'
class UsersSignupTestWithoutExistingUsers < ActionDispatch::IntegrationTest
test "Signup page is accessible" do
get new_user_registration_path
assert_response :success
end
end
class UsersSignupTestWithExistingUsers < ActionDispatch::IntegrationTest
def setup
post user_registration_path, params: {user: {
email: "user#test.com",
password: "password",
password_confirmation: "password"
}}
end
test "Signup page will redirect" do
get new_user_registration_path
assert_response :redirect
end
end
In the test that requires no users in the DB you can stub the method that looks in the DB for users so that it returns an empty set for that test.
I'm working my way through Chapter 9 of https://www.railstutorial.org/ and am running into trouble with an integration test.
The test looks like this:
class UsersLoginTest < ActionDispatch::IntegrationTest
...
test "login with remembering" do
log_in_as(#user, remember_me: '1')
assert_not_empty cookies['remember_token']
end
...
end
The call to log_in_as is a function added to ActionDispatch::IntegrationTest in my test_helper, and appears to be working as expected. One of the side effects of this function is that a cookie named 'remember_token' gets set. However, the assertion fails with the message:
FAIL["test_login_with_remembering", UsersLoginTest, 14.115229932998773]
test_login_with_remembering#UsersLoginTest (14.12s)
Expected nil (NilClass) to respond to #empty?.
test/integration/users_login_test.rb:48:in `block in <class:UsersLoginTest>'
Any idea what's going on here? Running the test in the debugger seems to suggest that the cookies object doesn't contain anything that looks like I would expect (there are a couple of cookies that I'm setting in the app, and none of them are appearing). All google turns up is a bunch of people suggesting that it's a bad idea to access cookies in integration tests. I'm running Rails 5.1.2 if that helps.
Rails earlier versions change the behavior, the Rails tutorial seems to be deprecated due to an older version Rails.
To pass tests you can forget helper like:
class UsersLoginTest < ActionDispatch::IntegrationTest
...
test "remember if checked in login" do
post login_path, params: { session: { email: #user.email, password: "password", remember_me: '1'}}
assert_not_empty cookies[:remember_token]
end
test "no remember if not checked in login" do
post login_path, params: { session: { email: #user.email, password: "password", remember_me: '1'}}
post login_path, params: { session: { email: #user.email, password: "password", remember_me: '0'}}
assert_empty cookies[:remember_token]
end
...
end
I'm going through Michael Hartl's Ruby tutorial and have been stuck for a day on a failing test
I get this when I run:
Error:
UsersControllerTest#test_should_redirect_edit_when_logged_in_as_wrong_user:
NoMethodError: undefined method `session' for nil:NilClass
test/test_helper.rb:19:in `log_in_as'
test/controllers/users_controller_test.rb:37:in `block in <class:UsersControllerTest>'
Here is the calling code:
require 'test_helper'
class UsersControllerTest < ActionDispatch::IntegrationTest
def setup
#user = users(:michael)
#otheruser = users(:archer)
end
test "should redirect update when logged in as wrong user" do
log_in_as(#other_user)
patch user_path(#user), params: { user: { name: #user.name,
email: #user.email } }
assert flash.empty?
assert_redirected_to root_url
end
*And here is the method I'm trying to call from the **test_helper** class:*
# Log in as a particular user
def log_in_as(user)
session[:user_id] = user.id
end
I was missing a part in my test_helper.rb class:
class ActionDispatch::IntegrationTest
# Log in as a particular user.
def log_in_as(user, password: 'password', remember_me: '1')
post login_path, params: { session: { email: user.email,
password: password,
remember_me: remember_me } }
end
end
Thank you for taking a look!
Did you include this line of code: include SessionsHelper in your application_controller.rb?
You have typo in setup method from the code above: #otheruser = users(:archer) should be #other_user = users(:archer)
Check again the code from the test file: test / controllers / users_controller_test.rb
especially this part of the code:
test "should redirect edit when logged in as wrong user" do
log_in_as(#other_user)
get edit_user_path(#user)
assert flash.empty?
assert_redirected_to root_url
end
Hope it helps!
I'm trying to ensure proper user access is maintained with Devise in Rails 4, and I'm having a hard time logging a user in in the test suite.
The simplest case:
require 'test_helper'
include Devise::TestHelpers
class SiteLayoutTest < ActionDispatch::IntegrationTest
def setup
#user = users(:test1)
end
test "logged in should get index" do
sign_in #user
get users_path
assert_response :success
assert_select "title", "User Index"
end
end
So far I've not done more really than just implement Devise and a Users controller with the appropriate actions.
I consistently get: NoMethodError: undefined method 'env' for nil:NilClass, referring specifically to the line containing sign_in #user and I can find other instances of people getting the same error, but never seem to find an actual solution to the problem I'm attempting to solve.
How do I log a user in with Devise in Rails 4 for testing purposes? Thanks.
EDIT:
fixtures/users.yml
test1:
id: '1'
email: 'test1#example.com'
encrypted_password: <%= Devise::Encryptor.digest(User, "password") %>
created_at: <%= Time.now - 6.minutes %>
updated_at: <%= Time.now - 4.minutes %>
SOLUTION IN SITU:
test "logged in should get index" do
post user_session_path, 'user[email]' => #user.email, 'user[password]' => 'password'
get users_path
assert_response :success
assert_select "title", "User Index"
end
This is from their docs:
"Do not use Devise::TestHelpers in integration tests."
You have to sign in manually. This is an example of a test for a website that does not allow users to get to the root path unless signed in. You can create a method in a support file that signs in the user manually and then call it whenever you want to sign in the user, so that you don't have to use this code every time you need to sign in a user.
require 'test_helper'
class UserFlowsTest < ActionDispatch::IntegrationTest
test "signed in user is redirected to root_path" do
get user_session_path
assert_equal 200, status
#david = User.create(email: "david#mail.com", password: Devise::Encryptor.digest(User, "helloworld"))
post user_session_path, 'user[email]' => #david.email, 'user[password]' => #david.password
follow_redirect!
assert_equal 200, status
assert_equal "/", path
end
test "user is redirected to sign in page when visiting home page" do
get "/"
assert_equal 302, status
follow_redirect!
assert_equal "/users/sign_in", path
assert_equal 200, status
end
end
EDIT: Just in case it's helpful in the future. You can use Warden Test Helpers for integration tests but the way above is a better test. This is a working example:
require 'test_helper'
include Warden::Test::Helpers
class UserFlowsTest < ActionDispatch::IntegrationTest
test "user can see home page after login" do
#david = User.create(email: "david#mail.com", password: Devise::Encryptor.digest(User, "helloworld"))
login_as(#david)
get "/"
assert_equal 200, status # User gets root_path because he loged in
assert_equal "/", path
logout
get "/"
assert_equal 302, status # User is redirected because he loged out
Warden.test_reset! #reset Warden after each example
end
end
I'm trying to test user model, for which I've devise authentication.
The problem I'm facing is,
1. Having 'password'/'password_confirmation' fields in fixtures is giving me invalid column 'password'/'password_confirmation' error.
If I remove these columns from fixture and add in user_test.rb
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
#user = User.new(name: "example user",
email: "example#example.com",
password: "Test123",
work_number: '1234567890',
cell_number: '1234567890')
end
test "should be valid" do
assert #user.valid?
end
test "name should be present" do
#user.name = "Example Name "
assert #user.valid?
end
end
The error I'm getting is:
test_0001_should be valid FAIL (0.74s)
Minitest::Assertion: Failed assertion, no message given.
test/models/user_test.rb:49:in `block in <class:UserTest>'
test_0002_name should be present FAIL (0.01s)
Minitest::Assertion: Failed assertion, no message given.
test/models/user_test.rb:54:in `block in <class:UserTest>'
Fabulous run in 0.75901s
2 tests, 2 assertions, 2 failures, 0 errors, 0 skips
I'm wondering why my user object is not valid?
Thanks
I got a work around after some investigation like below:
Add a helper method for fixture:
# test/helpers/fixture_file_helpers.rb
module FixtureFileHelpers
def encrypted_password(password = 'password123')
User.new.send(:password_digest, password)
end
end
# test/test_helper.rb
require './helpers/fixture_file_helpers.rb'
ActiveRecord::FixtureSet.context_class.send :include, FixtureFileHelpers
And make fixture like this:
default:
email: 'default#example.com'
name: "User name"
encrypted_password: <%= encrypted_password %>
work_number: '(911) 235-9871'
cell_number: '(911) 235-9871'
And use this fixture as user object in user test.
def setup
#user = users(:default)
end