I'm going through Mr. Hartl's Tutorial and trying to copy it exactly, even kinda using his completed github code as a guide, but I'm stuck with the following after running the "bundle exec rspec spec/":
Failures:
1) Authentication signin with valid information
Failure/Error: before { sign_in user }
ActionView::MissingTemplate:
Missing template sessions/create, application/create with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}. Searched in:
* "/home/nemo/rails_projects/sample_app/app/views"
# ./spec/support/utilities.rb:19:in `sign_in'
# ./spec/requests/authentication_pages_spec.rb:32:in `block (4 levels) in <top (required)>'
2) Authentication signin with valid information
Failure/Error: before { sign_in user }
ActionView::MissingTemplate:
Missing template sessions/create, application/create with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}. Searched in:
* "/home/nemo/rails_projects/sample_app/app/views"
# ./spec/support/utilities.rb:19:in `sign_in'
# ./spec/requests/authentication_pages_spec.rb:32:in `block (4 levels) in <top (required)>'
3) Authentication signin with valid information
Failure/Error: before { sign_in user }
ActionView::MissingTemplate:
Missing template sessions/create, application/create with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}. Searched in:
* "/home/nemo/rails_projects/sample_app/app/views"
# ./spec/support/utilities.rb:19:in `sign_in'
# ./spec/requests/authentication_pages_spec.rb:32:in `block (4 levels) in <top (required)>'
4) Authentication signin with valid information
Failure/Error: before { sign_in user }
ActionView::MissingTemplate:
Missing template sessions/create, application/create with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}. Searched in:
* "/home/nemo/rails_projects/sample_app/app/views"
# ./spec/support/utilities.rb:19:in `sign_in'
# ./spec/requests/authentication_pages_spec.rb:32:in `block (4 levels) in <top (required)>'
5) Authentication signin with valid information
Failure/Error: before { sign_in user }
ActionView::MissingTemplate:
Missing template sessions/create, application/create with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}. Searched in:
* "/home/nemo/rails_projects/sample_app/app/views"
# ./spec/support/utilities.rb:19:in `sign_in'
# ./spec/requests/authentication_pages_spec.rb:32:in `block (4 levels) in <top (required)>'
6) Authentication signin with valid information followed by signout
Failure/Error: before { sign_in user }
ActionView::MissingTemplate:
Missing template sessions/create, application/create with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}. Searched in:
* "/home/nemo/rails_projects/sample_app/app/views"
# ./spec/support/utilities.rb:19:in `sign_in'
# ./spec/requests/authentication_pages_spec.rb:32:in `block (4 levels) in <top (required)>'
7) User pages profile page signup with valid information after saving the user
Failure/Error: before { visit user_path(user) }
AbstractController::ActionNotFound:
The action 'index' could not be found for UsersController
# ./spec/requests/user_pages_spec.rb:16:in `block (3 levels) in <top (required)>'
8) User pages profile page signup with valid information after saving the user
Failure/Error: before { visit user_path(user) }
AbstractController::ActionNotFound:
The action 'index' could not be found for UsersController
# ./spec/requests/user_pages_spec.rb:16:in `block (3 levels) in <top (required)>'
9) User pages profile page signup with valid information after saving the user
Failure/Error: before { visit user_path(user) }
AbstractController::ActionNotFound:
The action 'index' could not be found for UsersController
# ./spec/requests/user_pages_spec.rb:16:in `block (3 levels) in <top (required)>'
10) User pages profile page with invalid information
Failure/Error: before { click_button "Save changes" }
Capybara::ElementNotFound:
Unable to find button "Save changes"
# ./spec/requests/user_pages_spec.rb:76:in `block (4 levels) in <top (required)>'
11) User pages profile page page
Failure/Error: it { should have_content("Update your profile") }
expected #has_content?("Update your profile") to return true, got false
# ./spec/requests/user_pages_spec.rb:70:in `block (4 levels) in <top (required)>'
12) User pages profile page page
Failure/Error: it { should have_title("Edit user") }
expected #has_title?("Edit user") to return true, got false
# ./spec/requests/user_pages_spec.rb:71:in `block (4 levels) in <top (required)>'
13) User pages profile page page
Failure/Error: it { should have_link('change', href: 'http://gravatar.com/emails') }
expected #has_link?("change", {:href=>"http://gravatar.com/emails"}) to return true, got false
# ./spec/requests/user_pages_spec.rb:72:in `block (4 levels) in <top (required)>'
Finished in 1.83 seconds
53 examples, 13 failures
spec/requests/authentication_pages_spec.rb:
require 'spec_helper'
describe "Authentication" do
subject { page }
describe "signin page" do
before { visit signin_path }
it { should have_content('Sign in') }
it { should have_title('Sign in') }
end
describe "signin" do
before { visit signin_path }
describe "with invalid information" do
before { click_button "Sign in" }
it { should have_title('Sign in') }
it { should have_selector('div.alert.alert-error', text: 'Invalid') }
describe "after visiting another page" do
before { click_link "Home" }
it { should_not have_selector('div.alert.alert-error') }
end
end
describe "with valid information" do
let(:user) { FactoryGirl.create(:user) }
before { sign_in user }
it { should have_title(user.name) }
it { should have_link('Profile', href: user_path(user)) }
it { should have_link('Settings', href: edit_user_path(user)) }
it { should have_link('Sign out', href: signout_path) }
it { should_not have_link('Sign in', href: signin_path) }
describe "followed by signout" do
before { click_link "Sign out" }
it { should have_link('Sign in') }
end
end
end
end
spec/requests/user_pages_spec.rb
require 'spec_helper'
describe "User pages" do
subject { page }
describe "signup page" do
before { visit signup_path }
it { should have_content('Sign up') }
it { should have_title(full_title('Sign up')) }
end
describe "profile page" do
let(:user) { FactoryGirl.create(:user) }
before { visit user_path(user) }
it { should have_content(user.name) }
it { should have_title(user.name) }
describe "signup" do
before { visit signup_path }
let(:submit) { "Create my account" }
describe "with invalid information" do
it "should not create a user" do
expect { click_button submit }.not_to change(User, :count)
end
describe "after submission" do
before { click_button submit }
it { should have_title('Sign up') }
it { should have_content('error') }
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: "foobar"
fill_in "Confirmation", with: "foobar"
end
it "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
describe "after saving the user" do
before { click_button submit }
let(:user) { User.find_by(email: 'user#example.com') }
it { should have_link('Sign out') }
it { should have_title(user.name) }
it { should have_selector('div.alert.alert-success', text: 'Welcome') }
end
end
end
describe "edit" do
let(:user) { FactoryGirl.create(:user) }
before { visit edit_user_path(user) }
end
describe "page" do
it { should have_content("Update your profile") }
it { should have_title("Edit user") }
it { should have_link('change', href: 'http://gravatar.com/emails') }
end
describe "with invalid information" do
before { click_button "Save changes" }
it { should have_content('error') }
end
end
end
app/controllers/users_controller.rb
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
sign_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
# Handle a successful update.
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
end
app/views/users/edit.html.erb:
<% provide(:title, "Edit user") %>
<h1>Update your profile</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(#user) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirm Password" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Save changes", class: "btn btn-large btn-primary" %>
<% end %>
<%= gravatar_for #user %>
change
</div>
</div>
I'm kind of a greenhorn at this, so let me know if you would like to inspect any of my other codes.
Added to the post, spec/support/utilities.rb:
include ApplicationHelper
RSpec::Matchers.define :have_error_message do |message|
match do |page|
page.should have_selector('div.alert.alert-error', text: 'Invalid')
end
end
def sign_in(user, options={})
if options[:no_capybara]
# Sign in when not using Capybara.
remember_token = User.new_remember_token
cookies[:remember_token] = remember_token
user.update_attribute(:remember_token, User.encrypt(remember_token))
else
visit signin_path
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
end
Added app/controllers/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])
# Sign the user in and redirect to the user's show page.
else
flash.now[:error] = 'Invalid email/password combination'
render 'new'
end
end
def destroy
sign_out
redirect_to root_url
end
end
app/views/sessions/new.html.erb
<% provide(:title, "Sign in") %>
<h1>Sign in</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(:session, url: sessions_path) do |f| %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.submit "Sign in", class: "btn btn-large btn-primary" %>
<% end %>
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>
</div>
I reverted some of the code to the following excerpt from previous tutorials to sessions_controller.rb:
.
.
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
sign_in user
redirect_to user
else
flash.now[:error] = 'Invalid email/password combination'
render 'new'
end
end
.
.
It resulted in only 7 errors this time around.
Failures:
1) User pages profile page signup with valid information after saving the user
Failure/Error: before { visit user_path(user) }
NoMethodError:
undefined method `paginate' for #<Class:0xa6de278>
# ./app/controllers/users_controller.rb:4:in `index'
# ./spec/requests/user_pages_spec.rb:16:in `block (3 levels) in <top (required)>'
2) User pages profile page signup with valid information after saving the user
Failure/Error: before { visit user_path(user) }
NoMethodError:
undefined method `paginate' for #<Class:0xa6de278>
# ./app/controllers/users_controller.rb:4:in `index'
# ./spec/requests/user_pages_spec.rb:16:in `block (3 levels) in <top (required)>'
3) User pages profile page signup with valid information after saving the user
Failure/Error: before { visit user_path(user) }
NoMethodError:
undefined method `paginate' for #<Class:0xa6de278>
# ./app/controllers/users_controller.rb:4:in `index'
# ./spec/requests/user_pages_spec.rb:16:in `block (3 levels) in <top (required)>'
4) User pages profile page with invalid information
Failure/Error: before { click_button "Save changes" }
Capybara::ElementNotFound:
Unable to find button "Save changes"
# ./spec/requests/user_pages_spec.rb:76:in `block (4 levels) in <top (required)>'
5) User pages profile page page
Failure/Error: it { should have_content("Update your profile") }
expected #has_content?("Update your profile") to return true, got false
# ./spec/requests/user_pages_spec.rb:70:in `block (4 levels) in <top (required)>'
6) User pages profile page page
Failure/Error: it { should have_title("Edit user") }
expected #has_title?("Edit user") to return true, got false
# ./spec/requests/user_pages_spec.rb:71:in `block (4 levels) in <top (required)>'
7) User pages profile page page
Failure/Error: it { should have_link('change', href: 'http://gravatar.com/emails') }
expected #has_link?("change", {:href=>"http://gravatar.com/emails"}) to return true, got false
# ./spec/requests/user_pages_spec.rb:72:in `block (4 levels) in <top (required)>'
Finished in 1.88 seconds
53 examples, 7 failures
Failed examples:
rspec ./spec/requests/user_pages_spec.rb:57 # User pages profile page signup with valid information after saving the user
rspec ./spec/requests/user_pages_spec.rb:58 # User pages profile page signup with valid information after saving the user
rspec ./spec/requests/user_pages_spec.rb:59 # User pages profile page signup with valid information after saving the user
rspec ./spec/requests/user_pages_spec.rb:78 # User pages profile page with invalid information
rspec ./spec/requests/user_pages_spec.rb:70 # User pages profile page page
rspec ./spec/requests/user_pages_spec.rb:71 # User pages profile page page
rspec ./spec/requests/user_pages_spec.rb:72 # User pages profile page page
It looks like the problem is with your Sessions#create method:
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
# Sign the user in and redirect to the user's show page.
else
flash.now[:error] = 'Invalid email/password combination'
render 'new'
end
end
I suspect you you are ending up where you have the comment, at which point it "falls through" to the Rails standard controller code which then looks for the create sessions view corresponding to this being the create controller method.
If you check out the corresponding code in the Hartl github repository, its:
def create
user = User.authenticate(params[:session][:email],
params[:session][:password])
if user.nil?
flash.now[:error] = "Invalid email/password combination."
#title = "Sign in"
render 'new'
else
sign_in user
redirect_back_or user
end
end
As to how you got there, it appears that the sign_in user method was successful in getting to and through your Sessions new controller and view code. The submit in your view took you to the Sessions#create point.
Related
Updated but still doesn't work!
update - I thought I had included the Rspec tests I was using but I had not. they are now included
I made the suggested change, but it still doesn't pass. The only hint given by the returned failed test is that it's just not achieving the goal of the test. It doesn't seem to give any clues as to why...
I'm having trouble getting my tests to pass after changing the code as per listing 9.49 and 9.50. I have a feeling I'm missing a detail somewhere, but I can't seem to find it. Here is my code:
edit.html.erb
This page should render the shared 'fields', which has been refactored as part of the exercise.
<% provide(:title, "Edit user") %>
<h1>Update your profile</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(#user) do |f| %>
<%= render 'fields', f: f %>
<%= f.submit "Save changes", class: "btn btn-large btn-primary" %>
<% end %>
<%= gravatar_for #user %>
change
</div>
</div>
new.html.erb
This page should render the shared 'fields', which has been refactored as part of the exercise.
<% provide(:title, 'Sign up') %>
<h1>Sign Up</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(#user) do |f| %>
<%= render 'fields', f: f %>
<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
_fields.html.erb
This page has been refactored. I have a feeling the error has something to do with this, but again I'm not sure.
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :passsword %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirm Password" %>
<%= f.password_field :password_confirmation %>
Here are the RSpec tests that keep failing:
describe "signup page" do
before { visit signup_path }
it { should have_content('Sign Up') }
it { should have_title(full_title('Sign up')) }
end
describe "signup" do
before { visit signup_path }
let(:submit) { "Create my account" }
describe "with valid information" do
before do
fill_in "Name", with: "Example User"
fill_in "Email", with: "user#example.com"
fill_in "Password", with: "foobar"
fill_in "Confirm Password", with: "foobar"
end
it "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
describe "after saving the user" do
before { click_button submit }
let(:user) { User.find_by(email: 'user#example.com') }
it { should have_link('Sign out') }
it { should have_title(user.name) }
it { should have_selector('div.alert.alert-success', text: 'Welcome') }
end
end
end
describe "edit" do
let(:user) { FactoryGirl.create(:user) }
before do
sign_in user
visit edit_user_path(user)
end
describe "with valid information" do
let(:new_name) { "New Name" }
let(:new_email) { "new#example.com" }
before do
fill_in "Name", with: new_name
fill_in "Email", with: new_email
fill_in "Password", with: user.password
fill_in "Confirm Password", with: user.password
click_button "Save changes"
end
it { should have_title(new_name) }
it { should have_selector('div.alert.alert-success') }
it { should have_link('Sign out', href: signout_path) }
specify { expect(user.reload.name).to eq new_name }
specify { expect(user.reload.email).to eq new_email }
end
end
Here are my failed tests:
Failures:
1) UserPages 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/requests/user_pages_spec.rb:85:in `block (4 levels) in <top (required)>'
2) UserPages signup with valid information after saving the user
Failure/Error: it { should have_link('Sign out') }
expected #has_link?("Sign out") to return true, got false
# ./spec/requests/user_pages_spec.rb:92:in `block (5 levels) in <top (required)>'
3) UserPages signup with valid information after saving the user
Failure/Error: it { should have_selector('div.alert.alert-success', text: 'Welcome') }
expected #has_selector?("div.alert.alert-success", {:text=>"Welcome"}) to return true, got false
# ./spec/requests/user_pages_spec.rb:94:in `block (5 levels) in <top (required)>'
4) UserPages signup with valid information after saving the user
Failure/Error: it { should have_title(user.name) }
NoMethodError:
undefined method `name' for nil:NilClass
# ./spec/requests/user_pages_spec.rb:93:in `block (5 levels) in <top (required)>'
> 5) UserPages edit with valid information
> Failure/Error: it { should have_selector('div.alert.alert-success') }
> expected #has_selector?("div.alert.alert-success") to return true, got false
> # ./spec/requests/user_pages_spec.rb:138:in `block (4 levels) in <top (required)>'
>
> 6) UserPages edit with valid information
> Failure/Error: specify { expect(user.reload.name).to eq new_name }
>
> expected: "New Name"
> got: "Person 65"
>
> (compared using ==)
> # ./spec/requests/user_pages_spec.rb:140:in `block (4 levels) in <top (required)>'
>
> 7) UserPages edit with valid information
> Failure/Error: it { should have_title(new_name) }
> expected #has_title?("New Name") to return true, got false
> # ./spec/requests/user_pages_spec.rb:137:in `block (4 levels) in <top (required)>'
>
> 8) UserPages edit with valid information
> Failure/Error: specify { expect(user.reload.email).to eq new_email }
>
> expected: "new#example.com"
> got: "person_64#example.com"
>
> (compared using ==)
> # ./spec/requests/user_pages_spec.rb:141:in `block (4 levels) in <top (required)>'
>
>Finished in 6.01 seconds
>88 examples, 8 failures
>
>Failed examples:
>
>rspec ./spec/requests/user_pages_spec.rb:84 # UserPages signup with valid information should >create a user
>rspec ./spec/requests/user_pages_spec.rb:93 # UserPages signup with valid information after >saving the user
>rspec ./spec/requests/user_pages_spec.rb:92 # UserPages signup with valid information after >saving the user
>rspec ./spec/requests/user_pages_spec.rb:94 # UserPages signup with valid information after >saving the user
>rspec ./spec/requests/user_pages_spec.rb:138 # UserPages edit with valid information
>rspec ./spec/requests/user_pages_spec.rb:140 # UserPages edit with valid information
>rspec ./spec/requests/user_pages_spec.rb:137 # UserPages edit with valid information
>rspec ./spec/requests/user_pages_spec.rb:141 # UserPages edit with valid information
>
>Randomized with seed 6990
Have a look at your _fields.html.erb
Change <%= f.label :passsword %> to <%= f.label :password %> (emphasis on the number of S's in "password".)
This is my first post here so hopefully I have followed the guide but if there is a better way to post, feel free to point me in the right direction - I learn fast.
I am new to rails and working through the Hartl Rails Tutorial. I searched google and here for the solution but can't seem to locate an answer to why the tests fail on click_button "Sign in".
I also went through the rails casts video Railscasts #270 Authentication
What am I missing so I can get these tests to pass? Any help would be greatly appreciated.
All the test pass if i use the form_for but fail when I use form_tag in .sessions/new.html.erb. The Sign_in page still renders correctly but once I try to sign in, the web page shows an error on:
def create
user = User.find_by(email: params[:session][:email].downcase)
Here is the exercise that I am trying to accomplish - Chapter 8, section 8.5, exercise 1:
8.5 Exercises
Refactor the signin form to use form_tag in place of form_for. Make
sure the test suite still passes. Hint: See the RailsCast on
authentication in Rails 3.1, and note in particular the change in
the structure of the params hash.
.sessions/new.html.erb
<% provide(:title, "Sign in") %>
<h1>Sign in</h1>
<div class="row">
<div class="span6 offset3">
<%= form_tag sessions_path do %>
<%= label_tag :email %>
<%= text_field :email, params[:email] %>
<%= label_tag :password %>
<%= password_field_tag :password %>
<%= submit_tag "Sign in", class: "btn btn-large btn-primary" %>
<% end %>
<!--
<%= form_for(:session, url: sessions_path) do |f| %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.submit "Sign in", class: "btn btn-large btn-primary" %>
<% end %>
-->
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>
</div>
This is the output of rspec spec/
> Failures:
1) Authentication signin with invalid information
Failure/Error: before { click_button "Sign in" }
NoMethodError:
undefined method `[]' for nil:NilClass
# ./app/controllers/sessions_controller.rb:7:in `create'
# ./spec/requests/authentication_pages_spec.rb:19:in `block (4 levels) in <top (required)>'
2) Authentication signin with invalid information
Failure/Error: before { click_button "Sign in" }
NoMethodError:
undefined method `[]' for nil:NilClass
# ./app/controllers/sessions_controller.rb:7:in `create'
# ./spec/requests/authentication_pages_spec.rb:19:in `block (4 levels) in <top (required)>'
3) Authentication signin with invalid information after visiting another page
Failure/Error: before { click_button "Sign in" }
NoMethodError:
undefined method `[]' for nil:NilClass
# ./app/controllers/sessions_controller.rb:7:in `create'
# ./spec/requests/authentication_pages_spec.rb:19:in `block (4 levels) in <top (required)>'
4) Authentication signin with valid information
Failure/Error: fill_in "Email", with: user.email.upcase
Capybara::ElementNotFound:
Unable to find field "Email"
# ./spec/requests/authentication_pages_spec.rb:41:in `block (4 levels) in <top (required)>'
5) Authentication signin with valid information
Failure/Error: fill_in "Email", with: user.email.upcase
Capybara::ElementNotFound:
Unable to find field "Email"
# ./spec/requests/authentication_pages_spec.rb:41:in `block (4 levels) in <top (required)>'
6) Authentication signin with valid information
Failure/Error: fill_in "Email", with: user.email.upcase
Capybara::ElementNotFound:
Unable to find field "Email"
# ./spec/requests/authentication_pages_spec.rb:41:in `block (4 levels) in <top (required)>'
7) Authentication signin with valid information
Failure/Error: fill_in "Email", with: user.email.upcase
Capybara::ElementNotFound:
Unable to find field "Email"
# ./spec/requests/authentication_pages_spec.rb:41:in `block (4 levels) in <top (required)>'
8) Authentication signin with valid information followed by signout
Failure/Error: fill_in "Email", with: user.email.upcase
Capybara::ElementNotFound:
Unable to find field "Email"
# ./spec/requests/authentication_pages_spec.rb:41:in `block (4 levels) in <top (required)>'
.....
./spec/requests/authentication_pages_spec.rb
require 'spec_helper'
describe "Authentication" do
subject { page }
describe "signin page" do
before { visit signin_path }
it { should have_content('Sign in') }
it { should have_title('Sign in') }
end
#Testing for sign in failure
describe "signin" do
before { visit signin_path }
describe "with invalid information" do
before { click_button "Sign in" }
it { should have_title('Sign in') }
# This uses Capabara have_selector method
# dot means "class" in CSS testing for div tag with classes "alert"
# and "alert-error" and the error message contains "invalid"
it { should have_selector('div.alert.alert-error', text: 'Invalid') }
describe "after visiting another page" do
before { click_link "Home" }
it { should_not have_selector('div.alert.alert-error') }
end
end
# Testing for sign success
describe "with valid information" do
# This is using FactoryGirl gem
let(:user) { FactoryGirl.create(:user) }
before do
fill_in "Email", with: user.email.upcase
fill_in "Password", with: user.password
click_button "Sign in"
end
# Uses Capybara's have_link method - takes arguments as text
# of the link and optional :href
it { should have_title(user.name) }
it { should have_link('Profile', href: user_path(user)) }
it { should have_link('Sign out', href: signout_path) }
it { should_not have_link('Sign in', href: signin_path) }
describe "followed by signout" do
before { click_link "Sign out" }
it { should have_link('Sign in') }
end
end
end
end
./app/controllers/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])
# Sign the user in and redirect to the user's show page.
sign_in user
redirect_to user
else
# Flash [:error] comes from bootstap CSS
flash.now[:error] = 'Invalid email/password combination'
# This line activates the link signin to show the page view new.html.erb
render 'new'
end
end
def destroy
sign_out
redirect_to root_url
end
end
this works for me
new.html.erb
<% provide(:title, "Sign in") %>
<h1>Sign in</h1>
<div class="row">
<div class="span6 offset3">
<%= form_tag sessions_path do %>
<%= label_tag :email %>
<%= text_field_tag :email %>
<%= label_tag :password %>
<%= password_field_tag :password %>
<%= submit_tag "Sign in", class: "btn btn-large btn-primary" %>
<% end %>
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>
</div>
sessions_controller.erb
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by(email: params[:email].downcase)
if user && user.authenticate(params[:password])
sign_in user
redirect_to user
else
flash.now[:error] = 'Invalid email/password combination'
render 'new'
end
end
def destroy
sign_out
redirect_to root_url
end
end
Please tell me if it works for you.
Thanks
In the exercise is mentioned that the structure of the params hash is changed. You need to edit this in the controller like following (this works in my case). It does not work currently because the params aren't accessible.
User.find_by_email(params[:email].downcase) and authenticate(params[:password]) are modified. If somebody can elaborate why this is feel free to do so.
An extract of my code you can find here:
def create
user = User.find_by_email(params[:email].downcase)
if user && user.authenticate(params[:password])
# Sign in the user and redirect to user show page
sign_in user
redirect_to user
else
flash.now[:error] = 'Invalid email/password combination'
render 'new'
end
end
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I'm new to Ruby on Rails and I'm following the tutorial by Michael Hartl. I started chapter 8 and can't figure out what step I missed to get failures. Any help is greatly appreciated.
Failures:
1) User pages signup with invalid information should not create a user
Failure/Error: expect { click_button submit }.not_to change(User, :count)
ActionView::Template::Error:
undefined method `errors' for nil:NilClass
# ./app/views/shared/_error_messages.html.erb:7:in `_app_views_shared__error_messages_html_erb___725910499_85961520'
# ./app/views/users/new.html.erb:7:in `block in _app_views_users_new_html_erb___744286408_86222100'
# ./app/views/users/new.html.erb:6:in `_app_views_users_new_html_erb___744286408_86222100'
# ./app/controllers/users_controller.rb:23:in `create'
# (eval):2:in `click_button'
# ./spec/requests/user_pages_spec.rb:30:in `block (5 levels) in <top (required)>'
# ./spec/requests/user_pages_spec.rb:30:in `block (4 levels) in <top (required)>'
2) User pages signup with invalid information after submission
Failure/Error: before { click_button submit }
ActionView::Template::Error:
undefined method `errors' for nil:NilClass
# ./app/views/shared/_error_messages.html.erb:7:in `_app_views_shared__error_messages_html_erb___725910499_85961520'
# ./app/views/users/new.html.erb:7:in `block in _app_views_users_new_html_erb___744286408_86222100'
# ./app/views/users/new.html.erb:6:in `_app_views_users_new_html_erb___744286408_86222100'
# ./app/controllers/users_controller.rb:23:in `create'
# (eval):2:in `click_button'
# ./spec/requests/user_pages_spec.rb:33:in `block (5 levels) in <top (required)>'
3) User pages signup with invalid information after submission
Failure/Error: before { click_button submit }
ActionView::Template::Error:
undefined method `errors' for nil:NilClass
# ./app/views/shared/_error_messages.html.erb:7:in `_app_views_shared__error_messages_html_erb___725910499_85961520'
# ./app/views/users/new.html.erb:7:in `block in _app_views_users_new_html_erb___744286408_86222100'
# ./app/views/users/new.html.erb:6:in `_app_views_users_new_html_erb___744286408_86222100'
# ./app/controllers/users_controller.rb:23:in `create'
# (eval):2:in `click_button'
# ./spec/requests/user_pages_spec.rb:33:in `block (5 levels) in <top (required)>'
users_controller.rb
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def new
#title = "Sign up"
#user = User.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user }
end
end
def create
#user = User.new(params[:user])
if #user.save
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
render 'new'
end
end
end
user_pages_spec.rb
require 'spec_helper'
describe "User pages" do
subject { page }
describe "signup page" do
before { visit signup_path }
it { should have_selector('h1', text: 'Sign up') }
it { should have_selector('title', text: full_title('Sign up')) }
end
describe "profile page" do
let(:user) { FactoryGirl.create(:user) }
before { visit user_path(user) }
it { should have_selector('h1', text: user.name) }
it { should have_selector('title', text: user.name) }
end
describe "signup" do
before { visit signup_path }
let(:submit) { "Create my account" }
describe "with invalid information" do
it "should not create a user" do
expect { click_button submit }.not_to change(User, :count)
end
describe "after submission" do
before { click_button submit }
it { should have_selector('title', text: 'Sign up') }
it { should have_content('error') }
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: "foobar"
fill_in "Confirmation", with: "foobar"
end
it "should create a user" do
expect { click_button submit}.to change(User, :count).by(1)
end
describe "after saving the user" do
before { click_button submit }
let(:user) { User.find_by_email('user#example.com') }
it { should have_selector('title', text: user.name) }
it { should have_selector('div.alert.alert-success', text: 'Welcome') }
end
end
end
end
app/views/shared/_error_messages.html.erb
<% if #user.errors.any? %>
<div id="error_explanation">
<div class="alert alert-error">
The form contains <%= pluralize(#user.errors.count, "error")%>
</div>
<ul>
<% #users.errors.full_messages.each do |msg| %>
<li>* <%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
Instead of #users in your _error_messages.html.erb, which is nil, you should have #user.
<% #user.errors.full_messages.each do |msg| %>
<li>* <%= msg %></li>
<% end %>
I have been following the guide for a while now and unfortunately have been stuck getting these tests to pass. Thank you for your time because I have given up looking for what is wrong and am desperate for any help.
Failures:
1) signup with valid information after saving user
Failure/Error: it {should have_link('Sign out')}
expected link "Sign out" to return something
# ./spec/requests/user_pages_spec.rb:97:in `block (4 levels) in <top (required)>'
2) signup with valid information after saving user
Failure/Error: it { should have_selector('div.alert.alert-success', text: 'Welcome') }
expected css "div.alert.alert-success" with text "Welcome" to return something
# ./spec/requests/user_pages_spec.rb:96:in `block (4 levels) in <top (required)>'
3) signup with valid information after saving user
Failure/Error: it { should have_selector('title', text: user.name) }
expected css "title" with text "Example User" to return something
# ./spec/requests/user_pages_spec.rb:95:in `block (4 levels) in <top (required)>'
4) create user page
Failure/Error: it {should have_selector('h1', text: 'Creating New User')}
expected css "h1" with text "Creating New User" to return something
# ./spec/requests/user_pages_spec.rb:56:in `block (2 levels) in <top (required)>'
5) create user page
Failure/Error: it {should have_selector('title', text: 'Sign Up')}
expected css "title" with text "Sign Up" to return something
# ./spec/requests/user_pages_spec.rb:57:in `block (2 levels) in <top (required)>'
6) edit with valid information
Failure/Error: it { should have_selector('div.alert.alert-success') }
expected css "div.alert.alert-success" to return something
# ./spec/requests/user_pages_spec.rb:132:in `block (3 levels) in <top (required)>'
7) edit with valid information
Failure/Error: it { should have_selector('title', text: new_name) }
expected css "title" with text "New Name" to return something
# ./spec/requests/user_pages_spec.rb:131:in `block (3 levels) in <top (required)>'
8) edit with valid information
Failure/Error: it { should have_link('Sign out', href: signout_path) }
expected link "Sign out" to return something
# ./spec/requests/user_pages_spec.rb:133:in `block (3 levels) in <top (required)>'
9) edit with invalid info
Failure/Error: it {should have_content('error')}
expected there to be content "error" in "with invalid info"
# ./spec/requests/user_pages_spec.rb:117:in `block (3 levels) in <top (required)>'
10) edit page
Failure/Error: it { should have_selector('h1', text: "Update your profile") }
expected css "h1" with text "Update your profile" to return something
# ./spec/requests/user_pages_spec.rb:111:in `block (3 levels) in <top (required)>'
11) edit page
Failure/Error: it { should have_selector('title', text: "Edit user") }
expected css "title" with text "Edit user" to return something
# ./spec/requests/user_pages_spec.rb:112:in `block (3 levels) in <top (required)>'
12) profile page
Failure/Error: it{should have_selector('h2', text: user.name)}
expected css "h2" with text "Person 66" to return something
# ./spec/requests/user_pages_spec.rb:63:in `block (2 levels) in <top (required)>'
13) profile page
Failure/Error: it{should have_selector('title', text: user.name)}
expected css "title" with text "Person 67" to return something
# ./spec/requests/user_pages_spec.rb:64:in `block (2 levels) in <top (required)>'
My User Pages Spec
require 'spec_helper'
describe "UserPages" do
subject {page}
describe "index" do
before do
sign_in FactoryGirl.create(:user)
FactoryGirl.create(:user, name: "Bob", email: "bob#example.com")
FactoryGirl.create(:user, name: "Ben", email: "ben#example.com")
visit users_path
end
it { should have_selector('title', text: 'All users') }
it { should have_selector('h1', text: 'All Users') }
describe "pagination" do
before(:all) {30.times {FactoryGirl.create(:user)}}
after(:all) {User.delete_all}
it {should have_selector('div.pagination')}
describe "delete links" do
it { should_not have_link('delete') }
describe "as an admin user" do
let(:admin) { FactoryGirl.create(:admin) }
before do
sign_in admin
visit users_path
end
it { should have_link('delete', href: user_path(User.first)) }
it "should be able to delete another user" do
expect { click_link('delete') }.to change(User, :count).by(-1)
end
it { should_not have_link('delete', href: user_path(admin)) }
end
end
end
it "should list each user" do
User.all.each do |user|
page.should have_selector('li', text: user.name)
end
end
end
end
describe "create user page" do
before {visit new_user_path}
it {should have_selector('h1', text: 'Creating New User')}
it {should have_selector('title', text: 'Sign Up')}
end
describe "profile page" do
let(:user){FactoryGirl.create(:user)}
before {visit user_path(user)}
it{should have_selector('h2', text: user.name)}
it{should have_selector('title', text: user.name)}
end
describe "signup" do
before { visit new_user_path }
let(:submit) { "Create my account" }
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 "Name", with: "Example User"
fill_in "Email", with: "user#example.com"
fill_in "Password", with: "foobar"
choose("user_admin_true")
fill_in "Confirmation", with: "foobar"
end
it "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
describe "after saving user" do
before {click_button submit}
let(:user) { User.find_by_email('user#example.com') }
it { should have_selector('title', text: user.name) }
it { should have_selector('div.alert.alert-success', text: 'Welcome') }
it { should have_link('Sign out')}
end
end
end
describe "edit" do
let(:user) {FactoryGirl.create(:user)}
before do
sign_in user
visit edit_user_path(user)
end
describe "page" do
it { should have_selector('h1', text: "Update your profile") }
it { should have_selector('title', text: "Edit user") }
end
describe "with invalid info" do
before {click_button "Save changes"}
it {should have_content('error')}
end
describe "with valid information" do
let(:new_name) { "New Name" }
let(:new_email) { "new#example.com" }
before do
fill_in "Name", with: new_name
fill_in "Email", with: new_email
fill_in "Password", with: user.password
fill_in "Confirm Password", with: user.password
click_button "Save changes"
end
it { should have_selector('title', text: new_name) }
it { should have_selector('div.alert.alert-success') }
it { should have_link('Sign out', href: signout_path) }
specify { user.reload.name.should == new_name }
specify { user.reload.email.should == new_email }
end
end
Users Controller
class UsersController < ApplicationController
before_filter :signed_in_user, only: [:index, :edit, :update, :destroy]
before_filter :correct_user, only: [:edit, :update]
before_filter :admin_user, only: :destroy
def index
#users = User.paginate(page: params[:page])
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Account creation succesful. Welcome to the CeFam Online Database"
redirect_to #user
else
render 'new'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User removed."
redirect_to users_url
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
flash[:success] = "Profile updated"
sign_in #user
redirect_to #user
else
render 'edit'
end
end
private
def admin_user
redirect_to(root_path) unless current_user.admin?
end
def signed_in_user
flash[:notice] = "Please sign in." unless signed_in?
redirect_to signin_url unless signed_in?
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_path) unless current_user?(#user)
end
end
Header
<header class="navbar navbar-fixed-top navbar-inverse">
<div class="navbar-inner">
<div class="container">
<%= link_to "Image Home Logo", '#', id: "logo" %>
<nav>
<ul class="nav pull-right">
<li><%= link_to "Home", root_path %></li>
<li><%= link_to "Help", help_path %></li>
<!--Visibile only when signed in-->
<% if signed_in? %>
<li><%= link_to "List users", users_path %></li>
<li><%= link_to "Search", '#' %></li>
<li><%= link_to "Add Entry", '#' %></li>
<li id="fat-menu" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Account <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><%= link_to "Profile", current_user %></li>
<li><%= link_to "Settings", edit_user_path(current_user) %></li>
<li class="divider"></li>
<li><%= link_to "Sign out", signout_path, method: "delete" %>
</li>
<%else%>
<li><%= link_to "Sign in", signin_path %></li>
<%end%>
</ul>
</nav>
</div>
</div>
</header>
User's show.html.erb
<% provide(:title,#user.name) %>
<h1> User Profile </h1>
<h2><%=#user.name%><br>
<%= #user.email %><br>
Administrator: <%= #user.admin%>
</h2>
User's new.html.erb
<% provide(:title,'Sign Up')%>
<h1>Creating New User</h1>
<div class="row">
<div class="span4 offset4">
<%= form_for(#user) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :admin %>
<%= f.radio_button :admin, "true"%> Yes <br>
<%= f.radio_button :admin, "false"%> No<br><br>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<br>
<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
Here's the source of at least one of your problems, look at your user_pages_spec.rb:
it "should list each user" do
User.all.each do |user|
page.should have_selector('li', text: user.name)
end
end
You want to test for User.paginate not User.all (because Capybara has no way of seeing past the default 30 rendered on a single paginated view). It's explained in the tutorial that testing for one page should suffice since the will_paginate gem is pretty well-tested already.
So replace that block with this, and your pagination tests should pass:
it 'should list each user' do
User.paginate(page: 1).each do |user|
page.should have_selector('li', text: user.name)
end
end
I'm getting the following error when testing the sign up page for the ruby-on-rails tutorial:
Failures:
1) User pages signup with valid information should create a user
Failure/Error: expect { click_button submit }.to change(User, :count).by(1)
ActionView::MissingTemplate:
Missing template users/create, application/create with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee]}. Searched in:
* "/Users/Fif/rails_projects/sample_app/app/views"
# (eval):2:in `click_button'
# ./spec/requests/user_pages_spec.rb:43:in `block (5 levels) in <top (required)>'
# ./spec/requests/user_pages_spec.rb:43:in `block (4 levels) in <top (required)>'
Finished in 0.76918 seconds
35 examples, 1 failure
Failed examples:
rspec ./spec/requests/user_pages_spec.rb:42 # User pages signup with valid information should create a user
I'm not sure what the problem is, and I've gone over the code several times to make sure that it matches the examples in the book. I'm pretty sure that it has to do with the new.html.erb file
user_pages_spec.rb
require 'spec_helper'
describe "User pages" do
subject { page }
describe "signup page" do
before { visit signup_path }
it { should have_selector('h1', text: 'Sign up') }
it { should have_selector('title', text: full_title('Sign up')) }
end
describe "profile page" do
let(:user) { FactoryGirl.create(:user) }
before { visit user_path(user) }
it { should have_selector('h1', text: user.name) }
it { should have_selector('title', text: user.name) }
end
describe "signup" do
before { visit signup_path }
let(:submit) { "Create my account" }
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 "Name", with: "Example User"
fill_in "Email", with: "user#example.com"
fill_in "Password", with: "foobar"
fill_in "Confirmation", with: "foobar"
end
it "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
end
end
end
new.html.erb
<%= provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(#user) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
users_controller.rb
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
# Handle a successful save.
else
render 'new'
end
end
end
Short Answer:
It is not supposed to work (yet).
Continue the tutorial, the answer will come in section 7.4;
Slightly longer Answer:
When you fill in the form and push the submit-button, the create-event in the users_controller gets triggered. Since you don't have any code there (yet), Rails assumes that you just want to render create.html.erb, which doesn't exist (and never will).
In order to get this to work immediately, you have to add redirect_to #user right underneath if #user.save. Check Listing 7.25;
Jump down to the bottom of the tutorial and the question is answered. Include redirect_to #user right under your #Handle a successful save.