2012-04-10 14 views
1

ich auf das Vorhandensein eines Links mich entschieden, die von CanCan kontrolliert wird:Haben Sie Probleme beim Testen CanCan Ansichten mit RSpec

before do 
    @author = Fabricate(:author) 
    visit new_user_session_path 
    fill_in 'Email', :with => @author.email 
    fill_in 'Password', :with => @author.password 
    click_button 'Sign in' 
    visit articles_path 
end 

it { should have_link 'New article', :href => new_article_path } 

Dies ist der Ansicht ist, dass es Tests ist:

<% if can? :create, @articles %> 
    <%= link_to 'New article', new_article_path %> 
<% end %> 

Als ich das laufen Test, schlägt es fehl und erzeugt diesen Fehler:

Failure/Error: it { should have_link 'New article', :href => new_article_path }

expected link "New article" to return something 

Das ist komisch, weil es funktioniert, wenn ich es manuell in m teste y Browser. Hier ist die Fähigkeit Klasse:

class Ability 
    include CanCan::Ability 

    def initialize(user) 
    user ||= User.new # Guest user 

    if user.role? :admin 
     can :manage, :all 
    else 
     can :read, :all 

     if user.role?(:author) 
     can :create, Article 
     can :update, Article do |article| 
      article.try(:author) == user 
     end 
     can :destroy, Article do |article| 
      article.try(:author) == user 
     end 
     end 
    end 
    end 
end 

Weiteren Kontext, hier ist mein Benutzer und user_fabricator Klasse:

class User < ActiveRecord::Base 
    devise :database_authenticatable, :registerable, 
     :recoverable, :rememberable, :trackable, :validatable 

    attr_accessible :email, :password, :password_confirmation, :remember_me 
    attr_accessible :name, :roles 

    has_many :articles, :foreign_key => 'author_id', :dependent => :destroy 

    ROLES = %w[admin moderator author] 

    def roles=(roles) 
    self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.sum 
    end 

    def roles 
    ROLES.reject { |r| ((roles_mask || 0) & 2**ROLES.index(r)).zero? } 
    end 

    def role?(role) 
    roles.include?(role.to_s) 
    end 
end 

Die Benutzerrollen Methoden basieren auf Ryan Bates Methoden auf einem seiner Railscasts Episoden. Hier ist der Verarbeiter:

Fabricator(:user) do 
    email { sequence(:email) { |i| "user#{i}@example.com" } } 
    name { sequence(:name) { |i| "Example User-#{i}" } } 
    password 'foobar' 
end 

Fabricator(:admin, :from => :user) do 
    roles ['admin'] 
end 

Fabricator(:author, :from => :user) do 
    roles ['author'] 
end 

ich eine Ahnung haben, dass es etwas damit zu tun hat, wie ich die Fähigkeit Klasse definiert, aber ich kann nicht finden, wo ich schief gelaufen ist. Jede Hilfe wird sehr geschätzt. Thanks :)

+1

Kann CanCan wirklich "tun"? : create, @ articles'? Ich nehme an, '@ articles' ist ein Array von Artikeln hier. Sollte es nicht so etwas wie 'kann? : create,: articles' oder 'can? : erstellen, Artikel? Haben Sie auch wirklich so viele verschachtelte Funktionsaufrufe in der Spezifikation? Um das klar zu machen, haben Sie es mit 'it {have_link ('Neuer Artikel',: href => neuer_Artikel_Pfad)}} versucht? – Frost

+0

@Frost, ändere es in 'kann? : erstellen, Artikel funktioniert. Es ist komisch, weil ich nur der Folge der RailsCasts folge, also dachte ich mir, dass es funktionieren würde. Wie auch immer, du solltest das als Antwort posten, damit ich es akzeptieren kann. Danke :) –

+0

Fertig: http://stackoverflow.com/questions/10086150/having-trouble-testing-cancan-views-with-rspec/10089429#10089429 – Frost

Antwort

0

In der Ansicht, in der Sie

if can? :create, @articles 

tun ich denke, man ein Array can?, vorbei sind, die ein wenig seltsam scheint.

Soweit ich weiß, erwartet die can? Methode entweder ein Symbol oder eine Klasse.

Versuchen Sie, @articles durch Article oder :articles zu ersetzen.