2011-10-30 14 views
9

Acabo de terminar chapter 10 of the Ruby on Rails Tutorial, agregando la capacidad de editar/actualizar, indexar y destruir usuarios. Parece que todo funciona correctamente en mi aplicación, pero muchas de mis pruebas fallan cuando ejecuto RSpec.¿Por qué fallan mis pruebas de RSpec, pero mi aplicación está funcionando?

Tengo el users_controller_spec configurado exactamente como lo hace el libro y el código de mi aplicación es el mismo también. ¿Podría ser que un problema sea que estoy usando Rails 3.1.1 en lugar de Rails 3.0 que usa en el libro? Realmente no ha sido un problema para las pruebas anteriores, solo ocasionalmente para algunas líneas de código diferentes. Los problemas comenzaron a aparecer después de que comencé section 10.2.1.

Aquí está la lista de errores que estoy viendo y hágamelo saber si necesita más información. ¡Gracias!

1) UsersController GET 'index' for signed-in users should be successful 
Failure/Error: response.should be_success 
    expected success? to return true, got false 
# ./spec/controllers/users_controller_spec.rb:31:in `block (4 levels) in <top (required)>' 

2) UsersController GET 'index' for signed-in users should have the right title 
Failure/Error: response.should have_selector("title", :content => "All users") 
    expected following output to contain a <title>All users</title> tag: 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
    <html><body>You are being <a href="http://test.host/signin">redirected</a>.</body></html> 
# ./spec/controllers/users_controller_spec.rb:36:in `block (4 levels) in <top (required)>' 

3) UsersController GET 'index' for signed-in users should have an element for each user 
Failure/Error: response.should have_selector("li", :content => user.name) 
    expected following output to contain a <li>Richard Berger</li> tag: 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
    <html><body>You are being <a href="http://test.host/signin">redirected</a>.</body></html> 
# ./spec/controllers/users_controller_spec.rb:42:in `block (5 levels) in <top (required)>' 
# ./spec/controllers/users_controller_spec.rb:41:in `each' 
# ./spec/controllers/users_controller_spec.rb:41:in `block (4 levels) in <top (required)>' 

4) UsersController GET 'index' for signed-in users should paginate users 
Failure/Error: response.should have_selector("div.pagination") 
    expected following output to contain a <div.pagination/> tag: 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
    <html><body>You are being <a href="http://test.host/signin">redirected</a>.</body></html> 
# ./spec/controllers/users_controller_spec.rb:48:in `block (4 levels) in <top (required)>' 

5) UsersController GET 'edit' should be successful 
Failure/Error: response.should be_success 
    expected success? to return true, got false 
# ./spec/controllers/users_controller_spec.rb:184:in `block (3 levels) in <top (required)>' 

6) UsersController GET 'edit' should have the right title 
Failure/Error: response.should have_selector("title", :content => "Edit user") 
    expected following output to contain a <title>Edit user</title> tag: 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
    <html><body>You are being <a href="http://test.host/signin">redirected</a>.</body></html> 
# ./spec/controllers/users_controller_spec.rb:189:in `block (3 levels) in <top (required)>' 

7) UsersController GET 'edit' should have a link to change the Gravatar 
Failure/Error: response.should have_selector("a", :href => gravatar_url, :content => "change") 
    expected following output to contain a <a href='http://gravatar.com/emails'>change</a> tag: 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
    <html><body>You are being <a href="http://test.host/signin">redirected</a>.</body></html> 
# ./spec/controllers/users_controller_spec.rb:195:in `block (3 levels) in <top (required)>' 

8) UsersController PUT 'update' failure should render the 'edit' page 
Failure/Error: response.should render_template('edit') 
    expecting <"edit"> but rendering with <""> 
# ./spec/controllers/users_controller_spec.rb:214:in `block (4 levels) in <top (required)>' 

9) UsersController PUT 'update' failure should have the right title 
Failure/Error: response.should have_selector("title", :content => "Edit user") 
    expected following output to contain a <title>Edit user</title> tag: 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
    <html><body>You are being <a href="http://test.host/signin">redirected</a>.</body></html> 
# ./spec/controllers/users_controller_spec.rb:219:in `block (4 levels) in <top (required)>' 

10) UsersController PUT 'update' success should change the user's attributes 
Failure/Error: @user.name.should == @attr[:name] 
    expected: "New Name" 
     got: "Richard Berger" (using ==) 
# ./spec/controllers/users_controller_spec.rb:232:in `block (4 levels) in <top (required)>' 

