I have the following errors:
1) Failure:
UsersLoginTest#test_login_with_invalid_information [/REDACTED/users_login_test.rb:32]:
expecting <"session/new"> but rendering with <["sessions/new", "layouts/application"]>
2) Failure:
UsersEditTest#test_unsuccessful_edit [/REDACTED/test/integration/users_edit_test.rb:11]:
expecting <"users/edit"> but rendering with <[]>
3) Failure:
UsersEditTest#test_successful_edit [/REDACTED/test/integration/users_edit_test.rb:22]:
expecting <"users/edit"> but rendering with <[]>
Relevant code from user_login_test.rb:
test "login with invalid information" do
get login_path
assert_template 'session/new'
post login_path, session: { email: "", password: "" }
assert_template 'session/new'
assert_not flash.empty?
get root_path
assert flash.empty?
end
users_edit_test.rb:
require 'test_helper'
class UsersEditTest < ActionDispatch::IntegrationTest
def setup
#user = User.find_by_name(:testuser)
end
test "unsuccessful edit" do
log_in_as(#user)
get edit_user_path(#user)
assert_template 'users/edit'
patch user_path(#user), user: { name: "",
email: "foo#invalid",
password: "foo",
password_confirmation: "bar" }
assert_template 'users/edit'
end
test "successful edit" do
log_in_as(#user)
get edit_user_path(#user)
assert_template 'users/edit'
name = "Foo Bar"
email = "foo#bar.com"
patch user_path(#user), user: { name: name,
email: email,
password: "",
password_confirmation: "" }
assert_not flash.empty?
assert_redirected_to #user
#user.reload
assert_equal name, #user.name
assert_equal email, #user.email
end
end
After several grueling hours of trying to hunt down the problem, I am still unable to find it. Tracing through the several problems, I feel like it might be a problem with the following test login code:
def log_in_as(user, options = {})
password = options[:password] || 'password'
remember_me = options[:remember_me] || '1'
if integration_test?
get login_path
post login_path, session: { email: user.name,
password: password,
remember_me: remember_me
}
else
session[:user_id] = user.id
end
end
I'm happy to update with more information as needed, but I'm pretty much at a loss.
It seems you redirected instead of rendering. Try that:
expect(response).to redirect_to root_path
to make sure you're redirected
I'm currently working through chapter 9 of the same Rails tutorial, and I ran into pretty much the same issue. After playing around in the console for a while I decided to just test it manually in the browser and was indeed unable to get to my edit page even though I was logged in. Which got me thinking that it might not be a problem with my tests but instead with the authorization in the users_controller.
Turns out I had completely forgotten to put the redirect_to login_url (in the logged_in_user filter) within an unless block so it was always just redirecting to the login page no matter what. The correct code is:
def logged_in_user
unless logged_in?
flash[:danger] = 'Please log in.'
redirect_to login_url
end
end
Now my tests are passing. Perhaps you've run into a similar issue. Either way I've often found it useful to just return to the browser and try to replicate the integration tests manually, just to figure out if it's a problem with my code or I've just written a dodgy test.
Related
I'm using Rails 6 to work through the Hartl Tutorial, using mostly the online version. I'm in Chapter 10 (which doesn't correspond to the book version chapter numbering)...
https://www.railstutorial.org/book/updating_and_deleting_users
In Section 10.2.2, after Listing 10.25, the Rails Test should be green, but I get these 2 FAIL messages:
FAIL["test_should_redirect_edit_when_not_logged_in", #, 11.729448000027332]
test_should_redirect_edit_when_not_logged_in#UsersControllerTest (11.73s)
Expected true to be nil or false
test/controllers/users_controller_test.rb:18:in `block in '
FAIL["test_should_redirect_update_when_not_logged_in", #, 1.2034909999929368]
test_should_redirect_update_when_not_logged_in#UsersControllerTest (1.20s)
Expected true to be nil or false
test/controllers/users_controller_test.rb:26:in `block in '
The related code is this:
test "should redirect edit when not logged in" do
log_in_as(#other_user)
get edit_user_path(#user)
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect update when not logged in" do
log_in_as(#other_user)
patch user_path(#user), params: { user: { name: #user.name,
email: #user.email } }
assert_not flash.empty?
assert_redirected_to login_url
end
It's the log_in_as(#other_user) that appears to be the problem, but it could be elsewhere. I can't see why this section has a problem when the similar one in users_edit_test.rb does not.
Can someone please try to help me out in this error? I don't really understand what the error means to me.
test "valid signup information with account activation" do
get signup_path
assert_difference 'User.count', 1 do
post users_path, params: {user: {name: "Example User",
email: "user#example.com",
password: "password",
password_confirmation: "password"}}
end
assert_equal 1, ActionMailer::Base.deliveries.size
user = assigns(:user)
assert_not user.activated?
#Try to log in before actication.
log_in_as(user)
assert_not is_logged_in?
#Invalid activation token with valid email
get edit_account_activation_path('invalid token',email: user.email)
assert_not is_logged_in?
#Valid activation token with invalid email
get edit_account_activation_path(user.activation_token, email: 'wrong')
assert_not is_logged_in?
#Valid activation token with valid email
get edit_account_activation_path(user.activation_token,email: user.email)
assert user.reload.activated?
follow_redirect!
assert_template 'users/show'
assert is_logged_in?
end
This test is keep failing because of this error:
Failure:
UsersSignupTest#test_valid_signup_information_with_account_activation [D:/RubyOnRails/RailsProjects/sample_app/test/integration/users_signup_test.rb:53]:
Expected true to be nil or false
The Error on line 53 is coming from here.
Line 52 log_in_as(user)
Line 53 assert_not is_logged_in?
This is my methods
def is_logged_in?
!session[:user_id].nil?
end
def log_in_as(user)
session[:user_id] = user.id
end
Let's take a look at what each step of your test is actually doing, to understand the error.
First, you "sign up" a user - most likely at the UsersController#create action (or whatever else your routes.rb file defines):
post users_path, params: {user: {name: "Example User",
email: "user#example.com",
password: "password",
password_confirmation: "password"}}
Doing this creates a new User record, where user.disabled == true:
assert_difference 'User.count', 1
assert_not user.activated?
Next, you wanted to test that a disabled user cannot log in. The logic that dictates this is will be within the login controller action. My guess is that it will be in SessionsController#create, if such a thing exists in your application. It could also be placed somewhere more generic, like as a before_action in the ApplicationController.
In order to test this, you need to simulate a real sign-in action. I cannot say for sure what code this will require without seeing the rest of your application, but for example it could be something like:
post sessions_path, params: {user: {email: "user#example.com",
password: "password"}}
Or if you want to make this a true integration test, you could even simulate filling in the form and clicking the "log in" button. What you have here currently is more akin to a controller test, not an integration test.
The method you were using previously:
def log_in_as(user)
session[:user_id] = user.id
end
Is fine to use in tests that don't care about simulating a "real" login. But for tests that do care about the login being "real", you need to it the relevant controller action.
In this case, your logic for "not letting disabled users log in" was never actually being invoked; hence the failure.
If you want to make the error message clearer when using assertions like this, you can include the error message like so:
assert_not is_logged_in?, 'Disabled user was able to log in'
Below is a complete example of what the tests could look like. You may need to tweak the implementation slightly, depending on how your controllers are defined.
test "valid signup information with account activation" do
get signup_path
assert_difference 'User.count', 1 do
post users_path, params: {user: {name: "Example User",
email: "user#example.com",
password: "password",
password_confirmation: "password"}}
end
assert_equal 1, ActionMailer::Base.deliveries.size
user = assigns(:user)
assert_not user.activated?
end
test "cannot log in with disabled account" do
user = user.create!(name: "Example User",
email: "user#example.com",
password: "password",
password_confirmation: "password")
post login_path, params: { session: { email: "user#example.com",
password: "password" } }
assert_not is_logged_in?, 'Disabled user was able to log in'
end
test "cannot login with invalid activation token" do
# ...
end
test "can login with valid activation token" do
# ...
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!
Working through the Rails Tutorial and in chapter 8 I can't get one of my tests to pass. Been checking around for hours... any help would be greatly appreciated.
ERROR["test_login_with_valid_information", UsersLoginTest, 2015-09-07 00:25:37 -0700]
test_login_with_valid_information#UsersLoginTest (1441610737.31s)
BCrypt::Errors::InvalidHash:
BCrypt::Errors::InvalidHash: invalid hash
app/controllers/sessions_controller.rb:8:in `create'
test/integration/users_login_test.rb:22:in `block in <class:UsersLoginTest>'
app/controllers/sessions_controller.rb:8:in `create'
test/integration/users_login_test.rb:22:in `block in <class:UsersLoginTest>'
22/22: [============] 100% Time: 00:00:00, Time: 00:00:00
Finished in 0.46288s
22 tests, 44 assertions, 0 failures, 1 errors, 0 skips
users_login_test.rb
require 'test_helper'
class UsersLoginTest < ActionDispatch::IntegrationTest
def setup
#user = users(:michael)
end
test "login with invalid information" do
get login_path
assert_template 'sessions/new'
post login_path, session: { email: "", password: "" }
assert_template 'sessions/new'
assert_not flash.empty?
get root_path
assert flash.empty?
end
test "login with valid information" do
get login_path
post login_path, session: { email: #user.email, password: 'password' }
assert_redirected_to #user
follow_redirect!
assert_template 'users/show'
assert_select "a[href=?]", login_path, count: 0
assert_select "a[href=?]", logout_path
assert_select "a[href=?]", user_path(#user)
end
end
sessions_controller.rb
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
log_in user
redirect_to user
else
flash.now[:danger] = 'Invalid email/password combination'
render 'new'
end
end
def destroy
end
end
I know it's been a while since originally posted, but I had exactly the same error and my problem was a typo (missing =) in
users.yml
michael:
name: Michael Example
email: michael#example.com
password_digest: <% User.digest('password') %>
where it should have been
michael:
name: Michael Example
email: michael#example.com
password_digest: <%= User.digest('password') %>
#PraveenGeorge is correct - you need to back track and review your code at least since the last time the tests passed. Based on the fact that the content of the two files you've shared match to the tutorial, the problem lies elsewhere (and, unfortunately, out of sight from us on SO).
Perhaps it's in user.rb where you def User.digest(string) or in sessions_helper.rb?
Dear #Travislogan : As the ruby on rails tutorial itself is self explanatory in most possible way, you might have missed some of the steps/code before you reached into the section 8.2. So please cross check all tests and your project code from at least the previous chapter to the current one , one more time.It will help you to find out the error in your code.
Here is my test, similar to the mailer test from the Hartl tutorial:
test "valid signup information with account activation" do
get new_user_path
assert_difference 'User.count', 1 do
post users_path, user: { username: "Jwan622",
first_name: "Jeffrey",
last_name: "Wan",
email: "Jwan622#yahoo.com",
password: "password",
password_confirmation: "password",
city: "New York City",
state: "New York",
country: "United States"
}
end
assert_equal 1, ActionMailer::Base.deliveries.size
user = assigns(:user)
assert_not user.activated?
log_in_as(user)
assert_not is_logged_in?
# Invalid activation token
get edit_account_activation_path("invalid token")
assert_not is_logged_in?
# Valid token, wrong email
get edit_account_activation_path(user.activation_token, email: 'wrong')
assert_not is_logged_in?
# Valid activation token
get edit_account_activation_path(user.activation_token, email: user.email)
assert user.reload.activated?
follow_redirect!
assert_template 'root_path'
assert is_logged_in?
end
Here is my error message:
1) Failure:
UserSignupTest#test_valid_signup_information_with_account_activation [/Users/Jwan/Dropbox/Turing/projects/FlyAwayFromHere/test/integration/user_signup_test.rb:94]:
expecting <"root_path"> but rendering with <["layouts/_praise_bar", "layouts/_city_change", "planners/new", "layouts/_nav_bar", "layouts/_footer_bar", "layouts/application"]>
Questions:
1) What kind of test is assert_template? Is it minitest? capybara?
2) What kind of method is get? Is it a rack method that works in rails?
3) What does "assigns" do?
4) What am I doing wrong with this assert_template?
Change it to assert_template :new to make it work; this is testing that the new.html.erb was rendered.
See http://guides.rubyonrails.org/testing.html#testing-templates-and-layouts for more about assert_template and testing views in general.