Trying to complete exercise 1, Chapter 8, section 8.5 - ruby-on-rails

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

Related

bad URI(is not URI?) while testing | Rspec

I`ve got these strange issues I dont know how to fix it. Please help me if you can.
Here is a testing result:
1) Admin can edit a hotel
Failure/Error: visit edit_admin_hotel_path(hotel)
URI::InvalidURIError:
bad URI(is not URI?):
# ./spec/requests/admin_spec.rb:32:in `block (2 levels) in <top (required)>'
2) Admin can edit a user
Failure/Error: visit edit_admin_user_path(admin)
URI::InvalidURIError:
bad URI(is not URI?):
# ./spec/requests/admin_spec.rb:54:in `block (2 levels) in <top (required)>'
rake routes shows me nice edit routes for users and hotels:
edit_admin_hotel GET /admin/hotels/:id/edit(.:format) admin/hotels#edit
edit_admin_user GET /admin/users/:id/edit(.:format) admin/users#edit
And everything works just fine if I start server and check it manually. So I have no idea where these issues comes from. Thanks for any help!
And my admin_spec.rb file:
require 'spec_helper'
describe "Admin" do
let(:admin) { FactoryGirl.create(:user) }
let(:hotel) { FactoryGirl.create(:hotel) }
before(:each) do
sign_up_as_admin admin
visit admin_hotels_path
end
subject { page }
it { expect(page).to have_content("Manage Hotels") }
it { expect(page).to have_content("Manage Users") }
it { expect(page).to have_link("Sign out") }
it { expect(page).to have_content("List of hotels") }
it { expect(page).to have_content("Hello, Admin") }
it "can add a hotel" do
click_link "Add Hotel"
expect(current_path).to eq(new_admin_hotel_path)
fill_in 'name', with: "TestHotel"
fill_in 'price', with: "666"
fill_in 'star_rating', with: "5"
expect { click_button "Submit" }.to change(Hotel,:count).by(1)
expect(current_path).to eq(admin_hotel_path(1))
end
it "can edit a hotel" do
visit edit_admin_hotel_path(hotel)
end
it "can delete a hotel" do
visit admin_hotel_path(hotel)
expect { click_link "Delete hotel" }.to change(Hotel,:count).by(-1)
#expect { click_link "Delete hotel" }.to redirect_to(admin_hotels_path)
end
it "can create a new user" do
click_link "Add User"
expect(current_path).to eq(new_admin_user_path)
expect(page).to have_content("Create New User")
fill_in "Name", :with => "user"
fill_in "Email", :with => "user#auser.com"
fill_in "Password", :with => "user.password"
fill_in "password_confirmation", :with => "user.password"
expect { click_button "Create User" }.to change(User,:count).by(1)
expect(current_path).to eq(admin_users_path)
end
it "can edit a user" do
visit edit_admin_user_path(admin)
end
end
Edit/update actions in users_controller.rb:
# GET admin/users/1/edit
def edit
#user = User.find(params[:id])
render "edit", status: 302
end
# PATCH/PUT admin/users/1
def update
#user = User.find(params[:id])
if #user.try(:update_attributes, user_params)
render "edit", notice: 'User was successfully updated.'
else
render action: 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation, :admin)
end
And user/edit.html.erb:
<% provide(:title, "Edit user") %>
<h1>Update profile</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for([:admin, #user]) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= 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" %>
<% end %>
<%= button_to 'Delete User', [:admin, #user], :data => { confirm: 'Are you sure?' }, method: :delete %>
</div>
</div>
Update 1:
I found out that these bad URI(is not URI?) errors also in hotel_controller and comment_controller while testing edit action. These errors in all of my controllers in edit actions and I dont know what cousing them :(
Your edit action is wrong:
def edit
#user = User.find(params[:id])
render "edit", status: 302
end
A 302 status means that the response is a redirect and that the Location header in the response contains the URI (relative or absolute) to redirect to. Capybara will be looking for this header and probably winds up trying to do URI.parse(nil).
It's not clear to me why you are setting the status here at all
In your spec_helper have you included the url_helpers?
config.include Rails.application.routes.url_helpers

Having trouble with Rails Tutorial 9.6.5, can't get tests to pass

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".)

Rspec - Unable to find field "Name", Unable to find button "Create my account"

I ran rspec on some tests I created and here is the output I received.
Failures:
1) User pages signup with valid information should create a user
Failure/Error: fill_in "Name", with: "Example User"
Capybara::ElementNotFound:
Unable to find field "Name"
# ./spec/requests/user_pages_spec.rb:18:in `block (4 levels) in <top (required)>'
2) User pages signup with invalid information should not create a user
Failure/Error: expect { click_button submit }.not_to change(User, :count)
Capybara::ElementNotFound:
Unable to find button "Create my account"
# ./spec/requests/user_pages_spec.rb:12:in `block (5 levels) in <top (required)>'
# ./spec/requests/user_pages_spec.rb:12:in `block (4 levels) in <top (required)>'
Here is my rspec code for user_pages_spec.rb
require 'spec_helper'
describe "User pages" do
subject { page }
describe "signup" do
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
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) }
end
describe "signup page" do
before { visit signup_path }
it { should have_content('Sign up') }
it { should have_title(full_title('Sign up')) }
end
end
Now, to show you my html page
<% 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.text_field :password %>
<%= f.label :password_confirmation %>
<%= f.text_field :password_confirmation %>
<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
In this example, clearly you can find a text-field named "Name" and a button "Create my account". I'm baffled at how rspec saw errors.
Can anyone help me?
Edit: Maybe it didn't work because I haven't defined a create method in my UsersController
class UsersController < ApplicationController
def new
#user = User.new
end
def show
#user = User.find(params[:id])
end
end
You are not actually going to any page before you start trying to fill in the form.
At the beginning of the test you will need a visit statement. Something like:
describe "User pages" do
subject { page }
describe "signup" do
before { visit new_user_path }
...

Rspec errors following Hartl's rails guide

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

Hartl Ruby-on-Rails Tutorial (3.2), Section 7.2 - Sign up form missing template

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.

Resources