11) UsersController PUT 'update' success should redirect to the user show page 
Failure/Error: response.should redirect_to(user_path(@user)) 
    Expected response to be a redirect to <http://test.host/users/1> but was a redirect to <http://test.host/signin> 
# ./spec/controllers/users_controller_spec.rb:238:in `block (4 levels) in <top (required)>' 

12) UsersController PUT 'update' success should have a flash message 
Failure/Error: flash[:success].should =~ /updated/ 
    expected: /updated/ 
     got: nil (using =~) 
# ./spec/controllers/users_controller_spec.rb:243:in `block (4 levels) in <top (required)>' 

13) UsersController authentication of edit/update pages for signed-in users should require matching users for 'edit' 
Failure/Error: response.should redirect_to(root_path) 
    Expected response to be a redirect to <http://test.host/> but was a redirect to <http://test.host/signin> 
# ./spec/controllers/users_controller_spec.rb:276:in `block (4 levels) in <top (required)>' 

14) UsersController authentication of edit/update pages for signed-in users should require matching users for 'update' 
Failure/Error: response.should redirect_to(root_path) 
    Expected response to be a redirect to <http://test.host/> but was a redirect to <http://test.host/signin> 
# ./spec/controllers/users_controller_spec.rb:281:in `block (4 levels) in <top (required)>' 

15) UsersController DELETE 'destroy' as a non-admin user should protect the page 
Failure/Error: response.should redirect_to(root_path) 
    Expected response to be a redirect to <http://test.host/> but was a redirect to <http://test.host/signin> 
# ./spec/controllers/users_controller_spec.rb:303:in `block (4 levels) in <top (required)>' 

16) UsersController DELETE 'destroy' as an admin user should destroy the user 
Failure/Error: lambda do 
    count should have been changed by -1, but was changed by 0 
# ./spec/controllers/users_controller_spec.rb:315:in `block (4 levels) in <top (required)>' 

17) UsersController DELETE 'destroy' as an admin user should redirect to the users page 
Failure/Error: response.should redirect_to(users_path) 
    Expected response to be a redirect to <http://test.host/users> but was a redirect to <http://test.host/signin> 
# ./spec/controllers/users_controller_spec.rb:322:in `block (4 levels) in <top (required)>' 

ACTUALIZACIÓN:

que resuelve 2 de los errores, pero la mayoría todavía persisten. Parece que un problema es que cuando la prueba intenta "obtener: índice", no encuentra la página correcta debido a una redirección (a la página de inicio de sesión). No instituí ningún redireccionamiento (a propósito de todos modos), pero tal vez alguien tiene una idea de cómo pudo haber sucedido y cómo podría solucionarse.

ACTUALIZACIÓN # 2:

Por la petición de @ bkempner, aquí está el código correspondiente de la users_controller_spec y la users_controller (users_controller_spec primero). Gran cantidad de código, pero muchos errores ...:

describe "for signed-in users" do 

    before(:each) do 
    @user = test_sign_in(Factory(:user)) 
    second = Factory(:user, :email => "[email protected]") 
    third = Factory(:user, :email => "[email protected]") 

    @users = [@user, second, third] 
    30.times do 
     @users << Factory(:user, :email => Factory.next(:email)) 
    end 
    end 

    it "should be successful" do 
    get :index 
    response.should be_success 
    end 

    it "should have the right title" do 
    get :index 
    response.should have_selector("title", :content => "All users") 
    end 

    it "should have an element for each user" do 
    get :index 
    @users[0..2].each do |user| 
     response.should have_selector("li", :content => user.name) 
    end 
    end 

    it "should paginate users" do 
    get :index 
    response.should have_selector("div.pagination") 
    response.should have_selector("span.diabled", :content => "Previous") 
    response.should have_selector("a", :href => "/users?page=2", :content => "2") 
    response.should have_selector("a", :href => "/users?page=2", :content => "Next") 
    end 
end 

describe "GET 'edit'" do 

    before(:each) do 
    @user = Factory(:user) 
    test_sign_in(@user) 
    end 

    it "should be successful" do 
    get :edit, :id => @user 
    response.should be_success 
    end 

    it "should have the right title" do 
    get :edit, :id => @user 
    response.should have_selector("title", :content => "Edit user") 
    end 

    it "should have a link to change the Gravatar" do 
    get :edit, :id => @user 
    gravatar_url = "http://gravatar.com/emails" 
    response.should have_selector("a", :href => gravatar_url, :content => "change") 
    end 
end 

