I am currently working on Michael Hartl's Ruby on Rails tutorial. I've been getting 4 separate errors during this chapter and would greatly appreciate your help with resolving them.
$ bundle exec rake test
1) Error:
SiteLayoutTest#test_layout_links:
NoMethodError: undefined method `full_title' for #<SiteLayoutTest:0x000000049fd568>
test/integration/site_layout_test.rb:13:in `block in <class:SiteLayoutTest>'
2) Error:
UsersLoginTest#test_login_with_remembering:
ActionController::RoutingError: No route matches [POST] "/login"
test/test_helper.rb:18:in `log_in_as'
test/integration/users_login_test.rb:31:in `block in <class:UsersLoginTest>'
3) Error:
UsersLoginTest#test_login_with_valid_information_followed_by_logout:
ActionController::RoutingError: No route matches [POST] "/login"
test/integration/users_login_test.rb:11:in `block in <class:UsersLoginTest>'
4) Error:
UsersLoginTest#test_login_without_remembering:
ActionController::RoutingError: No route matches [POST] "/login"
test/test_helper.rb:18:in `log_in_as'
test/integration/users_login_test.rb:36:in `block in <class:UsersLoginTest>'
23 runs, 39 assertions, 0 failures, 4 errors, 0 skips
$ bundle exec rake routes
Prefix Verb URI Pattern Controller#Action
root GET / static_pages#home
help GET /help(.:format) static_pages#help
about GET /about(.:format) static_pages#about
contact GET /contact(.:format) static_pages#contact
signup GET /signup(.:format) users#new
login GET /login(.:format) sessions#new
GET /login(.:format) sessions#create
logout GET /logout(.:format) sessions#destroy
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
config/routes.rb
Rails.application.routes.draw do
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
get 'login' => 'sessions#create'
get 'logout' => 'sessions#destroy'
resources :users
end
test/integration/users_login_test.rb
require 'test_helper'
class UsersLoginTest < ActionDispatch::IntegrationTest
def setup
#user = users(:michael)
end
test "login with valid information followed by logout" do
get login_path
post login_path, session: { email: #user.email, password: 'password' }
assert is_logged_in?
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)
delete logout_path
assert_not is_logged_in?
assert_redirected_to root_url
# Simulate a user clicking logout in a second window.
delete logout_path
follow_redirect!
assert_select "a[href=?]", login_path
assert_select "a[href=?]", logout_path, count: 0
assert_select "a[href=?]", user_path(#user), count: 0
end
test "login with remembering" do
log_in_as(#user, remember_me: '1')
assert_not_nil cookies['remember_token']
end
test "login without remembering" do
log_in_as(#user, remember_me: '0')
assert_nil cookies['remember_token']
end
end
test/test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
class ActiveSupport::TestCase
fixtures :all
# Returns true if a test user is logged in.
def is_logged_in?
!session[:user_id].nil?
end
# Logs in a test user.
def log_in_as(user, options = {})
password = options[:password] || 'password'
remember_me = options[:remember_me] || '1'
if integration_test?
post login_path, session: { email: user.email,
password: password,
remember_me: remember_me }
else
session[:user_id] = user.id
end
end
private
# Returns true inside an integration test.
def integration_test?
defined?(post_via_redirect)
end
end
test/integration/site_layout_test.rb
require 'test_helper'
class SiteLayoutTest < ActionDispatch::IntegrationTest
test "layout links" do
get root_path
assert_template 'static_pages/home'
assert_select "a[href=?]", root_path, count: 2
assert_select "a[href=?]", help_path
assert_select "a[href=?]", about_path
assert_select "a[href=?]", contact_path
get signup_path
assert_select "title", full_title("Sign up")
end
end
I made a mess..ugh. Any and all help is much appreciated!
Edit: Also, i'm fairly new to all this, so if I'm supposed to be deleting the old tests as they test GREEN, please let me know. I'm not sure if these failed tests go RED because I'm doing something wrong or if I'm supposed to be deleting them as I go through the tutorial. Thank you!
In your routes.rb
get 'login' => 'sessions#new'
get 'login' => 'sessions#create'
that looks weird. I guess it should be
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
Related
I'm trying to rewrite my tests in Rspec and am stuck on trying to make an update to a user.
I'm sure this is a silly thing I'm overlooking, but I've looked everywhere and can't find an answer.
Here's myspec file:
require 'spec_helper'
describe UsersController, type: [:request, :controller] do
before(:each) { host! 'localhost:3000/' }
describe "#update" do
it "doesn't update user" do
form_params = {
params: {
id: 1,
email: "hello#example",
name: "hello"
}
}
patch :update, params: form_params
end
end
end
It seems like the :update portion is wrong but as far as I can see in my routes, there's no other way to call it.
Here's the error:
ActionController::RoutingError: No route matches [PATCH] "/update"
Here's my routes:
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
Here's my old test:
test "should redirect update when not logged in" do
patch user_path(#user), params: { user: { name: #user.name, email: #user.email } }
assert_not flash.empty?
assert_redirected_to login_url
end
And if you guys possibly know - how do I convert assert_not flash.empty? to Rspec?
Thanks so much in advance!
At first, you can't to use multiple types in type: [:request, :controller]. If you want to write request specs you have to specify named route (user_path) or url ("/users/:id")
require 'spec_helper'
describe UsersController, type: :request do
describe "#update" do
let(:user) { create :user } # or use fixtures here
# I'm just a bit confused here, why it should not update?
it "doesn't update user" do
patch user_path(user), email: "hello#example", name: "hello"
expect(flash.empty?).to eq false
expect(response).to redirect_to login_path
end
end
end
I'm getting two different test errors in Chapter 8.2.1 of Michael Hartl's Ruby on Rails Tutorial. I'm new to Rails, but I have triple checked for syntax errors and anything else I could find. Any help is very much appreciated.
Error Message 1:
ERROR["test_should_get_new", Minitest::Result, 0.9693643249993329]
test_should_get_new#Minitest::Result (0.97s)
NameError: NameError: undefined local variable or method users_new_url' for #<UsersControllerTest:0x00000006e953f8>
test/controllers/users_controller_test.rb:5:inblock in '
Error Message 2:
ERROR["test_invalid_signup_information", Minitest::Result, 0.8977870759990765]
test_invalid_signup_information#Minitest::Result (0.90s)
ActionController::RoutingError: ActionController::RoutingError: No route matches [POST] "/signup"
test/integration/users_signup_test.rb:8:in block (2 levels) in <class:UsersSignupTest>'
test/integration/users_signup_test.rb:7:inblock in '
Routes.rb
Rails.application.routes.draw do
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
resources :users
end
Sessions Controller:
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 the user in and redirect to the user's show page.
else
flash.now[:danger] = 'Invalid email/password combination'
render 'new'
end
end
def destroy
end
end
Users Controller:
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
flash[:success] = "Welcome to your new profile!"
redirect_to #user
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
end
Users controller test
require 'test_helper'
class UsersControllerTest < ActionDispatch::IntegrationTest
test "should get new" do
get users_new_url
assert_response :success
end
end
Users Signup Test
require 'test_helper'
class UsersSignupTest < ActionDispatch::IntegrationTest
test "invalid signup information" do
get signup_path
assert_no_difference 'User.count' do
post users_path, params: { user: { name: "",
email: "user#invalid",
password: "foo",
password_confirmation: "bar" } }
end
assert_template 'users/new'
assert_select 'div#error_explanation'
assert_select 'div.field_with_errors'
assert_select 'form[action="/signup"]'
end
test "valid signup information" 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
follow_redirect!
assert_template 'users/show'
assert_not flash.nil?
end
end
In your users_controller_test, the code doesn't know what users_new_url is. This is probably because that route doesn't exist. You will most likely have to do something like get new_user_path, but you can find out by typing rake routes and getting the list of your available routes.
Here's an example of what rake routes will output:
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
You can reference a named path by appending _path to the name. i.e. users_path will map to the "users#index"controller and method.
rake routes will also help for your second problem, which is that you do not have a route defined for POST /signup -- you have a GET /signup.
So, you'll need to add a line like:
post '/signup', to: 'users#create'
This route will map to your UsersController's #create method, which I see you have in your code.
I've been following the Michael Hartl tutorial for learning rails and have been doing pretty well thus far, but I'm stumped on this issue which I've encountered repeatedly. I'm not skilled enough to know if there is a configuration problem in my environment or something else, but this makes NO sense to me.
In ANY of the controller tests I attempt to run, I can never get my helper URL methods to work. As an example:
test "should redirect home when not an admin" do
log_in_as(#other_user)
assert_no_difference 'User.count' do
delete user_path(#user)
end
assert redirect_to root_url
end
Generates the following error:
ERROR["test_should_redirect_home_when_not_an_admin", UsersControllerTest, 0.9899668790167198]
test_should_redirect_home_when_not_an_admin#UsersControllerTest (0.99s)
ActionController::UrlGenerationError: ActionController::UrlGenerationError: No route matches {:action=>"/users/762146111", :controller=>"users"}
test/controllers/users_controller_test.rb:60:in `block (2 levels) in <class:UsersControllerTest>'
test/controllers/users_controller_test.rb:59:in `block in <class:UsersControllerTest>'
Even simple tests like
test "should redirect index when not logged in" do
get users_path
assert_redirected_to login_url
end
Produce the same error:
ERROR["test_should_redirect_index_when_not_logged_in", UsersControllerTest, 1.5291320629185066]
test_should_redirect_index_when_not_logged_in#UsersControllerTest (1.53s)
ActionController::UrlGenerationError: ActionController::UrlGenerationError: No route matches {:action=>"/users", :controller=>"users"}
test/controllers/users_controller_test.rb:34:in `block in <class:UsersControllerTest>'
Everything I've googled about this issue hasn't helped, because for some reason I cannot determine the user_path method (or any other similar method) somehow thinks the action I'm trying to take in my controller is the path!
I've verified that my routes file is configured correctly.
Rails.application.routes.draw do
root 'static_pages#home'
get '/help' => 'static_pages#help'
get '/about' => 'static_pages#about'
get '/contact' => 'static_pages#contact'
get '/signup' => 'users#new'
post '/signup' => 'users#create'
get '/login' => 'sessions#new'
post '/login' => 'sessions#create'
delete '/logout' => 'sessions#destroy'
get 'sessions/new'
resources :users
end
I've checked that running "rails routes" has the correct routes. I've even checked in rails console that "app.user_path(1)" spits out a valid path.
At this point I'm just beyond stumped as to why these helper methods don't seem to be helping... I also don't know what they're actually called so my googling has been fairly fruitless.
To get around this issue in the tutorial, I've been using syntax like
patch :edit, { id: #user }, params: { user: { name: #user.name,
email: #user.email }}
Or
test "should redirect index when not logged in" do
get :index
assert_redirected_to login_url
end
Which seems to work.
Also here is one of my test files if that's helpful:
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def setup
#user = users(:michael)
#other_user = users(:archer)
end
test "should get new" do
get :new
assert_response :success
end
test "should redirect edit when user not logged in" do
get :edit, params: { id: #user }
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect update when user not logged in" do
patch :edit, { id: #user }, params: { user: { name: #user.name,
email: #user.email }}
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect index when not logged in" do
# get users_path
get :index
assert_redirected_to login_url
end
test "should redirect destroy when not logged in" do
assert_no_difference 'User.count' do
delete user_path(#user)
end
assert redirect_to login_url
end
test "should redirect home when not an admin" do
log_in_as(#other_user)
assert_no_difference 'User.count' do
delete user_path(#user)
end
assert redirect_to root_url
end
end
Please let me know what other files I can post to be helpful.
I had the same issue and I fixed it by changing the file 'users_controller_test.rb' file replacing:
class UsersControllerTest < ActionController::TestCase
for
class UsersControllerTest < ActionDispatch::IntegrationTest
But first, in your case, check that you have in your Gemfile the line:
gem 'rails', '5.0.1'
as the tutorial shows.
I can also see that you have the following test:
test 'should get new' do
get :new
assert_response :success
end
When you make the correction you'll have to change the above test to:
test 'should get new' do
get new_user_path
assert_response :success
end
After that, run your tests and you should have them all passed.
Hope it helps
I'm doing some integration testing in rails for a sessions controller and in the test I get that my login_path is not defined even though it is defined in the routes.rb file and when I invoke that path in the console it also shows up. Any idea what's causing this?
routes.rb:
Rails.application.routes.draw do
get 'sessions/new'
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :users
end
test:
require 'test_helper'
class UsersLoginTest < ActionDispatch::IntegrationTest
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
If I'm reading the documentation correctly, you should call the "test" method and then pass the test code as a block. Something like this should work
class UsersLoginTest < ActionDispatch::IntegrationTest
test "user can log in" 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
end
I am trying to work through the Rails tutorial at railstutorial.org and am stuck at this problem. My user_path in the test is supposed to go to the individual user's profile page, but is instead going to users/index (which I haven't created yet, on purpose).
/* My test code */
describe "profile page" do
#let(user) { FactoryGirl.create(:user) }
#user = User.new(name: "Example User", email: "user#example.com",
password: "foobar", password_confirmation: "foobar")
before { visit user_path(#user) }
it { should have_content(user.name) }
it { shoult have_title(user.name) }
end
/* Failures: */
1) UserPages profile page
←[31mFailure/Error:←[0m ←[31mbefore { visit user_path(#user) }←[0m
←[31mActionView::MissingTemplate←[0m:
←[31mMissing template users/index, application/index with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffe
}. Searched in:←[0m
←[31m * "C:/Users/rajeshch/Documents/Projects/sample_app/app/views"←[0m
[36m # C:in `find_template'←[0m
[36m # ./spec/requests/user_pages_spec.rb:19:in `block (3 levels) in <top (required)>'←[0m
The routes file shows that user_path should give me users/{id} or so
> rake routes
Prefix Verb URI Pattern Controller#Action
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show <<<------
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
root GET / static_pages#home
signup GET /signup(.:format) users#new
help GET /help(.:format) static_pages#help
about GET /about(.:format) static_pages#about
contact GET /contact(.:format) static_pages#contact
/* users_controller.rb*/
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def new
end
end
/* config/routes.rb */
SampleApp::Application.routes.draw do
resources :users
root 'static_pages#home'
match '/signup', to: 'users#new', via: 'get'
match '/help', to: 'static_pages#help', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'
match '/contact', to: 'static_pages#contact', via: 'get'
end
You should save the User first with #user.save! before calling visit user_path(#user)
Because until you save the user it wont persist in the database and will not have any id.
describe "profile page" do
#let(user) { FactoryGirl.create(:user) }
#user = User.new(name: "Example User", email: "user#example.com",
password: "foobar", password_confirmation: "foobar")
# Add this to your code ..
#user.save!
before { visit user_path(#user) }
it { should have_content(user.name) }
it { shoult have_title(user.name) }
end
Have you checked if #user has a value?
user_path(#user) will go to /users/<#user.id> but if #user is nil, it will try to go /users/. Given you haven't created the index method and views yet, that will probably be why it fails.
Thanks for the test code. Firstly your user is not in the database - change the .new to .create or add a #user.save. Secondly your params[:id] is not populated in the test code so the find will fail (add controller.params[:id] = #user.id to your test). (Thirdly you have a typo shoult instead of should in the last test.)
It doesn't seem like you included your test code, which would be immensely helpful in figuring out this problem. Most likely, you have #user set as nil in the test, fixing that will solve the problem.