describe "PUT 'update'" do 

    before(:each) do 
    @user = Factory(:user) 
    test_sign_in(@user) 
    end 

    describe "failure" do 

    before(:each) do 
     @attr = { :email => "", :name => "", :password => "", :password_confirmation => "" } 
    end 

    it "should render the 'edit' page" do 
     put :update, :id => @user, :user => @attr 
     response.should render_template('edit') 
    end 

    it "should have the right title" do 
     put :update, :id => @user, :user => @attr 
     response.should have_selector("title", :content => "Edit user") 
    end 
    end 

    describe "success" do 

    before(:each) do 
     @attr = { :name => "New Name", :email => "[email protected]", :password => "barbaz", :password_confirmation => "barbaz" } 
    end 

    it "should change the user's attributes" do 
     put :update, :id => @user, :user => @attr 
     @user.reload 
     @user.name.should == @attr[:name] 
     @user.email.should == @attr[:email] 
    end 

    it "should redirect to the user show page" do 
     put :update, :id => @user, :user => @attr 
     response.should redirect_to(user_path(@user)) 
    end 

    it "should have a flash message" do 
     put :update, :id => @user, :user => @attr 
     flash[:success].should =~ /updated/ 
    end 
    end 
end 

describe "authentication of edit/update pages" do 

    describe "for signed-in users" do 

    before(:each) do 
     wrong_user = Factory(:user, :email => "[email protected]") 
     test_sign_in(wrong_user) 
    end 

    it "should require matching users for 'edit'" do 
     get :edit, :id => @user 
     response.should redirect_to(root_path) 
    end 

    it "should require matching users for 'update'" do 
     get :update, :id => @user, :user => {} 
     response.should redirect_to(root_path) 
    end 
    end 
end 

describe "DELETE 'destroy'" do 

    before(:each) do 
    @user = Factory(:user) 
    end 

    describe "as a non-admin user" do 
    it "should protect the page" do 
     test_sign_in(@user) 
     delete :destroy, :id => @user 
     response.should redirect_to(root_path) 
    end 
    end 

    describe "as an admin user" do 

    before(:each) do 
     admin = Factory(:user, :email => "[email protected]", :admin => true) 
     test_sign_in(admin) 
    end 

    it "should destroy the user" do 
     lambda do 
     delete :destroy, :id => @user 
     end.should change(User, :count).by(-1) 
    end 

    it "should redirect to the users page" do 
     delete :destroy, :id => @user 
     response.should redirect_to(users_path) 
    end 
    end 
end 

Y ahora todo el users_controller:

class UsersController < ApplicationController 
before_filter :authenticate, :only => [:index, :edit, :update, :destroy] 
before_filter :correct_user, :only => [:edit, :update] 
before_filter :admin_user, :only => :destroy 

def index 
    @title = "All users" 
    @users = User.paginate(:page => params[:page]) 
end 

def show 
    @user = User.find(params[:id]) 
    @title = @user.name 
end 

def new 
    @user = User.new 
    @title = "Sign up" 
end 

def create 
    @user = User.new(params[:user]) 
    if @user.save 
    sign_in @user 
    flash[:success] = "Welcome to the Sample App!" 
    redirect_to @user 
    else 
    @title = "Sign up" 
    render 'new' 
    end 
end 

def edit 
    @title = "Edit user" 
end 

def update 
    @user = User.find(params[:id]) 
    if @user.update_attributes(params[:user]) 
    flash[:success] = "Profile updated" 
    redirect_to @user 
    else 
    @title = "Edit user" 
    render 'edit' 
    end 
end 

def destroy 
    User.find(params[:id]).destroy 
    flash[:success] = "User destroyed." 
    redirect_to users_path 
end 

private 

    def authenticate 
    deny_access unless signed_in? 
    end 

    def correct_user 
    @user = User.find(params[:id]) 
    redirect_to(root_path) unless current_user?(@user) 
    end 

    def admin_user 
    redirect_to(root_path) unless current_user.admin? 
    end 
end 
+0

¿Lo resolvió? Has editado lat hace 20 días y acabo de empezar a portar a 3.1 y tener el mismo problema. –

Respuesta

1

Tuve el mismo problema y encontré la respuesta publicada here.

básicamente RSPEC necesita @current_user y el usuario actual para ser configurado para sign_in y sign_out. Raro y molesto, pero tal vez la razón por la que uno podría considerar el uso de Devise en una aplicación de producción.

+0

así que esto parece haber solucionado mi problema, aunque todavía no estoy totalmente seguro de por qué. ¡gracias por la ayuda! – RBergs

0

Proporcionar a su controlador y el código de prueba sería de gran ayuda. Pero sin ellos mi conjetura sería que se echa en falta esta en el bloque antes de las pruebas fallan:

@user = Factory(:user) 
test_sign_in(@user) 

La redirección está sucediendo debido a cualquier lógica de autorización está siendo utilizado en el tutorial, creo que se detalla en 10.11 y 10.12.

Este es un problema común que veo en las pruebas de controlador con auth, con suerte eso es todo lo que es para ti también.

EDIT:

Gracias por proporcionar su código.

He aquí algunas cosas que noté:

1.) fallas 1-14, 19 se deben a la autenticación de usuario no está trabajando, específicamente signed_in ?. ¿Pasan las pruebas de tu controlador de sesión? Definitivamente debe asegurarse de que los pase antes de probar el controlador de los usuarios, ya que depende de esa funcionalidad.

2.) Los fracasos son 15-18, ya que probablemente no creó la migración para añadir el atributo booleano en el listado 10.35 -o- necesita ejecutar la migración de su base de datos de prueba: rake db:test:prepare

Lo sentimos i no pudo identificar todos sus problemas pero, afortunadamente, le da un paso en la dirección correcta.

+0

Gracias por la respuesta, pero desafortunadamente no creo que ese sea el problema. Voy a agregar mi controlador y código de prueba a la publicación principal ahora para verificarlo. – RBergs

+0

hmm, gracias por seguir con el problema. todas las pruebas de mi controlador de sesión están pasando, así que no pienses que ese es el problema. también estoy bastante seguro de que migré el atributo y la base de datos. Acabo de actualizar la lista de errores también porque hubo un par de cambios menores. todavía no sé lo que está mal, por desgracia! – RBergs

0

Compruebe que deny_access en SessionsHelper se define antes del bloque private.

El libro tiene un error tipográfico que implica que debe poner deny_access al final del módulo. Lamentablemente, esto significa que la función se define como privada.

module SessionsHelper 
    . 
    . 
    . 
    def deny_access 
    redirect_to signin_path, :notice => "Please sign in to access this page." 
    end 
end 

El código corregido en el sitio web es Railstutorial.org a continuación:

module SessionsHelper 
    . 
    . 
    . 
    def deny_access 
    redirect_to signin_path, :notice => "Please sign in to access this page." 
    end 

    private 
    . 
    . 
    . 
end 
+0

gracias por la sugerencia, pero ya tengo el deny_access en la ubicación correcta. – RBergs

0

que tenían el mismo problema y el uso de los carriles 3.1.3. Esta es mi solución.

En primer lugar, asegúrese de que ambos:

def current_user=(user) 
    @current_user = user 
end 

def current_user 
    @current_user ||= user_from_remember_token 
end 

están en sessions_helper.rb

Además, en cambio sessions_helper.rb:

def sign_out 
    cookies.delete(:remember_token) 
    current_user.nil 
end 

a

def sign_out 
    cookies.delete(:remember_token) 
    self.current_user.nil 
end 

Uno mas cosas.

En cambio spec_helper.rb:

def test_sign_in(user) 
    controller.sign_in(user) 
end 

a

def test_sign_in(user) 
    controller.current_user = user 
end 

ver si eso ayuda, no he terminado el capítulo, pero esto me consigue a través 10.2.1. Alguien con más experiencia puede comentar en por qué esto funciona. Leí otra solución que escribió en torno a before_filter para que rspec pase.

0

¿Tiene render_views llamada después del nivel superior describe en el users_controller_spec?

+0

sí, gracias por la sugerencia – RBergs

0

Hoy me encontré con este problema con los rieles 3.1.3. Sin embargo, fui al sitio github para la aplicación de muestra railstutorial y noté que sessions_helper.erb tenía algunos cambios.

1.) Añadir el 'yo' palabra clave para 'current_user' en el método sign_in (usuario):

def sign_in(user) 
    cookies.permanent.signed[:remember_token] = [user.id, user.salt] 
    self.current_user = user 
end 

2.) Esto también va para el método 'sign_out', añadir el 'auto 'keyword to' current_user '

def sign_out 
    cookies.delete(:remember_token) 
    self.current_user = nil 
end 

No realicé más cambios y pasaron todas las pruebas.

+0

interesante, así que no estoy seguro de por qué, pero la adición de uno mismo no funcionó, al agregar una segunda línea que se refiere a @current_user (como [referenciado aquí] (http://stackoverflow.com/questions)/6821692/cookies-do-not-persist-in-rspec-on-rails-3-1)) funcionó ... – RBergs

Cuestiones relacionadas