diff --git a/.travis.yml b/.travis.yml index 0c0a2782..b31a69b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ rvm: - 1.8.7 + - 1.9.3 + - 2.0.0 - ree notifications: recipients: diff --git a/cancan.gemspec b/cancan.gemspec index 7240a245..eba87a7e 100644 --- a/cancan.gemspec +++ b/cancan.gemspec @@ -10,9 +10,8 @@ Gem::Specification.new do |s| s.files = Dir["{lib,spec}/**/*", "[A-Z]*", "init.rb"] - ["Gemfile.lock"] s.require_path = "lib" - s.add_development_dependency 'rspec', '~> 2.6.0' + s.add_development_dependency 'rspec', '~> 2.14.0' s.add_development_dependency 'rails', '~> 3.0.9' - s.add_development_dependency 'rr', '~> 0.10.11' # 1.0.0 has respond_to? issues: http://github.com/btakita/rr/issues/issue/43 s.add_development_dependency 'supermodel', '~> 0.1.4' s.rubyforge_project = s.name diff --git a/spec/cancan/ability_spec.rb b/spec/cancan/ability_spec.rb index 38595cb7..5646eaab 100644 --- a/spec/cancan/ability_spec.rb +++ b/spec/cancan/ability_spec.rb @@ -2,37 +2,36 @@ describe CanCan::Ability do before(:each) do - @ability = Object.new - @ability.extend(CanCan::Ability) + (@ability = double).extend(CanCan::Ability) end - it "should be able to :read anything" do + it "is able to :read anything" do @ability.can :read, :all - @ability.can?(:read, String).should be_true - @ability.can?(:read, 123).should be_true + expect(@ability.can?(:read, String)).to be_true + expect(@ability.can?(:read, 123)).to be_true end - it "should not have permission to do something it doesn't know about" do - @ability.can?(:foodfight, String).should be_false + it "does not have permission to do something it doesn't know about" do + expect(@ability.can?(:foodfight, String)).to be_false end - it "should pass true to `can?` when non false/nil is returned in block" do + it "passes true to `can?` when non false/nil is returned in block" do @ability.can :read, :all @ability.can :read, Symbol do |sym| "foo" # TODO test that sym is nil when no instance is passed end - @ability.can?(:read, :some_symbol).should == true + expect(@ability.can?(:read, :some_symbol)).to be_true end - it "should pass nil to a block when no instance is passed" do + it "passes nil to a block when no instance is passed" do @ability.can :read, Symbol do |sym| - sym.should be_nil + expect(sym).to be_nil true end - @ability.can?(:read, Symbol).should be_true + expect(@ability.can?(:read, Symbol)).to be_true end - it "should pass to previous rule, if block returns false or nil" do + it "passes to previous rule, if block returns false or nil" do @ability.can :read, Symbol @ability.can :read, Integer do |i| i < 5 @@ -40,364 +39,363 @@ @ability.can :read, Integer do |i| i > 10 end - @ability.can?(:read, Symbol).should be_true - @ability.can?(:read, 11).should be_true - @ability.can?(:read, 1).should be_true - @ability.can?(:read, 6).should be_false + expect(@ability.can?(:read, Symbol)).to be_true + expect(@ability.can?(:read, 11)).to be_true + expect(@ability.can?(:read, 1)).to be_true + expect(@ability.can?(:read, 6)).to be_false end - it "should not pass class with object if :all objects are accepted" do + it "does not pass class with object if :all objects are accepted" do @ability.can :preview, :all do |object| - object.should == 123 + expect(object).to eq(123) @block_called = true end @ability.can?(:preview, 123) - @block_called.should be_true + expect(@block_called).to be_true end - it "should not call block when only class is passed, only return true" do + it "does not call block when only class is passed, only return true" do @block_called = false @ability.can :preview, :all do |object| @block_called = true end - @ability.can?(:preview, Hash).should be_true - @block_called.should be_false + expect(@ability.can?(:preview, Hash)).to be_true + expect(@block_called).to be_false end - it "should pass only object for global manage actions" do + it "passes only object for global manage actions" do @ability.can :manage, String do |object| - object.should == "foo" + expect(object).to eq("foo") @block_called = true end - @ability.can?(:stuff, "foo").should - @block_called.should be_true + expect(@ability.can?(:stuff, "foo")).to be_true + expect(@block_called).to be_true end - it "should alias update or destroy actions to modify action" do + it "makes alias for update or destroy actions to modify action" do @ability.alias_action :update, :destroy, :to => :modify @ability.can :modify, :all - @ability.can?(:update, 123).should be_true - @ability.can?(:destroy, 123).should be_true + expect(@ability.can?(:update, 123)).to be_true + expect(@ability.can?(:destroy, 123)).to be_true end - it "should allow deeply nested aliased actions" do + it "allows deeply nested aliased actions" do @ability.alias_action :increment, :to => :sort @ability.alias_action :sort, :to => :modify @ability.can :modify, :all - @ability.can?(:increment, 123).should be_true + expect(@ability.can?(:increment, 123)).to be_true end - it "should raise an Error if alias target is an exist action" do - lambda{ @ability.alias_action :show, :to => :show }.should raise_error(CanCan::Error, "You can't specify target (show) as alias because it is real action name") + it "raises an Error if alias target is an exist action" do + expect { @ability.alias_action :show, :to => :show }.to raise_error(CanCan::Error, "You can't specify target (show) as alias because it is real action name") end - it "should always call block with arguments when passing no arguments to can" do + it "always calls block with arguments when passing no arguments to can" do @ability.can do |action, object_class, object| - action.should == :foo - object_class.should == 123.class - object.should == 123 + expect(action).to eq(:foo) + expect(object_class).to eq(123.class) + expect(object).to eq(123) @block_called = true end @ability.can?(:foo, 123) - @block_called.should be_true + expect(@block_called).to be_true end - it "should pass nil to object when comparing class with can check" do + it "passes nil to object when comparing class with can check" do @ability.can do |action, object_class, object| - action.should == :foo - object_class.should == Hash - object.should be_nil + expect(action).to eq(:foo) + expect(object_class).to eq(Hash) + expect(object).to be_nil @block_called = true end @ability.can?(:foo, Hash) - @block_called.should be_true + expect(@block_called).to be_true end - it "should automatically alias index and show into read calls" do + it "automatically makes alias for index and show into read calls" do @ability.can :read, :all - @ability.can?(:index, 123).should be_true - @ability.can?(:show, 123).should be_true + expect(@ability.can?(:index, 123)).to be_true + expect(@ability.can?(:show, 123)).to be_true end - it "should automatically alias new and edit into create and update respectively" do + it "automatically makes alias for new and edit into create and update respectively" do @ability.can :create, :all @ability.can :update, :all - @ability.can?(:new, 123).should be_true - @ability.can?(:edit, 123).should be_true + expect(@ability.can?(:new, 123)).to be_true + expect(@ability.can?(:edit, 123)).to be_true end - it "should not respond to prepare (now using initialize)" do - @ability.should_not respond_to(:prepare) + it "does not respond to prepare (now using initialize)" do + expect(@ability).to_not respond_to(:prepare) end - it "should offer cannot? method which is simply invert of can?" do - @ability.cannot?(:tie, String).should be_true + it "offers cannot? method which is simply invert of can?" do + expect(@ability.cannot?(:tie, String)).to be_true end - it "should be able to specify multiple actions and match any" do + it "is able to specify multiple actions and match any" do @ability.can [:read, :update], :all - @ability.can?(:read, 123).should be_true - @ability.can?(:update, 123).should be_true - @ability.can?(:count, 123).should be_false + expect(@ability.can?(:read, 123)).to be_true + expect(@ability.can?(:update, 123)).to be_true + expect(@ability.can?(:count, 123)).to be_false end - it "should be able to specify multiple classes and match any" do + it "is able to specify multiple classes and match any" do @ability.can :update, [String, Range] - @ability.can?(:update, "foo").should be_true - @ability.can?(:update, 1..3).should be_true - @ability.can?(:update, 123).should be_false + expect(@ability.can?(:update, "foo")).to be_true + expect(@ability.can?(:update, 1..3)).to be_true + expect(@ability.can?(:update, 123)).to be_false end - it "should support custom objects in the rule" do + it "supports custom objects in the rule" do @ability.can :read, :stats - @ability.can?(:read, :stats).should be_true - @ability.can?(:update, :stats).should be_false - @ability.can?(:read, :nonstats).should be_false + expect(@ability.can?(:read, :stats)).to be_true + expect(@ability.can?(:update, :stats)).to be_false + expect(@ability.can?(:read, :nonstats)).to be_false end - it "should check ancestors of class" do + it "checks ancestors of class" do @ability.can :read, Numeric - @ability.can?(:read, Integer).should be_true - @ability.can?(:read, 1.23).should be_true - @ability.can?(:read, "foo").should be_false + expect(@ability.can?(:read, Integer)).to be_true + expect(@ability.can?(:read, 1.23)).to be_true + expect(@ability.can?(:read, "foo")).to be_false end - it "should support 'cannot' method to define what user cannot do" do + it "supports 'cannot' method to define what user cannot do" do @ability.can :read, :all @ability.cannot :read, Integer - @ability.can?(:read, "foo").should be_true - @ability.can?(:read, 123).should be_false + expect(@ability.can?(:read, "foo")).to be_true + expect(@ability.can?(:read, 123)).to be_false end - it "should pass to previous rule, if block returns false or nil" do + it "passes to previous rule, if block returns false or nil" do @ability.can :read, :all @ability.cannot :read, Integer do |int| int > 10 ? nil : ( int > 5 ) end - @ability.can?(:read, "foo").should be_true - @ability.can?(:read, 3).should be_true - @ability.can?(:read, 8).should be_false - @ability.can?(:read, 123).should be_true + expect(@ability.can?(:read, "foo")).to be_true + expect(@ability.can?(:read, 3)).to be_true + expect(@ability.can?(:read, 8)).to be_false + expect(@ability.can?(:read, 123)).to be_true end - it "should always return `false` for single cannot definition" do + it "always returns `false` for single cannot definition" do @ability.cannot :read, Integer do |int| int > 10 ? nil : ( int > 5 ) end - @ability.can?(:read, "foo").should be_false - @ability.can?(:read, 3).should be_false - @ability.can?(:read, 8).should be_false - @ability.can?(:read, 123).should be_false + expect(@ability.can?(:read, "foo")).to be_false + expect(@ability.can?(:read, 3)).to be_false + expect(@ability.can?(:read, 8)).to be_false + expect(@ability.can?(:read, 123)).to be_false end - it "should pass to previous cannot definition, if block returns false or nil" do + it "passes to previous cannot definition, if block returns false or nil" do @ability.cannot :read, :all @ability.can :read, Integer do |int| int > 10 ? nil : ( int > 5 ) end - @ability.can?(:read, "foo").should be_false - @ability.can?(:read, 3).should be_false - @ability.can?(:read, 10).should be_true - @ability.can?(:read, 123).should be_false + expect(@ability.can?(:read, "foo")).to be_false + expect(@ability.can?(:read, 3)).to be_false + expect(@ability.can?(:read, 10)).to be_true + expect(@ability.can?(:read, 123)).to be_false end - it "should append aliased actions" do + it "appends aliased actions" do @ability.alias_action :update, :to => :modify @ability.alias_action :destroy, :to => :modify - @ability.aliased_actions[:modify].should == [:update, :destroy] + expect(@ability.aliased_actions[:modify]).to eq([:update, :destroy]) end - it "should clear aliased actions" do + it "clears aliased actions" do @ability.alias_action :update, :to => :modify @ability.clear_aliased_actions - @ability.aliased_actions[:modify].should be_nil + expect(@ability.aliased_actions[:modify]).to be_nil end - it "should pass additional arguments to block from can?" do + it "passes additional arguments to block from can?" do @ability.can :read, Integer do |int, x| int > x end - @ability.can?(:read, 2, 1).should be_true - @ability.can?(:read, 2, 3).should be_false + expect(@ability.can?(:read, 2, 1)).to be_true + expect(@ability.can?(:read, 2, 3)).to be_false end - it "should use conditions as third parameter and determine abilities from it" do + it "uses conditions as third parameter and determine abilities from it" do @ability.can :read, Range, :begin => 1, :end => 3 - @ability.can?(:read, 1..3).should be_true - @ability.can?(:read, 1..4).should be_false - @ability.can?(:read, Range).should be_true + expect(@ability.can?(:read, 1..3)).to be_true + expect(@ability.can?(:read, 1..4)).to be_false + expect(@ability.can?(:read, Range)).to be_true end - it "should allow an array of options in conditions hash" do + it "allows an array of options in conditions hash" do @ability.can :read, Range, :begin => [1, 3, 5] - @ability.can?(:read, 1..3).should be_true - @ability.can?(:read, 2..4).should be_false - @ability.can?(:read, 3..5).should be_true + expect(@ability.can?(:read, 1..3)).to be_true + expect(@ability.can?(:read, 2..4)).to be_false + expect(@ability.can?(:read, 3..5)).to be_true end - it "should allow a range of options in conditions hash" do + it "allows a range of options in conditions hash" do @ability.can :read, Range, :begin => 1..3 - @ability.can?(:read, 1..10).should be_true - @ability.can?(:read, 3..30).should be_true - @ability.can?(:read, 4..40).should be_false + expect(@ability.can?(:read, 1..10)).to be_true + expect(@ability.can?(:read, 3..30)).to be_true + expect(@ability.can?(:read, 4..40)).to be_false end - it "should allow nested hashes in conditions hash" do + it "allows nested hashes in conditions hash" do @ability.can :read, Range, :begin => { :to_i => 5 } - @ability.can?(:read, 5..7).should be_true - @ability.can?(:read, 6..8).should be_false + expect(@ability.can?(:read, 5..7)).to be_true + expect(@ability.can?(:read, 6..8)).to be_false end - it "should match any element passed in to nesting if it's an array (for has_many associations)" do + it "matches any element passed in to nesting if it's an array (for has_many associations)" do @ability.can :read, Range, :to_a => { :to_i => 3 } - @ability.can?(:read, 1..5).should be_true - @ability.can?(:read, 4..6).should be_false + expect(@ability.can?(:read, 1..5)).to be_true + expect(@ability.can?(:read, 4..6)).to be_false end - it "should accept a set as a condition value" do - mock(object_with_foo_2 = Object.new).foo { 2 } - mock(object_with_foo_3 = Object.new).foo { 3 } + it "accepts a set as a condition value" do + expect(object_with_foo_2 = double(:foo => 2)).to receive(:foo) + expect(object_with_foo_3 = double(:foo => 3)).to receive(:foo) @ability.can :read, Object, :foo => [1, 2, 5].to_set - @ability.can?(:read, object_with_foo_2).should be_true - @ability.can?(:read, object_with_foo_3).should be_false + expect(@ability.can?(:read, object_with_foo_2)).to be_true + expect(@ability.can?(:read, object_with_foo_3)).to be_false end - it "should not match subjects return nil for methods that must match nested a nested conditions hash" do - mock(object_with_foo = Object.new).foo { :bar } + it "does not match subjects return nil for methods that must match nested a nested conditions hash" do + expect(object_with_foo = double(:foo => :bar)).to receive(:foo) @ability.can :read, Array, :first => { :foo => :bar } - @ability.can?(:read, [object_with_foo]).should be_true - @ability.can?(:read, []).should be_false + expect(@ability.can?(:read, [object_with_foo])).to be_true + expect(@ability.can?(:read, [])).to be_false end - it "should match strings but not substrings specified in a conditions hash" do + it "matches strings but not substrings specified in a conditions hash" do @ability.can :read, String, :presence => "declassified" - @ability.can?(:read, "declassified").should be_true - @ability.can?(:read, "classified").should be_false + expect(@ability.can?(:read, "declassified")).to be_true + expect(@ability.can?(:read, "classified")).to be_false end - it "should not stop at cannot definition when comparing class" do + it "does not stop at cannot definition when comparing class" do @ability.can :read, Range @ability.cannot :read, Range, :begin => 1 - @ability.can?(:read, 2..5).should be_true - @ability.can?(:read, 1..5).should be_false - @ability.can?(:read, Range).should be_true + expect(@ability.can?(:read, 2..5)).to be_true + expect(@ability.can?(:read, 1..5)).to be_false + expect(@ability.can?(:read, Range)).to be_true end - it "should stop at cannot definition when no hash is present" do + it "stops at cannot definition when no hash is present" do @ability.can :read, :all @ability.cannot :read, Range - @ability.can?(:read, 1..5).should be_false - @ability.can?(:read, Range).should be_false + expect(@ability.can?(:read, 1..5)).to be_false + expect(@ability.can?(:read, Range)).to be_false end - it "should allow to check ability for Module" do + it "allows to check ability for Module" do module B; end class A; include B; end @ability.can :read, B - @ability.can?(:read, A).should be_true - @ability.can?(:read, A.new).should be_true + expect(@ability.can?(:read, A)).to be_true + expect(@ability.can?(:read, A.new)).to be_true end - it "should pass nil to a block for ability on Module when no instance is passed" do + it "passes nil to a block for ability on Module when no instance is passed" do module B; end class A; include B; end @ability.can :read, B do |sym| - sym.should be_nil + expect(sym).to be_nil true end - @ability.can?(:read, B).should be_true - @ability.can?(:read, A).should be_true + expect(@ability.can?(:read, B)).to be_true + expect(@ability.can?(:read, A)).to be_true end - it "passing a hash of subjects should check permissions through association" do + it "checks permissions through association when passing a hash of subjects" do @ability.can :read, Range, :string => {:length => 3} - @ability.can?(:read, "foo" => Range).should be_true - @ability.can?(:read, "foobar" => Range).should be_false - @ability.can?(:read, 123 => Range).should be_true + expect(@ability.can?(:read, "foo" => Range)).to be_true + expect(@ability.can?(:read, "foobar" => Range)).to be_false + expect(@ability.can?(:read, 123 => Range)).to be_true end - it "passing a hash of subjects with multiple definitions should check permissions correctly" do + it "checks permissions correctly when passing a hash of subjects with multiple definitions" do @ability.can :read, Range, :string => {:length => 4} @ability.can [:create, :read], Range, :string => {:upcase => 'FOO'} - @ability.can?(:read, "foo" => Range).should be_true - @ability.can?(:read, "foobar" => Range).should be_false - @ability.can?(:read, 1234 => Range).should be_true + expect(@ability.can?(:read, "foo" => Range)).to be_true + expect(@ability.can?(:read, "foobar" => Range)).to be_false + expect(@ability.can?(:read, 1234 => Range)).to be_true end - it "should allow to check ability on Hash-like object" do + it "allows to check ability on Hash-like object" do class Container < Hash; end @ability.can :read, Container - @ability.can?(:read, Container.new).should be_true + expect(@ability.can?(:read, Container.new)).to be_true end - it "should have initial attributes based on hash conditions of 'new' action" do + it "has initial attributes based on hash conditions of 'new' action" do @ability.can :manage, Range, :foo => "foo", :hash => {:skip => "hashes"} @ability.can :create, Range, :bar => 123, :array => %w[skip arrays] @ability.can :new, Range, :baz => "baz", :range => 1..3 @ability.cannot :new, Range, :ignore => "me" - @ability.attributes_for(:new, Range).should == {:foo => "foo", :bar => 123, :baz => "baz"} + expect(@ability.attributes_for(:new, Range)).to eq({:foo => "foo", :bar => 123, :baz => "baz"}) end - it "should raise access denied exception if ability us unauthorized to perform a certain action" do + it "raises access denied exception if ability us unauthorized to perform a certain action" do begin @ability.authorize! :read, :foo, 1, 2, 3, :message => "Access denied!" rescue CanCan::AccessDenied => e - e.message.should == "Access denied!" - e.action.should == :read - e.subject.should == :foo + expect(e.message).to eq("Access denied!") + expect(e.action).to eq(:read) + expect(e.subject).to eq(:foo) else fail "Expected CanCan::AccessDenied exception to be raised" end end - it "should not raise access denied exception if ability is authorized to perform an action and return subject" do + it "does not raise access denied exception if ability is authorized to perform an action and return subject" do @ability.can :read, :foo - lambda { - @ability.authorize!(:read, :foo).should == :foo - }.should_not raise_error + expect { + expect(@ability.authorize!(:read, :foo)).to eq(:foo) + }.to_not raise_error end - it "should know when block is used in conditions" do + it "knows when block is used in conditions" do @ability.can :read, :foo - @ability.should_not have_block(:read, :foo) + expect(@ability).to_not have_block(:read, :foo) @ability.can :read, :foo do |foo| false end - @ability.should have_block(:read, :foo) + expect(@ability).to have_block(:read, :foo) end - it "should know when raw sql is used in conditions" do + it "knows when raw sql is used in conditions" do @ability.can :read, :foo - @ability.should_not have_raw_sql(:read, :foo) + expect(@ability).to_not have_raw_sql(:read, :foo) @ability.can :read, :foo, 'false' - @ability.should have_raw_sql(:read, :foo) + expect(@ability).to have_raw_sql(:read, :foo) end - it "should raise access denied exception with default message if not specified" do + it "raises access denied exception with default message if not specified" do begin @ability.authorize! :read, :foo rescue CanCan::AccessDenied => e e.default_message = "Access denied!" - e.message.should == "Access denied!" + expect(e.message).to eq("Access denied!") else fail "Expected CanCan::AccessDenied exception to be raised" end end - it "should determine model adapter class by asking AbstractAdapter" do - model_class = Object.new - adapter_class = Object.new - stub(CanCan::ModelAdapters::AbstractAdapter).adapter_class(model_class) { adapter_class } - stub(adapter_class).new(model_class, []) { :adapter_instance } - @ability.model_adapter(model_class, :read).should == :adapter_instance + it "determines model adapterO class by asking AbstractAdapter" do + adapter_class, model_class = double, double + allow(CanCan::ModelAdapters::AbstractAdapter).to receive(:adapter_class).with(model_class) { adapter_class } + allow(adapter_class).to receive(:new).with(model_class, []) { :adapter_instance } + expect(@ability.model_adapter(model_class, :read)).to eq(:adapter_instance) end - it "should raise an error when attempting to use a block with a hash condition since it's not likely what they want" do - lambda { + it "raises an error when attempting to use a block with a hash condition since it's not likely what they want" do + expect { @ability.can :read, Array, :published => true do false end - }.should raise_error(CanCan::Error, "You are not able to supply a block with a hash of conditions in read Array ability. Use either one.") + }.to raise_error(CanCan::Error, "You are not able to supply a block with a hash of conditions in read Array ability. Use either one.") end describe "unauthorized message" do @@ -405,54 +403,53 @@ class Container < Hash; end I18n.backend = nil end - it "should use action/subject in i18n" do + it "uses action/subject in i18n" do I18n.backend.store_translations :en, :unauthorized => {:update => {:array => "foo"}} - @ability.unauthorized_message(:update, Array).should == "foo" - @ability.unauthorized_message(:update, [1, 2, 3]).should == "foo" - @ability.unauthorized_message(:update, :missing).should be_nil + expect(@ability.unauthorized_message(:update, Array)).to eq("foo") + expect(@ability.unauthorized_message(:update, [1, 2, 3])).to eq("foo") + expect(@ability.unauthorized_message(:update, :missing)).to be_nil end - it "should use symbol as subject directly" do + it "uses symbol as subject directly" do I18n.backend.store_translations :en, :unauthorized => {:has => {:cheezburger => "Nom nom nom. I eated it."}} - @ability.unauthorized_message(:has, :cheezburger).should == "Nom nom nom. I eated it." + expect(@ability.unauthorized_message(:has, :cheezburger)).to eq("Nom nom nom. I eated it.") end - it "should fall back to 'manage' and 'all'" do + it "falls back to 'manage' and 'all'" do I18n.backend.store_translations :en, :unauthorized => { :manage => {:all => "manage all", :array => "manage array"}, :update => {:all => "update all", :array => "update array"} } - @ability.unauthorized_message(:update, Array).should == "update array" - @ability.unauthorized_message(:update, Hash).should == "update all" - @ability.unauthorized_message(:foo, Array).should == "manage array" - @ability.unauthorized_message(:foo, Hash).should == "manage all" + expect(@ability.unauthorized_message(:update, Array)).to eq("update array") + expect(@ability.unauthorized_message(:update, Hash)).to eq("update all") + expect(@ability.unauthorized_message(:foo, Array)).to eq("manage array") + expect(@ability.unauthorized_message(:foo, Hash)).to eq("manage all") end - it "should follow aliased actions" do + it "follows aliased actions" do I18n.backend.store_translations :en, :unauthorized => {:modify => {:array => "modify array"}} @ability.alias_action :update, :to => :modify - @ability.unauthorized_message(:update, Array).should == "modify array" - @ability.unauthorized_message(:edit, Array).should == "modify array" + expect(@ability.unauthorized_message(:update, Array)).to eq("modify array") + expect(@ability.unauthorized_message(:edit, Array)).to eq("modify array") end - it "should have variables for action and subject" do + it "has variables for action and subject" do I18n.backend.store_translations :en, :unauthorized => {:manage => {:all => "%{action} %{subject}"}} # old syntax for now in case testing with old I18n - @ability.unauthorized_message(:update, Array).should == "update array" - @ability.unauthorized_message(:update, ArgumentError).should == "update argument error" - @ability.unauthorized_message(:edit, 1..3).should == "edit range" + expect(@ability.unauthorized_message(:update, Array)).to eq("update array") + expect(@ability.unauthorized_message(:update, ArgumentError)).to eq("update argument error") + expect(@ability.unauthorized_message(:edit, 1..3)).to eq("edit range") end end describe "#merge" do - it "should add the rules from the given ability" do + it "adds the rules from the given ability" do @ability.can :use, :tools - another_ability = Object.new - another_ability.extend(CanCan::Ability) + (another_ability = double).extend(CanCan::Ability) another_ability.can :use, :search @ability.merge(another_ability) - @ability.can?(:use, :search).should be_true - @ability.send(:rules).size.should == 2 + expect(@ability.can?(:use, :search)).to be_true + expect(@ability.send(:rules).size).to eq(2) end end end diff --git a/spec/cancan/controller_additions_spec.rb b/spec/cancan/controller_additions_spec.rb index cb8af3f1..05a59cc0 100644 --- a/spec/cancan/controller_additions_spec.rb +++ b/spec/cancan/controller_additions_spec.rb @@ -4,134 +4,138 @@ before(:each) do @controller_class = Class.new @controller = @controller_class.new - stub(@controller).params { {} } - stub(@controller).current_user { :current_user } - mock(@controller_class).helper_method(:can?, :cannot?, :current_ability) + allow(@controller).to receive(:params) { {} } + allow(@controller).to receive(:current_user) { :current_user } + expect(@controller_class).to receive(:helper_method).with(:can?, :cannot?, :current_ability) @controller_class.send(:include, CanCan::ControllerAdditions) end - it "should raise ImplementationRemoved when attempting to call 'unauthorized!' on a controller" do - lambda { @controller.unauthorized! }.should raise_error(CanCan::ImplementationRemoved) + it "raises ImplementationRemoved when attempting to call 'unauthorized!' on a controller" do + expect { @controller.unauthorized! }.to raise_error(CanCan::ImplementationRemoved) end - it "authorize! should assign @_authorized instance variable and pass args to current ability" do - mock(@controller.current_ability).authorize!(:foo, :bar) + it "authorize! assigns @_authorized instance variable and pass args to current ability" do + allow(@controller.current_ability).to receive(:authorize!).with(:foo, :bar) @controller.authorize!(:foo, :bar) - @controller.instance_variable_get(:@_authorized).should be_true + expect(@controller.instance_variable_get(:@_authorized)).to be_true end - it "should have a current_ability method which generates an ability for the current user" do - @controller.current_ability.should be_kind_of(Ability) + it "has a current_ability method which generates an ability for the current user" do + expect(@controller.current_ability).to be_kind_of(Ability) end - it "should provide a can? and cannot? methods which go through the current ability" do - @controller.current_ability.should be_kind_of(Ability) - @controller.can?(:foo, :bar).should be_false - @controller.cannot?(:foo, :bar).should be_true + it "provides a can? and cannot? methods which go through the current ability" do + expect(@controller.current_ability).to be_kind_of(Ability) + expect(@controller.can?(:foo, :bar)).to be_false + expect(@controller.cannot?(:foo, :bar)).to be_true end - it "load_and_authorize_resource should setup a before filter which passes call to ControllerResource" do - stub(CanCan::ControllerResource).new(@controller, nil, :foo => :bar).mock!.load_and_authorize_resource - mock(@controller_class).before_filter({}) { |options, block| block.call(@controller) } + it "load_and_authorize_resource setups a before filter which passes call to ControllerResource" do + expect(cancan_resource_class = double).to receive(:load_and_authorize_resource) + allow(CanCan::ControllerResource).to receive(:new).with(@controller, nil, :foo => :bar) {cancan_resource_class } + expect(@controller_class).to receive(:before_filter).with({}) { |options, &block| block.call(@controller) } @controller_class.load_and_authorize_resource :foo => :bar end - it "load_and_authorize_resource should properly pass first argument as the resource name" do - stub(CanCan::ControllerResource).new(@controller, :project, :foo => :bar).mock!.load_and_authorize_resource - mock(@controller_class).before_filter({}) { |options, block| block.call(@controller) } + it "load_and_authorize_resource properly passes first argument as the resource name" do + expect(cancan_resource_class = double).to receive(:load_and_authorize_resource) + allow(CanCan::ControllerResource).to receive(:new).with(@controller, :project, :foo => :bar) {cancan_resource_class} + expect(@controller_class).to receive(:before_filter).with({}) { |options, &block| block.call(@controller) } @controller_class.load_and_authorize_resource :project, :foo => :bar end - it "load_and_authorize_resource with :prepend should prepend the before filter" do - mock(@controller_class).prepend_before_filter({}) + it "load_and_authorize_resource with :prepend prepends the before filter" do + expect(@controller_class).to receive(:prepend_before_filter).with({}) @controller_class.load_and_authorize_resource :foo => :bar, :prepend => true end - it "authorize_resource should setup a before filter which passes call to ControllerResource" do - stub(CanCan::ControllerResource).new(@controller, nil, :foo => :bar).mock!.authorize_resource - mock(@controller_class).before_filter(:except => :show, :if => true) { |options, block| block.call(@controller) } + it "authorize_resource setups a before filter which passes call to ControllerResource" do + expect(cancan_resource_class = double).to receive(:authorize_resource) + allow(CanCan::ControllerResource).to receive(:new).with(@controller, nil, :foo => :bar) {cancan_resource_class} + expect(@controller_class).to receive(:before_filter).with(:except => :show, :if => true) { |options, &block| block.call(@controller) } @controller_class.authorize_resource :foo => :bar, :except => :show, :if => true end - it "load_resource should setup a before filter which passes call to ControllerResource" do - stub(CanCan::ControllerResource).new(@controller, nil, :foo => :bar).mock!.load_resource - mock(@controller_class).before_filter(:only => [:show, :index], :unless => false) { |options, block| block.call(@controller) } + it "load_resource setups a before filter which passes call to ControllerResource" do + expect(cancan_resource_class = double).to receive(:load_resource) + allow(CanCan::ControllerResource).to receive(:new).with(@controller, nil, :foo => :bar) {cancan_resource_class} + expect(@controller_class).to receive(:before_filter).with(:only => [:show, :index], :unless => false) { |options, &block| block.call(@controller) } @controller_class.load_resource :foo => :bar, :only => [:show, :index], :unless => false end - it "skip_authorization_check should set up a before filter which sets @_authorized to true" do - mock(@controller_class).before_filter(:filter_options) { |options, block| block.call(@controller) } + it "skip_authorization_check setups a before filter which sets @_authorized to true" do + expect(@controller_class).to receive(:before_filter).with(:filter_options) { |options, &block| block.call(@controller) } @controller_class.skip_authorization_check(:filter_options) - @controller.instance_variable_get(:@_authorized).should be_true + expect(@controller.instance_variable_get(:@_authorized)).to be_true end - it "check_authorization should trigger AuthorizationNotPerformed in after filter" do - mock(@controller_class).after_filter(:only => [:test]) { |options, block| block.call(@controller) } - lambda { + it "check_authorization triggers AuthorizationNotPerformed in after filter" do + expect(@controller_class).to receive(:after_filter).with(:only => [:test]) { |options, &block| block.call(@controller) } + expect { @controller_class.check_authorization(:only => [:test]) - }.should raise_error(CanCan::AuthorizationNotPerformed) + }.to raise_error(CanCan::AuthorizationNotPerformed) end - it "check_authorization should not trigger AuthorizationNotPerformed when :if is false" do - stub(@controller).check_auth? { false } - mock(@controller_class).after_filter({}) { |options, block| block.call(@controller) } - lambda { + it "check_authorization does not trigger AuthorizationNotPerformed when :if is false" do + allow(@controller).to receive(:check_auth?) { false } + allow(@controller_class).to receive(:after_filter).with({}) { |options, &block| block.call(@controller) } + expect { @controller_class.check_authorization(:if => :check_auth?) - }.should_not raise_error(CanCan::AuthorizationNotPerformed) + }.not_to raise_error end - it "check_authorization should not trigger AuthorizationNotPerformed when :unless is true" do - stub(@controller).engine_controller? { true } - mock(@controller_class).after_filter({}) { |options, block| block.call(@controller) } - lambda { + it "check_authorization does not trigger AuthorizationNotPerformed when :unless is true" do + allow(@controller).to receive(:engine_controller?) { true } + expect(@controller_class).to receive(:after_filter).with({}) { |options, &block| block.call(@controller) } + expect { @controller_class.check_authorization(:unless => :engine_controller?) - }.should_not raise_error(CanCan::AuthorizationNotPerformed) + }.not_to raise_error end - it "check_authorization should not raise error when @_authorized is set" do + it "check_authorization does not raise error when @_authorized is set" do @controller.instance_variable_set(:@_authorized, true) - mock(@controller_class).after_filter(:only => [:test]) { |options, block| block.call(@controller) } - lambda { + expect(@controller_class).to receive(:after_filter).with(:only => [:test]) { |options, &block| block.call(@controller) } + expect { @controller_class.check_authorization(:only => [:test]) - }.should_not raise_error(CanCan::AuthorizationNotPerformed) + }.not_to raise_error end - it "cancan_resource_class should be ControllerResource by default" do - @controller.class.cancan_resource_class.should == CanCan::ControllerResource + it "cancan_resource_class is ControllerResource by default" do + expect(@controller.class.cancan_resource_class).to eq(CanCan::ControllerResource) end - it "cancan_resource_class should be InheritedResource when class includes InheritedResources::Actions" do - stub(@controller.class).ancestors { ["InheritedResources::Actions"] } - @controller.class.cancan_resource_class.should == CanCan::InheritedResource + it "cancan_resource_class is InheritedResource when class includes InheritedResources::Actions" do + allow(@controller.class).to receive(:ancestors) { ["InheritedResources::Actions"] } + expect(@controller.class.cancan_resource_class).to eq(CanCan::InheritedResource) end - it "cancan_skipper should be an empty hash with :authorize and :load options and remember changes" do - @controller_class.cancan_skipper.should == {:authorize => {}, :load => {}} + it "cancan_skipper is an empty hash with :authorize and :load options and remember changes" do + expect(@controller_class.cancan_skipper).to eq({:authorize => {}, :load => {}}) @controller_class.cancan_skipper[:load] = true - @controller_class.cancan_skipper[:load].should == true + expect(@controller_class.cancan_skipper[:load]).to be_true end - it "skip_authorize_resource should add itself to the cancan skipper with given model name and options" do + it "skip_authorize_resource adds itself to the cancan skipper with given model name and options" do @controller_class.skip_authorize_resource(:project, :only => [:index, :show]) - @controller_class.cancan_skipper[:authorize][:project].should == {:only => [:index, :show]} + expect(@controller_class.cancan_skipper[:authorize][:project]).to eq({:only => [:index, :show]}) @controller_class.skip_authorize_resource(:only => [:index, :show]) - @controller_class.cancan_skipper[:authorize][nil].should == {:only => [:index, :show]} + expect(@controller_class.cancan_skipper[:authorize][nil]).to eq({:only => [:index, :show]}) @controller_class.skip_authorize_resource(:article) - @controller_class.cancan_skipper[:authorize][:article].should == {} + expect(@controller_class.cancan_skipper[:authorize][:article]).to eq({}) end - it "skip_load_resource should add itself to the cancan skipper with given model name and options" do + it "skip_load_resource adds itself to the cancan skipper with given model name and options" do @controller_class.skip_load_resource(:project, :only => [:index, :show]) - @controller_class.cancan_skipper[:load][:project].should == {:only => [:index, :show]} + expect(@controller_class.cancan_skipper[:load][:project]).to eq({:only => [:index, :show]}) @controller_class.skip_load_resource(:only => [:index, :show]) - @controller_class.cancan_skipper[:load][nil].should == {:only => [:index, :show]} + expect(@controller_class.cancan_skipper[:load][nil]).to eq({:only => [:index, :show]}) @controller_class.skip_load_resource(:article) - @controller_class.cancan_skipper[:load][:article].should == {} + expect(@controller_class.cancan_skipper[:load][:article]).to eq({}) end - it "skip_load_and_authore_resource should add itself to the cancan skipper with given model name and options" do + it "skip_load_and_authore_resource adds itself to the cancan skipper with given model name and options" do @controller_class.skip_load_and_authorize_resource(:project, :only => [:index, :show]) - @controller_class.cancan_skipper[:load][:project].should == {:only => [:index, :show]} - @controller_class.cancan_skipper[:authorize][:project].should == {:only => [:index, :show]} + expect(@controller_class.cancan_skipper[:load][:project]).to eq({:only => [:index, :show]}) + expect(@controller_class.cancan_skipper[:authorize][:project]).to eq({:only => [:index, :show]}) end end diff --git a/spec/cancan/controller_resource_spec.rb b/spec/cancan/controller_resource_spec.rb index 03f16bfb..13f93de6 100644 --- a/spec/cancan/controller_resource_spec.rb +++ b/spec/cancan/controller_resource_spec.rb @@ -6,36 +6,36 @@ @controller_class = Class.new @controller = @controller_class.new @ability = Ability.new(nil) - stub(@controller).params { @params } - stub(@controller).current_ability { @ability } - stub(@controller_class).cancan_skipper { {:authorize => {}, :load => {}} } + allow(@controller).to receive(:params) { @params } + allow(@controller).to receive(:current_ability) { @ability } + allow(@controller_class).to receive(:cancan_skipper) { {:authorize => {}, :load => {}} } end - it "should load the resource into an instance variable if params[:id] is specified" do + it "loads the resource into an instance variable if params[:id] is specified" do project = Project.create! @params.merge!(:action => "show", :id => project.id) resource = CanCan::ControllerResource.new(@controller) resource.load_resource - @controller.instance_variable_get(:@project).should == project + expect(@controller.instance_variable_get(:@project)).to eq(project) end - it "should not load resource into an instance variable if already set" do + it "does not load resource into an instance variable if already set" do @params.merge!(:action => "show", :id => "123") @controller.instance_variable_set(:@project, :some_project) resource = CanCan::ControllerResource.new(@controller) resource.load_resource - @controller.instance_variable_get(:@project).should == :some_project + expect(@controller.instance_variable_get(:@project)).to eq(:some_project) end - it "should properly load resource for namespaced controller" do + it "loads resource for namespaced controller" do project = Project.create! @params.merge!(:controller => "admin/projects", :action => "show", :id => project.id) resource = CanCan::ControllerResource.new(@controller) resource.load_resource - @controller.instance_variable_get(:@project).should == project + expect(@controller.instance_variable_get(:@project)).to eq(project) end - it "should attempt to load a resource with the same namespace as the controller when using :: for namespace" do + it "attempts to load a resource with the same namespace as the controller when using :: for namespace" do module MyEngine class Project < ::Project; end end @@ -44,11 +44,11 @@ class Project < ::Project; end @params.merge!(:controller => "MyEngine::ProjectsController", :action => "show", :id => project.id) resource = CanCan::ControllerResource.new(@controller) resource.load_resource - @controller.instance_variable_get(:@project).should == project + expect(@controller.instance_variable_get(:@project)).to eq(project) end # Rails includes namespace in params, see issue #349 - it "should create through the namespaced params" do + it "creates through the namespaced params" do module MyEngine class Project < ::Project; end end @@ -56,15 +56,15 @@ class Project < ::Project; end @params.merge!(:controller => "MyEngine::ProjectsController", :action => "create", :my_engine_project => {:name => "foobar"}) resource = CanCan::ControllerResource.new(@controller) resource.load_resource - @controller.instance_variable_get(:@project).name.should == "foobar" + expect(@controller.instance_variable_get(:@project).name).to eq("foobar") end - it "should properly load resource for namespaced controller when using '::' for namespace" do + it "loads resource for namespaced controller when using '::' for namespace" do project = Project.create! @params.merge!(:controller => "Admin::ProjectsController", :action => "show", :id => project.id) resource = CanCan::ControllerResource.new(@controller) resource.load_resource - @controller.instance_variable_get(:@project).should == project + expect(@controller.instance_variable_get(:@project)).to eq(project) end it "has the specified nested resource_class when using / for namespace" do @@ -74,418 +74,416 @@ class Dashboard; end @ability.can(:index, "admin/dashboard") @params.merge!(:controller => "admin/dashboard", :action => "index") resource = CanCan::ControllerResource.new(@controller, :authorize => true) - resource.send(:resource_class).should == Admin::Dashboard + expect(resource.send(:resource_class)).to eq(Admin::Dashboard) end - it "should build a new resource with hash if params[:id] is not specified" do + it "builds a new resource with hash if params[:id] is not specified" do @params.merge!(:action => "create", :project => {:name => "foobar"}) resource = CanCan::ControllerResource.new(@controller) resource.load_resource - @controller.instance_variable_get(:@project).name.should == "foobar" + expect(@controller.instance_variable_get(:@project).name).to eq("foobar") end - it "should build a new resource for namespaced model with hash if params[:id] is not specified" do + it "builds a new resource for namespaced model with hash if params[:id] is not specified" do @params.merge!(:action => "create", 'sub_project' => {:name => "foobar"}) resource = CanCan::ControllerResource.new(@controller, :class => ::Sub::Project) resource.load_resource - @controller.instance_variable_get(:@project).name.should == "foobar" + expect(@controller.instance_variable_get(:@project).name).to eq("foobar") end - it "should build a new resource for namespaced controller and namespaced model with hash if params[:id] is not specified" do + it "builds a new resource for namespaced controller and namespaced model with hash if params[:id] is not specified" do @params.merge!(:controller => "Admin::SubProjectsController", :action => "create", 'sub_project' => {:name => "foobar"}) resource = CanCan::ControllerResource.new(@controller, :class => Project) resource.load_resource - @controller.instance_variable_get(:@sub_project).name.should == "foobar" + expect(@controller.instance_variable_get(:@sub_project).name).to eq("foobar") end - it "should build a new resource with attributes from current ability" do + it "builds a new resource with attributes from current ability" do @params.merge!(:action => "new") @ability.can(:create, Project, :name => "from conditions") resource = CanCan::ControllerResource.new(@controller) resource.load_resource - @controller.instance_variable_get(:@project).name.should == "from conditions" + expect(@controller.instance_variable_get(:@project).name).to eq("from conditions") end - it "should override initial attributes with params" do + it "overrides initial attributes with params" do @params.merge!(:action => "new", :project => {:name => "from params"}) @ability.can(:create, Project, :name => "from conditions") resource = CanCan::ControllerResource.new(@controller) resource.load_resource - @controller.instance_variable_get(:@project).name.should == "from params" + expect(@controller.instance_variable_get(:@project).name).to eq("from params") end - it "should build a collection when on index action when class responds to accessible_by" do - stub(Project).accessible_by(@ability, :index) { :found_projects } + it "builds a collection when on index action when class responds to accessible_by" do + allow(Project).to receive(:accessible_by).with(@ability, :index) { :found_projects } @params[:action] = "index" resource = CanCan::ControllerResource.new(@controller, :project) resource.load_resource - @controller.instance_variable_get(:@project).should be_nil - @controller.instance_variable_get(:@projects).should == :found_projects + expect(@controller.instance_variable_get(:@project)).to be_nil + expect(@controller.instance_variable_get(:@projects)).to eq(:found_projects) end - it "should not build a collection when on index action when class does not respond to accessible_by" do + it "does not build a collection when on index action when class does not respond to accessible_by" do @params[:action] = "index" resource = CanCan::ControllerResource.new(@controller) resource.load_resource - @controller.instance_variable_get(:@project).should be_nil - @controller.instance_variable_defined?(:@projects).should be_false + expect(@controller.instance_variable_get(:@project)).to be_nil + expect(@controller.instance_variable_defined?(:@projects)).to be_false end - it "should not use accessible_by when defining abilities through a block" do - stub(Project).accessible_by(@ability) { :found_projects } + it "does not use accessible_by when defining abilities through a block" do + allow(Project).to receive(:accessible_by).with(@ability) { :found_projects } @params[:action] = "index" @ability.can(:read, Project) { |p| false } resource = CanCan::ControllerResource.new(@controller) resource.load_resource - @controller.instance_variable_get(:@project).should be_nil - @controller.instance_variable_defined?(:@projects).should be_false + expect(@controller.instance_variable_get(:@project)).to be_nil + expect(@controller.instance_variable_defined?(:@projects)).to be_false end - it "should not authorize single resource in collection action" do + it "does not authorize single resource in collection action" do @params[:action] = "index" @controller.instance_variable_set(:@project, :some_project) - stub(@controller).authorize!(:index, Project) { raise CanCan::AccessDenied } + allow(@controller).to receive(:authorize!).with(:index, Project) { raise CanCan::AccessDenied } resource = CanCan::ControllerResource.new(@controller) - lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied) + expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied) end - it "should authorize parent resource in collection action" do + it "authorizes parent resource in collection action" do @params[:action] = "index" @controller.instance_variable_set(:@category, :some_category) - stub(@controller).authorize!(:show, :some_category) { raise CanCan::AccessDenied } + allow(@controller).to receive(:authorize!).with(:show, :some_category) { raise CanCan::AccessDenied } resource = CanCan::ControllerResource.new(@controller, :category, :parent => true) - lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied) + expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied) end - it "should perform authorization using controller action and loaded model" do + it "performs authorization using controller action and loaded model" do @params.merge!(:action => "show", :id => "123") @controller.instance_variable_set(:@project, :some_project) - stub(@controller).authorize!(:show, :some_project) { raise CanCan::AccessDenied } + allow(@controller).to receive(:authorize!).with(:show, :some_project) { raise CanCan::AccessDenied } resource = CanCan::ControllerResource.new(@controller) - lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied) + expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied) end - it "should perform authorization using controller action and non loaded model" do + it "performs authorization using controller action and non loaded model" do @params.merge!(:action => "show", :id => "123") - stub(@controller).authorize!(:show, Project) { raise CanCan::AccessDenied } + allow(@controller).to receive(:authorize!).with(:show, Project) { raise CanCan::AccessDenied } resource = CanCan::ControllerResource.new(@controller) - lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied) + expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied) end - it "should call load_resource and authorize_resource for load_and_authorize_resource" do + it "calls load_resource and authorize_resource for load_and_authorize_resource" do @params.merge!(:action => "show", :id => "123") resource = CanCan::ControllerResource.new(@controller) - mock(resource).load_resource - mock(resource).authorize_resource + expect(resource).to receive(:load_resource) + expect(resource).to receive(:authorize_resource) resource.load_and_authorize_resource end - it "should not build a single resource when on custom collection action even with id" do + it "does not build a single resource when on custom collection action even with id" do @params.merge!(:action => "sort", :id => "123") resource = CanCan::ControllerResource.new(@controller, :collection => [:sort, :list]) resource.load_resource - @controller.instance_variable_get(:@project).should be_nil + expect(@controller.instance_variable_get(:@project)).to be_nil end - it "should load a collection resource when on custom action with no id param" do - stub(Project).accessible_by(@ability, :sort) { :found_projects } + it "loads a collection resource when on custom action with no id param" do + allow(Project).to receive(:accessible_by).with(@ability, :sort) { :found_projects } @params[:action] = "sort" resource = CanCan::ControllerResource.new(@controller) resource.load_resource - @controller.instance_variable_get(:@project).should be_nil - @controller.instance_variable_get(:@projects).should == :found_projects + expect(@controller.instance_variable_get(:@project)).to be_nil + expect(@controller.instance_variable_get(:@projects)).to eq(:found_projects) end - it "should build a resource when on custom new action even when params[:id] exists" do + it "builds a resource when on custom new action even when params[:id] exists" do @params.merge!(:action => "build", :id => "123") - stub(Project).new { :some_project } + allow(Project).to receive(:new) { :some_project } resource = CanCan::ControllerResource.new(@controller, :new => :build) resource.load_resource - @controller.instance_variable_get(:@project).should == :some_project + expect(@controller.instance_variable_get(:@project)).to eq(:some_project) end - it "should not try to load resource for other action if params[:id] is undefined" do + it "does not try to load resource for other action if params[:id] is undefined" do @params[:action] = "list" resource = CanCan::ControllerResource.new(@controller) resource.load_resource - @controller.instance_variable_get(:@project).should be_nil + expect(@controller.instance_variable_get(:@project)).to be_nil end - it "should be a parent resource when name is provided which doesn't match controller" do + it "is a parent resource when name is provided which doesn't match controller" do resource = CanCan::ControllerResource.new(@controller, :category) - resource.should be_parent + expect(resource).to be_parent end - it "should not be a parent resource when name is provided which matches controller" do + it "does not be a parent resource when name is provided which matches controller" do resource = CanCan::ControllerResource.new(@controller, :project) - resource.should_not be_parent + expect(resource).to_not be_parent end - it "should be parent if specified in options" do + it "is parent if specified in options" do resource = CanCan::ControllerResource.new(@controller, :project, {:parent => true}) - resource.should be_parent + expect(resource).to be_parent end - it "should not be parent if specified in options" do + it "does not be parent if specified in options" do resource = CanCan::ControllerResource.new(@controller, :category, {:parent => false}) - resource.should_not be_parent + expect(resource).to_not be_parent end - it "should have the specified resource_class if 'name' is passed to load_resource" do + it "has the specified resource_class if 'name' is passed to load_resource" do class Section end resource = CanCan::ControllerResource.new(@controller, :section) - resource.send(:resource_class).should == Section + expect(resource.send(:resource_class)).to eq(Section) end - it "should load parent resource through proper id parameter" do + it "loads parent resource through proper id parameter" do project = Project.create! @params.merge!(:controller => "categories", :action => "index", :project_id => project.id) resource = CanCan::ControllerResource.new(@controller, :project) resource.load_resource - @controller.instance_variable_get(:@project).should == project + expect(@controller.instance_variable_get(:@project)).to eq(project) end - it "should load resource through the association of another parent resource using instance variable" do + it "loads resource through the association of another parent resource using instance variable" do @params.merge!(:action => "show", :id => "123") - category = Object.new + category = double(:projects => {}) @controller.instance_variable_set(:@category, category) - stub(category).projects.stub!.find("123") { :some_project } + allow(category.projects).to receive(:find).with("123") { :some_project } resource = CanCan::ControllerResource.new(@controller, :through => :category) resource.load_resource - @controller.instance_variable_get(:@project).should == :some_project + expect(@controller.instance_variable_get(:@project)).to eq(:some_project) end - it "should load resource through the custom association name" do + it "loads resource through the custom association name" do @params.merge!(:action => "show", :id => "123") - category = Object.new + category = double(:custom_projects => {}) @controller.instance_variable_set(:@category, category) - stub(category).custom_projects.stub!.find("123") { :some_project } + allow(category.custom_projects).to receive(:find).with("123") { :some_project } resource = CanCan::ControllerResource.new(@controller, :through => :category, :through_association => :custom_projects) resource.load_resource - @controller.instance_variable_get(:@project).should == :some_project + expect(@controller.instance_variable_get(:@project)).to eq(:some_project) end - it "should load resource through the association of another parent resource using method" do + it "loads resource through the association of another parent resource using method" do @params.merge!(:action => "show", :id => "123") - category = Object.new - stub(@controller).category { category } - stub(category).projects.stub!.find("123") { :some_project } + category = double(:projects => {}) + allow(@controller).to receive(:category) { category } + allow(category.projects).to receive(:find).with("123") { :some_project } resource = CanCan::ControllerResource.new(@controller, :through => :category) resource.load_resource - @controller.instance_variable_get(:@project).should == :some_project + expect(@controller.instance_variable_get(:@project)).to eq(:some_project) end - it "should not load through parent resource if instance isn't loaded when shallow" do + it "does not load through parent resource if instance isn't loaded when shallow" do project = Project.create! @params.merge!(:action => "show", :id => project.id) resource = CanCan::ControllerResource.new(@controller, :through => :category, :shallow => true) resource.load_resource - @controller.instance_variable_get(:@project).should == project + expect(@controller.instance_variable_get(:@project)).to eq(project) end - it "should raise AccessDenied when attempting to load resource through nil" do + it "raises AccessDenied when attempting to load resource through nil" do project = Project.create! @params.merge!(:action => "show", :id => project.id) resource = CanCan::ControllerResource.new(@controller, :through => :category) - lambda { + expect { resource.load_resource - }.should raise_error(CanCan::AccessDenied) { |exception| - exception.action.should == :show - exception.subject.should == Project + }.to raise_error(CanCan::AccessDenied) { |exception| + expect(exception.action).to eq(:show) + expect(exception.subject).to eq(Project) } - @controller.instance_variable_get(:@project).should be_nil + expect(@controller.instance_variable_get(:@project)).to be_nil end - it "should authorize nested resource through parent association on index action" do + it "authorizes nested resource through parent association on index action" do @params.merge!(:action => "index") - category = Object.new - @controller.instance_variable_set(:@category, category) - stub(@controller).authorize!(:index, category => Project) { raise CanCan::AccessDenied } + @controller.instance_variable_set(:@category, category = double) + allow(@controller).to receive(:authorize!).with(:index, category => Project) { raise CanCan::AccessDenied } resource = CanCan::ControllerResource.new(@controller, :through => :category) - lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied) + expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied) end - it "should load through first matching if multiple are given" do + it "loads through first matching if multiple are given" do @params.merge!(:action => "show", :id => "123") - category = Object.new + category = double(:projects => {}) @controller.instance_variable_set(:@category, category) - stub(category).projects.stub!.find("123") { :some_project } + allow(category.projects).to receive(:find).with("123") { :some_project } resource = CanCan::ControllerResource.new(@controller, :through => [:category, :user]) resource.load_resource - @controller.instance_variable_get(:@project).should == :some_project + expect(@controller.instance_variable_get(:@project)).to eq(:some_project) end - it "should find record through has_one association with :singleton option without id param" do + it "finds record through has_one association with :singleton option without id param" do @params.merge!(:action => "show", :id => nil) - category = Object.new + category = double(:project => :some_project) @controller.instance_variable_set(:@category, category) - stub(category).project { :some_project } resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true) resource.load_resource - @controller.instance_variable_get(:@project).should == :some_project + expect(@controller.instance_variable_get(:@project)).to eq(:some_project) end - it "should not build record through has_one association with :singleton option because it can cause it to delete it in the database" do + it "does not build record through has_one association with :singleton option because it can cause it to delete it in the database" do @params.merge!(:action => "create", :project => {:name => "foobar"}) category = Category.new @controller.instance_variable_set(:@category, category) resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true) resource.load_resource - @controller.instance_variable_get(:@project).name.should == "foobar" - @controller.instance_variable_get(:@project).category.should == category + expect(@controller.instance_variable_get(:@project).name).to eq("foobar") + expect(@controller.instance_variable_get(:@project).category).to eq(category) end - it "should find record through has_one association with :singleton and :shallow options" do + it "finds record through has_one association with :singleton and :shallow options" do project = Project.create! @params.merge!(:action => "show", :id => project.id) resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true, :shallow => true) resource.load_resource - @controller.instance_variable_get(:@project).should == project + expect(@controller.instance_variable_get(:@project)).to eq(project) end - it "should build record through has_one association with :singleton and :shallow options" do + it "builds record through has_one association with :singleton and :shallow options" do @params.merge!(:action => "create", :project => {:name => "foobar"}) resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true, :shallow => true) resource.load_resource - @controller.instance_variable_get(:@project).name.should == "foobar" + expect(@controller.instance_variable_get(:@project).name).to eq("foobar") end - it "should only authorize :show action on parent resource" do + it "only authorizes :show action on parent resource" do project = Project.create! @params.merge!(:action => "new", :project_id => project.id) - stub(@controller).authorize!(:show, project) { raise CanCan::AccessDenied } + allow(@controller).to receive(:authorize!).with(:show, project) { raise CanCan::AccessDenied } resource = CanCan::ControllerResource.new(@controller, :project, :parent => true) - lambda { resource.load_and_authorize_resource }.should raise_error(CanCan::AccessDenied) + expect { resource.load_and_authorize_resource }.to raise_error(CanCan::AccessDenied) end - it "should load the model using a custom class" do + it "loads the model using a custom class" do project = Project.create! @params.merge!(:action => "show", :id => project.id) resource = CanCan::ControllerResource.new(@controller, :class => Project) resource.load_resource - @controller.instance_variable_get(:@project).should == project + expect(@controller.instance_variable_get(:@project)).to eq(project) end - it "should load the model using a custom namespaced class" do + it "loads the model using a custom namespaced class" do project = Sub::Project.create! @params.merge!(:action => "show", :id => project.id) resource = CanCan::ControllerResource.new(@controller, :class => ::Sub::Project) resource.load_resource - @controller.instance_variable_get(:@project).should == project + expect(@controller.instance_variable_get(:@project)).to eq(project) end - it "should authorize based on resource name if class is false" do + it "authorizes based on resource name if class is false" do @params.merge!(:action => "show", :id => "123") - stub(@controller).authorize!(:show, :project) { raise CanCan::AccessDenied } + allow(@controller).to receive(:authorize!).with(:show, :project) { raise CanCan::AccessDenied } resource = CanCan::ControllerResource.new(@controller, :class => false) - lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied) + expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied) end - it "should load and authorize using custom instance name" do + it "loads and authorize using custom instance name" do project = Project.create! @params.merge!(:action => "show", :id => project.id) - stub(@controller).authorize!(:show, project) { raise CanCan::AccessDenied } + allow(@controller).to receive(:authorize!).with(:show, project) { raise CanCan::AccessDenied } resource = CanCan::ControllerResource.new(@controller, :instance_name => :custom_project) - lambda { resource.load_and_authorize_resource }.should raise_error(CanCan::AccessDenied) - @controller.instance_variable_get(:@custom_project).should == project + expect { resource.load_and_authorize_resource }.to raise_error(CanCan::AccessDenied) + expect(@controller.instance_variable_get(:@custom_project)).to eq(project) end - it "should load resource using custom ID param" do + it "loads resource using custom ID param" do project = Project.create! @params.merge!(:action => "show", :the_project => project.id) resource = CanCan::ControllerResource.new(@controller, :id_param => :the_project) resource.load_resource - @controller.instance_variable_get(:@project).should == project + expect(@controller.instance_variable_get(:@project)).to eq(project) end # CVE-2012-5664 - it "should always convert id param to string" do + it "always converts id param to string" do @params.merge!(:action => "show", :the_project => { :malicious => "I am" }) resource = CanCan::ControllerResource.new(@controller, :id_param => :the_project) - resource.send(:id_param).class.should == String + expect(resource.send(:id_param).class).to eq(String) end - it "should load resource using custom find_by attribute" do + it "loads resource using custom find_by attribute" do project = Project.create!(:name => "foo") @params.merge!(:action => "show", :id => "foo") resource = CanCan::ControllerResource.new(@controller, :find_by => :name) resource.load_resource - @controller.instance_variable_get(:@project).should == project + expect(@controller.instance_variable_get(:@project)).to eq(project) end - it "should allow full find method to be passed into find_by option" do + it "allows full find method to be passed into find_by option" do project = Project.create!(:name => "foo") @params.merge!(:action => "show", :id => "foo") resource = CanCan::ControllerResource.new(@controller, :find_by => :find_by_name) resource.load_resource - @controller.instance_variable_get(:@project).should == project + expect(@controller.instance_variable_get(:@project)).to eq(project) end - it "should raise ImplementationRemoved when adding :name option" do - lambda { + it "raises ImplementationRemoved when adding :name option" do + expect { CanCan::ControllerResource.new(@controller, :name => :foo) - }.should raise_error(CanCan::ImplementationRemoved) + }.to raise_error(CanCan::ImplementationRemoved) end - it "should raise ImplementationRemoved exception when specifying :resource option since it is no longer used" do - lambda { + it "raises ImplementationRemoved exception when specifying :resource option since it is no longer used" do + expect { CanCan::ControllerResource.new(@controller, :resource => Project) - }.should raise_error(CanCan::ImplementationRemoved) + }.to raise_error(CanCan::ImplementationRemoved) end - it "should raise ImplementationRemoved exception when passing :nested option" do - lambda { + it "raises ImplementationRemoved exception when passing :nested option" do + expect { CanCan::ControllerResource.new(@controller, :nested => :project) - }.should raise_error(CanCan::ImplementationRemoved) + }.to raise_error(CanCan::ImplementationRemoved) end - it "should skip resource behavior for :only actions in array" do - stub(@controller_class).cancan_skipper { {:load => {nil => {:only => [:index, :show]}}} } + it "skips resource behavior for :only actions in array" do + allow(@controller_class).to receive(:cancan_skipper) { {:load => {nil => {:only => [:index, :show]}}} } @params.merge!(:action => "index") - CanCan::ControllerResource.new(@controller).skip?(:load).should be_true - CanCan::ControllerResource.new(@controller, :some_resource).skip?(:load).should be_false + expect(CanCan::ControllerResource.new(@controller).skip?(:load)).to be_true + expect(CanCan::ControllerResource.new(@controller, :some_resource).skip?(:load)).to be_false @params.merge!(:action => "show") - CanCan::ControllerResource.new(@controller).skip?(:load).should be_true + expect(CanCan::ControllerResource.new(@controller).skip?(:load)).to be_true @params.merge!(:action => "other_action") - CanCan::ControllerResource.new(@controller).skip?(:load).should be_false + expect(CanCan::ControllerResource.new(@controller).skip?(:load)).to be_false end - it "should skip resource behavior for :only one action on resource" do - stub(@controller_class).cancan_skipper { {:authorize => {:project => {:only => :index}}} } + it "skips resource behavior for :only one action on resource" do + allow(@controller_class).to receive(:cancan_skipper) { {:authorize => {:project => {:only => :index}}} } @params.merge!(:action => "index") - CanCan::ControllerResource.new(@controller).skip?(:authorize).should be_false - CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_true + expect(CanCan::ControllerResource.new(@controller).skip?(:authorize)).to be_false + expect(CanCan::ControllerResource.new(@controller, :project).skip?(:authorize)).to be_true @params.merge!(:action => "other_action") - CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_false + expect(CanCan::ControllerResource.new(@controller, :project).skip?(:authorize)).to be_false end - it "should skip resource behavior :except actions in array" do - stub(@controller_class).cancan_skipper { {:load => {nil => {:except => [:index, :show]}}} } + it "skips resource behavior :except actions in array" do + allow(@controller_class).to receive(:cancan_skipper) { {:load => {nil => {:except => [:index, :show]}}} } @params.merge!(:action => "index") - CanCan::ControllerResource.new(@controller).skip?(:load).should be_false + expect(CanCan::ControllerResource.new(@controller).skip?(:load)).to be_false @params.merge!(:action => "show") - CanCan::ControllerResource.new(@controller).skip?(:load).should be_false + expect(CanCan::ControllerResource.new(@controller).skip?(:load)).to be_false @params.merge!(:action => "other_action") - CanCan::ControllerResource.new(@controller).skip?(:load).should be_true - CanCan::ControllerResource.new(@controller, :some_resource).skip?(:load).should be_false + expect(CanCan::ControllerResource.new(@controller).skip?(:load)).to be_true + expect(CanCan::ControllerResource.new(@controller, :some_resource).skip?(:load)).to be_false end - it "should skip resource behavior :except one action on resource" do - stub(@controller_class).cancan_skipper { {:authorize => {:project => {:except => :index}}} } + it "skips resource behavior :except one action on resource" do + allow(@controller_class).to receive(:cancan_skipper) { {:authorize => {:project => {:except => :index}}} } @params.merge!(:action => "index") - CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_false + expect(CanCan::ControllerResource.new(@controller, :project).skip?(:authorize)).to be_false @params.merge!(:action => "other_action") - CanCan::ControllerResource.new(@controller).skip?(:authorize).should be_false - CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_true + expect(CanCan::ControllerResource.new(@controller).skip?(:authorize)).to be_false + expect(CanCan::ControllerResource.new(@controller, :project).skip?(:authorize)).to be_true end - it "should skip loading and authorization" do - stub(@controller_class).cancan_skipper { {:authorize => {nil => {}}, :load => {nil => {}}} } + it "skips loading and authorization" do + allow(@controller_class).to receive(:cancan_skipper) { {:authorize => {nil => {}}, :load => {nil => {}}} } @params.merge!(:action => "new") resource = CanCan::ControllerResource.new(@controller) - lambda { resource.load_and_authorize_resource }.should_not raise_error - @controller.instance_variable_get(:@project).should be_nil + expect { resource.load_and_authorize_resource }.not_to raise_error + expect(@controller.instance_variable_get(:@project)).to be_nil end end diff --git a/spec/cancan/exceptions_spec.rb b/spec/cancan/exceptions_spec.rb index 58e65b78..e1b67796 100644 --- a/spec/cancan/exceptions_spec.rb +++ b/spec/cancan/exceptions_spec.rb @@ -6,15 +6,15 @@ @exception = CanCan::AccessDenied.new(nil, :some_action, :some_subject) end - it "should have action and subject accessors" do - @exception.action.should == :some_action - @exception.subject.should == :some_subject + it "has action and subject accessors" do + expect(@exception.action).to eq(:some_action) + expect(@exception.subject).to eq(:some_subject) end - it "should have a changable default message" do - @exception.message.should == "You are not authorized to access this page." + it "has a changable default message" do + expect(@exception.message).to eq("You are not authorized to access this page.") @exception.default_message = "Unauthorized!" - @exception.message.should == "Unauthorized!" + expect(@exception.message).to eq("Unauthorized!") end end @@ -23,13 +23,13 @@ @exception = CanCan::AccessDenied.new("Access denied!") end - it "should have nil action and subject" do - @exception.action.should be_nil - @exception.subject.should be_nil + it "has nil action and subject" do + expect(@exception.action).to be_nil + expect(@exception.subject).to be_nil end - it "should have passed message" do - @exception.message.should == "Access denied!" + it "has passed message" do + expect(@exception.message).to eq("Access denied!") end end @@ -41,18 +41,18 @@ it "uses i18n for the default message" do I18n.backend.store_translations :en, :unauthorized => {:default => "This is a different message"} @exception = CanCan::AccessDenied.new - @exception.message.should == "This is a different message" + expect(@exception.message).to eq("This is a different message") end it "defaults to a nice message" do @exception = CanCan::AccessDenied.new - @exception.message.should == "You are not authorized to access this page." + expect(@exception.message).to eq("You are not authorized to access this page.") end it "does not use translation if a message is given" do @exception = CanCan::AccessDenied.new("Hey! You're not welcome here") - @exception.message.should == "Hey! You're not welcome here" - @exception.message.should_not == "You are not authorized to access this page." + expect(@exception.message).to eq("Hey! You're not welcome here") + expect(@exception.message).to_not eq("You are not authorized to access this page.") end end end diff --git a/spec/cancan/inherited_resource_spec.rb b/spec/cancan/inherited_resource_spec.rb index 3779fe6f..05f8842a 100644 --- a/spec/cancan/inherited_resource_spec.rb +++ b/spec/cancan/inherited_resource_spec.rb @@ -6,55 +6,55 @@ @controller_class = Class.new @controller = @controller_class.new @ability = Ability.new(nil) - stub(@controller).params { @params } - stub(@controller).current_ability { @ability } - stub(@controller_class).cancan_skipper { {:authorize => {}, :load => {}} } + allow(@controller).to receive(:params).and_return { @params } + allow(@controller).to receive(:current_ability) { @ability } + allow(@controller_class).to receive(:cancan_skipper) { {:authorize => {}, :load => {}} } end - it "show should load resource through @controller.resource" do + it "show loads resource through @controller.resource" do @params.merge!(:action => "show", :id => 123) - stub(@controller).resource { :project_resource } + allow(@controller).to receive(:resource) { :project_resource } CanCan::InheritedResource.new(@controller).load_resource - @controller.instance_variable_get(:@project).should == :project_resource + expect(@controller.instance_variable_get(:@project)).to eq(:project_resource) end - it "new should load through @controller.build_resource" do + it "new loads through @controller.build_resource" do @params[:action] = "new" - stub(@controller).build_resource { :project_resource } + allow(@controller).to receive(:build_resource) { :project_resource } CanCan::InheritedResource.new(@controller).load_resource - @controller.instance_variable_get(:@project).should == :project_resource + expect(@controller.instance_variable_get(:@project)).to eq(:project_resource) end - it "index should load through @controller.association_chain when parent" do + it "index loads through @controller.association_chain when parent" do @params[:action] = "index" - stub(@controller).association_chain { @controller.instance_variable_set(:@project, :project_resource) } + allow(@controller).to receive(:association_chain) { @controller.instance_variable_set(:@project, :project_resource) } CanCan::InheritedResource.new(@controller, :parent => true).load_resource - @controller.instance_variable_get(:@project).should == :project_resource + expect(@controller.instance_variable_get(:@project)).to eq(:project_resource) end - it "index should load through @controller.end_of_association_chain" do + it "index loads through @controller.end_of_association_chain" do @params[:action] = "index" - stub(Project).accessible_by(@ability, :index) { :projects } - stub(@controller).end_of_association_chain { Project } + allow(Project).to receive(:accessible_by).with(@ability, :index) { :projects } + allow(@controller).to receive(:end_of_association_chain) { Project } CanCan::InheritedResource.new(@controller).load_resource - @controller.instance_variable_get(:@projects).should == :projects + expect(@controller.instance_variable_get(:@projects)).to eq(:projects) end - it "should build a new resource with attributes from current ability" do + it "builds a new resource with attributes from current ability" do @params[:action] = "new" @ability.can(:create, Project, :name => "from conditions") - stub(@controller).build_resource { Struct.new(:name).new } + allow(@controller).to receive(:build_resource) { Struct.new(:name).new } resource = CanCan::InheritedResource.new(@controller) resource.load_resource - @controller.instance_variable_get(:@project).name.should == "from conditions" + expect(@controller.instance_variable_get(:@project).name).to eq("from conditions") end - it "should override initial attributes with params" do + it "overrides initial attributes with params" do @params.merge!(:action => "new", :project => {:name => "from params"}) @ability.can(:create, Project, :name => "from conditions") - stub(@controller).build_resource { Struct.new(:name).new } + allow(@controller).to receive(:build_resource) { Struct.new(:name).new } resource = CanCan::ControllerResource.new(@controller) resource.load_resource - @controller.instance_variable_get(:@project).name.should == "from params" + expect(@controller.instance_variable_get(:@project).name).to eq("from params") end end diff --git a/spec/cancan/matchers_spec.rb b/spec/cancan/matchers_spec.rb index de6a439e..e9c594e8 100644 --- a/spec/cancan/matchers_spec.rb +++ b/spec/cancan/matchers_spec.rb @@ -2,32 +2,28 @@ describe "be_able_to" do it "delegates to can?" do - object = Object.new - mock(object).can?(:read, 123) { true } - object.should be_able_to(:read, 123) + expect(object = double).to receive(:can?).with(:read, 123) { true } + expect(object).to be_able_to(:read, 123) end it "reports a nice failure message for should" do - object = Object.new - mock(object).can?(:read, 123) { false } - expect do - object.should be_able_to(:read, 123) - end.should raise_error('expected to be able to :read 123') + expect(object = double).to receive(:can?).with(:read, 123) { false } + expect { + expect(object).to be_able_to(:read, 123) + }.to raise_error('expected to be able to :read 123') end it "reports a nice failure message for should not" do - object = Object.new - mock(object).can?(:read, 123) { true } - expect do - object.should_not be_able_to(:read, 123) - end.should raise_error('expected not to be able to :read 123') + expect(object = double).to receive(:can?).with(:read, 123) { true } + expect { + expect(object).to_not be_able_to(:read, 123) + }.to raise_error('expected not to be able to :read 123') end it "delegates additional arguments to can? and reports in failure message" do - object = Object.new - mock(object).can?(:read, 123, 456) { false } - expect do - object.should be_able_to(:read, 123, 456) - end.should raise_error('expected to be able to :read 123 456') + expect(object = double).to receive(:can?).with(:read, 123, 456) { false } + expect { + expect(object).to be_able_to(:read, 123, 456) + }.to raise_error('expected to be able to :read 123 456') end end diff --git a/spec/cancan/model_adapters/active_record_adapter_spec.rb b/spec/cancan/model_adapters/active_record_adapter_spec.rb index a51774c4..85a772df 100644 --- a/spec/cancan/model_adapters/active_record_adapter_spec.rb +++ b/spec/cancan/model_adapters/active_record_adapter_spec.rb @@ -51,270 +51,269 @@ before(:each) do Article.delete_all Comment.delete_all - @ability = Object.new - @ability.extend(CanCan::Ability) + (@ability = double).extend(CanCan::Ability) @article_table = Article.table_name @comment_table = Comment.table_name end - it "should be for only active record classes" do - CanCan::ModelAdapters::ActiveRecordAdapter.should_not be_for_class(Object) - CanCan::ModelAdapters::ActiveRecordAdapter.should be_for_class(Article) - CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article).should == CanCan::ModelAdapters::ActiveRecordAdapter + it "is for only active record classes" do + expect(CanCan::ModelAdapters::ActiveRecordAdapter).to_not be_for_class(Object) + expect(CanCan::ModelAdapters::ActiveRecordAdapter).to be_for_class(Article) + expect(CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article)).to eq(CanCan::ModelAdapters::ActiveRecordAdapter) end - it "should find record" do + it "finds record" do article = Article.create! - CanCan::ModelAdapters::ActiveRecordAdapter.find(Article, article.id).should == article + expect(CanCan::ModelAdapters::ActiveRecordAdapter.find(Article, article.id)).to eq(article) end - it "should not fetch any records when no abilities are defined" do + it "does not fetch any records when no abilities are defined" do Article.create! - Article.accessible_by(@ability).should be_empty + expect(Article.accessible_by(@ability)).to be_empty end - it "should fetch all articles when one can read all" do + it "fetches all articles when one can read all" do @ability.can :read, Article article = Article.create! - Article.accessible_by(@ability).should == [article] + expect(Article.accessible_by(@ability)).to eq([article]) end - it "should fetch only the articles that are published" do + it "fetches only the articles that are published" do @ability.can :read, Article, :published => true article1 = Article.create!(:published => true) article2 = Article.create!(:published => false) - Article.accessible_by(@ability).should == [article1] + expect(Article.accessible_by(@ability)).to eq([article1]) end - it "should fetch any articles which are published or secret" do + it "fetches any articles which are published or secret" do @ability.can :read, Article, :published => true @ability.can :read, Article, :secret => true article1 = Article.create!(:published => true, :secret => false) article2 = Article.create!(:published => true, :secret => true) article3 = Article.create!(:published => false, :secret => true) article4 = Article.create!(:published => false, :secret => false) - Article.accessible_by(@ability).should == [article1, article2, article3] + expect(Article.accessible_by(@ability)).to eq([article1, article2, article3]) end - it "should fetch only the articles that are published and not secret" do + it "fetches only the articles that are published and not secret" do @ability.can :read, Article, :published => true @ability.cannot :read, Article, :secret => true article1 = Article.create!(:published => true, :secret => false) article2 = Article.create!(:published => true, :secret => true) article3 = Article.create!(:published => false, :secret => true) article4 = Article.create!(:published => false, :secret => false) - Article.accessible_by(@ability).should == [article1] + expect(Article.accessible_by(@ability)).to eq([article1]) end - it "should only read comments for articles which are published" do + it "only reads comments for articles which are published" do @ability.can :read, Comment, :article => { :published => true } comment1 = Comment.create!(:article => Article.create!(:published => true)) comment2 = Comment.create!(:article => Article.create!(:published => false)) - Comment.accessible_by(@ability).should == [comment1] + expect(Comment.accessible_by(@ability)).to eq([comment1]) end - it "should only read comments for visible categories through articles" do + it "only reads comments for visible categories through articles" do @ability.can :read, Comment, :article => { :category => { :visible => true } } comment1 = Comment.create!(:article => Article.create!(:category => Category.create!(:visible => true))) comment2 = Comment.create!(:article => Article.create!(:category => Category.create!(:visible => false))) - Comment.accessible_by(@ability).should == [comment1] + expect(Comment.accessible_by(@ability)).to eq([comment1]) end - it "should allow conditions in SQL and merge with hash conditions" do + it "allows conditions in SQL and merge with hash conditions" do @ability.can :read, Article, :published => true @ability.can :read, Article, ["secret=?", true] article1 = Article.create!(:published => true, :secret => false) article2 = Article.create!(:published => true, :secret => true) article3 = Article.create!(:published => false, :secret => true) article4 = Article.create!(:published => false, :secret => false) - Article.accessible_by(@ability).should == [article1, article2, article3] + expect(Article.accessible_by(@ability)).to eq([article1, article2, article3]) end - it "should allow a scope for conditions" do + it "allows a scope for conditions" do @ability.can :read, Article, Article.where(:secret => true) article1 = Article.create!(:secret => true) article2 = Article.create!(:secret => false) - Article.accessible_by(@ability).should == [article1] + expect(Article.accessible_by(@ability)).to eq([article1]) end - it "should fetch only associated records when using with a scope for conditions" do + it "fetches only associated records when using with a scope for conditions" do @ability.can :read, Article, Article.where(:secret => true) category1 = Category.create!(:visible => false) category2 = Category.create!(:visible => true) article1 = Article.create!(:secret => true, :category => category1) article2 = Article.create!(:secret => true, :category => category2) - category1.articles.accessible_by(@ability).should == [article1] + expect(category1.articles.accessible_by(@ability)).to eq([article1]) end - it "should raise an exception when trying to merge scope with other conditions" do + it "raises an exception when trying to merge scope with other conditions" do @ability.can :read, Article, :published => true @ability.can :read, Article, Article.where(:secret => true) - lambda { Article.accessible_by(@ability) }.should raise_error(CanCan::Error, "Unable to merge an Active Record scope with other conditions. Instead use a hash or SQL for read Article ability.") + expect(lambda { Article.accessible_by(@ability) }).to raise_error(CanCan::Error, "Unable to merge an Active Record scope with other conditions. Instead use a hash or SQL for read Article ability.") end - it "should not allow to fetch records when ability with just block present" do + it "does not allow to fetch records when ability with just block present" do @ability.can :read, Article do false end - lambda { Article.accessible_by(@ability) }.should raise_error(CanCan::Error) + expect(lambda { Article.accessible_by(@ability) }).to raise_error(CanCan::Error) end - it "should not allow to check ability on object against SQL conditions without block" do + it "does not allow to check ability on object against SQL conditions without block" do @ability.can :read, Article, ["secret=?", true] - lambda { @ability.can? :read, Article.new }.should raise_error(CanCan::Error) + expect(lambda { @ability.can? :read, Article.new }).to raise_error(CanCan::Error) end - it "should have false conditions if no abilities match" do - @ability.model_adapter(Article, :read).conditions.should == "'t'='f'" + it "has false conditions if no abilities match" do + expect(@ability.model_adapter(Article, :read).conditions).to eq("'t'='f'") end - it "should return false conditions for cannot clause" do + it "returns false conditions for cannot clause" do @ability.cannot :read, Article - @ability.model_adapter(Article, :read).conditions.should == "'t'='f'" + expect(@ability.model_adapter(Article, :read).conditions).to eq("'t'='f'") end - it "should return SQL for single `can` definition in front of default `cannot` condition" do + it "returns SQL for single `can` definition in front of default `cannot` condition" do @ability.cannot :read, Article @ability.can :read, Article, :published => false, :secret => true - @ability.model_adapter(Article, :read).conditions.should orderlessly_match(%Q["#{@article_table}"."published" = 'f' AND "#{@article_table}"."secret" = 't']) + expect(@ability.model_adapter(Article, :read).conditions).to orderlessly_match(%Q["#{@article_table}"."published" = 'f' AND "#{@article_table}"."secret" = 't']) end - it "should return true condition for single `can` definition in front of default `can` condition" do + it "returns true condition for single `can` definition in front of default `can` condition" do @ability.can :read, Article @ability.can :read, Article, :published => false, :secret => true - @ability.model_adapter(Article, :read).conditions.should == "'t'='t'" + expect(@ability.model_adapter(Article, :read).conditions).to eq("'t'='t'") end - it "should return `false condition` for single `cannot` definition in front of default `cannot` condition" do + it "returns `false condition` for single `cannot` definition in front of default `cannot` condition" do @ability.cannot :read, Article @ability.cannot :read, Article, :published => false, :secret => true - @ability.model_adapter(Article, :read).conditions.should == "'t'='f'" + expect(@ability.model_adapter(Article, :read).conditions).to eq("'t'='f'") end - it "should return `not (sql)` for single `cannot` definition in front of default `can` condition" do + it "returns `not (sql)` for single `cannot` definition in front of default `can` condition" do @ability.can :read, Article @ability.cannot :read, Article, :published => false, :secret => true - @ability.model_adapter(Article, :read).conditions.should orderlessly_match(%Q["not (#{@article_table}"."published" = 'f' AND "#{@article_table}"."secret" = 't')]) + expect(@ability.model_adapter(Article, :read).conditions).to orderlessly_match(%Q["not (#{@article_table}"."published" = 'f' AND "#{@article_table}"."secret" = 't')]) end - it "should return appropriate sql conditions in complex case" do + it "returns appropriate sql conditions in complex case" do @ability.can :read, Article @ability.can :manage, Article, :id => 1 @ability.can :update, Article, :published => true @ability.cannot :update, Article, :secret => true - @ability.model_adapter(Article, :update).conditions.should == %Q[not ("#{@article_table}"."secret" = 't') AND (("#{@article_table}"."published" = 't') OR ("#{@article_table}"."id" = 1))] - @ability.model_adapter(Article, :manage).conditions.should == {:id => 1} - @ability.model_adapter(Article, :read).conditions.should == "'t'='t'" + expect(@ability.model_adapter(Article, :update).conditions).to eq(%Q[not ("#{@article_table}"."secret" = 't') AND (("#{@article_table}"."published" = 't') OR ("#{@article_table}"."id" = 1))]) + expect(@ability.model_adapter(Article, :manage).conditions).to eq({:id => 1}) + expect(@ability.model_adapter(Article, :read).conditions).to eq("'t'='t'") end - it "should return appropriate sql conditions in complex case with nested joins" do + it "returns appropriate sql conditions in complex case with nested joins" do @ability.can :read, Comment, :article => { :category => { :visible => true } } - @ability.model_adapter(Comment, :read).conditions.should == { Category.table_name.to_sym => { :visible => true } } + expect(@ability.model_adapter(Comment, :read).conditions).to eq({ Category.table_name.to_sym => { :visible => true } }) end - it "should return appropriate sql conditions in complex case with nested joins of different depth" do + it "returns appropriate sql conditions in complex case with nested joins of different depth" do @ability.can :read, Comment, :article => { :published => true, :category => { :visible => true } } - @ability.model_adapter(Comment, :read).conditions.should == { Article.table_name.to_sym => { :published => true }, Category.table_name.to_sym => { :visible => true } } + expect(@ability.model_adapter(Comment, :read).conditions).to eq({ Article.table_name.to_sym => { :published => true }, Category.table_name.to_sym => { :visible => true } }) end - it "should not forget conditions when calling with SQL string" do + it "does not forget conditions when calling with SQL string" do @ability.can :read, Article, :published => true @ability.can :read, Article, ['secret=?', false] adapter = @ability.model_adapter(Article, :read) 2.times do - adapter.conditions.should == %Q[(secret='f') OR ("#{@article_table}"."published" = 't')] + expect(adapter.conditions).to eq(%Q[(secret='f') OR ("#{@article_table}"."published" = 't')]) end end - it "should have nil joins if no rules" do - @ability.model_adapter(Article, :read).joins.should be_nil + it "has nil joins if no rules" do + expect(@ability.model_adapter(Article, :read).joins).to be_nil end - it "should have nil joins if no nested hashes specified in conditions" do + it "has nil joins if no nested hashes specified in conditions" do @ability.can :read, Article, :published => false @ability.can :read, Article, :secret => true - @ability.model_adapter(Article, :read).joins.should be_nil + expect(@ability.model_adapter(Article, :read).joins).to be_nil end - it "should merge separate joins into a single array" do + it "merges separate joins into a single array" do @ability.can :read, Article, :project => { :blocked => false } @ability.can :read, Article, :company => { :admin => true } - @ability.model_adapter(Article, :read).joins.inspect.should orderlessly_match([:company, :project].inspect) + expect(@ability.model_adapter(Article, :read).joins.inspect).to orderlessly_match([:company, :project].inspect) end - it "should merge same joins into a single array" do + it "merges same joins into a single array" do @ability.can :read, Article, :project => { :blocked => false } @ability.can :read, Article, :project => { :admin => true } - @ability.model_adapter(Article, :read).joins.should == [:project] + expect(@ability.model_adapter(Article, :read).joins).to eq([:project]) end - it "should merge nested and non-nested joins" do + it "merges nested and non-nested joins" do @ability.can :read, Article, :project => { :blocked => false } @ability.can :read, Article, :project => { :comments => { :spam => true } } - @ability.model_adapter(Article, :read).joins.should == [{:project=>[:comments]}] + expect(@ability.model_adapter(Article, :read).joins).to eq([{:project=>[:comments]}]) end - it "should merge :all conditions with other conditions" do + it "merges :all conditions with other conditions" do user = User.create! article = Article.create!(:user => user) ability = Ability.new(user) ability.can :manage, :all ability.can :manage, Article, :user_id => user.id - Article.accessible_by(ability).should == [article] + expect(Article.accessible_by(ability)).to eq([article]) end - it "should restrict articles given a MetaWhere condition" do + it "restricts articles given a MetaWhere condition" do @ability.can :read, Article, :priority.lt => 2 article1 = Article.create!(:priority => 1) article2 = Article.create!(:priority => 3) - Article.accessible_by(@ability).should == [article1] - @ability.should be_able_to(:read, article1) - @ability.should_not be_able_to(:read, article2) + expect(Article.accessible_by(@ability)).to eq([article1]) + expect(@ability).to be_able_to(:read, article1) + expect(@ability).to_not be_able_to(:read, article2) end - it "should merge MetaWhere and non-MetaWhere conditions" do + it "merges MetaWhere and non-MetaWhere conditions" do @ability.can :read, Article, :priority.lt => 2 @ability.can :read, Article, :priority => 1 article1 = Article.create!(:priority => 1) article2 = Article.create!(:priority => 3) - Article.accessible_by(@ability).should == [article1] - @ability.should be_able_to(:read, article1) - @ability.should_not be_able_to(:read, article2) + expect(Article.accessible_by(@ability)).to eq([article1]) + expect(@ability).to be_able_to(:read, article1) + expect(@ability).to_not be_able_to(:read, article2) end - it "should match any MetaWhere condition" do + it "matches any MetaWhere condition" do adapter = CanCan::ModelAdapters::ActiveRecordAdapter article1 = Article.new(:priority => 1, :name => "Hello World") - adapter.matches_condition?(article1, :priority.eq, 1).should be_true - adapter.matches_condition?(article1, :priority.eq, 2).should be_false - adapter.matches_condition?(article1, :priority.eq_any, [1, 2]).should be_true - adapter.matches_condition?(article1, :priority.eq_any, [2, 3]).should be_false - adapter.matches_condition?(article1, :priority.eq_all, [1, 1]).should be_true - adapter.matches_condition?(article1, :priority.eq_all, [1, 2]).should be_false - adapter.matches_condition?(article1, :priority.ne, 2).should be_true - adapter.matches_condition?(article1, :priority.ne, 1).should be_false - adapter.matches_condition?(article1, :priority.in, [1, 2]).should be_true - adapter.matches_condition?(article1, :priority.in, [2, 3]).should be_false - adapter.matches_condition?(article1, :priority.nin, [2, 3]).should be_true - adapter.matches_condition?(article1, :priority.nin, [1, 2]).should be_false - adapter.matches_condition?(article1, :priority.lt, 2).should be_true - adapter.matches_condition?(article1, :priority.lt, 1).should be_false - adapter.matches_condition?(article1, :priority.lteq, 1).should be_true - adapter.matches_condition?(article1, :priority.lteq, 0).should be_false - adapter.matches_condition?(article1, :priority.gt, 0).should be_true - adapter.matches_condition?(article1, :priority.gt, 1).should be_false - adapter.matches_condition?(article1, :priority.gteq, 1).should be_true - adapter.matches_condition?(article1, :priority.gteq, 2).should be_false - adapter.matches_condition?(article1, :name.like, "%ello worl%").should be_true - adapter.matches_condition?(article1, :name.like, "hello world").should be_true - adapter.matches_condition?(article1, :name.like, "hello%").should be_true - adapter.matches_condition?(article1, :name.like, "h%d").should be_true - adapter.matches_condition?(article1, :name.like, "%helo%").should be_false - adapter.matches_condition?(article1, :name.like, "hello").should be_false - adapter.matches_condition?(article1, :name.like, "hello.world").should be_false + expect(adapter.matches_condition?(article1, :priority.eq, 1)).to be_true + expect(adapter.matches_condition?(article1, :priority.eq, 2)).to be_false + expect(adapter.matches_condition?(article1, :priority.eq_any, [1, 2])).to be_true + expect(adapter.matches_condition?(article1, :priority.eq_any, [2, 3])).to be_false + expect(adapter.matches_condition?(article1, :priority.eq_all, [1, 1])).to be_true + expect(adapter.matches_condition?(article1, :priority.eq_all, [1, 2])).to be_false + expect(adapter.matches_condition?(article1, :priority.ne, 2)).to be_true + expect(adapter.matches_condition?(article1, :priority.ne, 1)).to be_false + expect(adapter.matches_condition?(article1, :priority.in, [1, 2])).to be_true + expect(adapter.matches_condition?(article1, :priority.in, [2, 3])).to be_false + expect(adapter.matches_condition?(article1, :priority.nin, [2, 3])).to be_true + expect(adapter.matches_condition?(article1, :priority.nin, [1, 2])).to be_false + expect(adapter.matches_condition?(article1, :priority.lt, 2)).to be_true + expect(adapter.matches_condition?(article1, :priority.lt, 1)).to be_false + expect(adapter.matches_condition?(article1, :priority.lteq, 1)).to be_true + expect(adapter.matches_condition?(article1, :priority.lteq, 0)).to be_false + expect(adapter.matches_condition?(article1, :priority.gt, 0)).to be_true + expect(adapter.matches_condition?(article1, :priority.gt, 1)).to be_false + expect(adapter.matches_condition?(article1, :priority.gteq, 1)).to be_true + expect(adapter.matches_condition?(article1, :priority.gteq, 2)).to be_false + expect(adapter.matches_condition?(article1, :name.like, "%ello worl%")).to be_true + expect(adapter.matches_condition?(article1, :name.like, "hello world")).to be_true + expect(adapter.matches_condition?(article1, :name.like, "hello%")).to be_true + expect(adapter.matches_condition?(article1, :name.like, "h%d")).to be_true + expect(adapter.matches_condition?(article1, :name.like, "%helo%")).to be_false + expect(adapter.matches_condition?(article1, :name.like, "hello")).to be_false + expect(adapter.matches_condition?(article1, :name.like, "hello.world")).to be_false # For some reason this is reporting "The not_matches MetaWhere condition is not supported." - # adapter.matches_condition?(article1, :name.nlike, "%helo%").should be_true - # adapter.matches_condition?(article1, :name.nlike, "%ello worl%").should be_false + # expect(adapter.matches_condition?(article1, :name.nlike, "%helo%")).to be_true + # expect(adapter.matches_condition?(article1, :name.nlike, "%ello worl%")).to be_false end end end diff --git a/spec/cancan/model_adapters/data_mapper_adapter_spec.rb b/spec/cancan/model_adapters/data_mapper_adapter_spec.rb index 6c6c7f18..eac80d85 100644 --- a/spec/cancan/model_adapters/data_mapper_adapter_spec.rb +++ b/spec/cancan/model_adapters/data_mapper_adapter_spec.rb @@ -26,92 +26,91 @@ class Comment before(:each) do Article.destroy Comment.destroy - @ability = Object.new - @ability.extend(CanCan::Ability) + (@ability = double).extend(CanCan::Ability) end - it "should be for only data mapper classes" do - CanCan::ModelAdapters::DataMapperAdapter.should_not be_for_class(Object) - CanCan::ModelAdapters::DataMapperAdapter.should be_for_class(Article) - CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article).should == CanCan::ModelAdapters::DataMapperAdapter + it "is for only data mapper classes" do + expect(CanCan::ModelAdapters::DataMapperAdapter).not_to be_for_class(Object) + expect(CanCan::ModelAdapters::DataMapperAdapter).to be_for_class(Article) + expect(CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article)).to eq(CanCan::ModelAdapters::DataMapperAdapter) end - it "should find record" do + it "finds record" do article = Article.create - CanCan::ModelAdapters::DataMapperAdapter.find(Article, article.id).should == article + expect(CanCan::ModelAdapters::DataMapperAdapter.find(Article, article.id)).to eq(article) end - it "should not fetch any records when no abilities are defined" do + it "does not fetch any records when no abilities are defined" do Article.create - Article.accessible_by(@ability).should be_empty + expect(Article.accessible_by(@ability)).to be_empty end - it "should fetch all articles when one can read all" do + it "fetches all articles when one can read all" do @ability.can :read, Article article = Article.create - Article.accessible_by(@ability).should == [article] + expect(Article.accessible_by(@ability)).to eq([article]) end - it "should fetch only the articles that are published" do + it "fetches only the articles that are published" do @ability.can :read, Article, :published => true article1 = Article.create(:published => true) article2 = Article.create(:published => false) - Article.accessible_by(@ability).should == [article1] + expect(Article.accessible_by(@ability)).to eq([article1]) end - it "should fetch any articles which are published or secret" do + it "fetches any articles which are published or secret" do @ability.can :read, Article, :published => true @ability.can :read, Article, :secret => true article1 = Article.create(:published => true, :secret => false) article2 = Article.create(:published => true, :secret => true) article3 = Article.create(:published => false, :secret => true) article4 = Article.create(:published => false, :secret => false) - Article.accessible_by(@ability).should == [article1, article2, article3] + expect(Article.accessible_by(@ability)).to eq([article1, article2, article3]) end - it "should fetch only the articles that are published and not secret" do + it "fetches only the articles that are published and not secret" do @ability.can :read, Article, :published => true @ability.cannot :read, Article, :secret => true article1 = Article.create(:published => true, :secret => false) article2 = Article.create(:published => true, :secret => true) article3 = Article.create(:published => false, :secret => true) article4 = Article.create(:published => false, :secret => false) - Article.accessible_by(@ability).should == [article1] + expect(Article.accessible_by(@ability)).to eq([article1]) end - it "should only read comments for articles which are published" do + it "only reads comments for articles which are published" do @ability.can :read, Comment, :article => { :published => true } comment1 = Comment.create(:article => Article.create!(:published => true)) comment2 = Comment.create(:article => Article.create!(:published => false)) - Comment.accessible_by(@ability).should == [comment1] + expect(Comment.accessible_by(@ability)).to eq([comment1]) end - it "should allow conditions in SQL and merge with hash conditions" do + it "allows conditions in SQL and merge with hash conditions" do @ability.can :read, Article, :published => true @ability.can :read, Article, ["secret=?", true] article1 = Article.create(:published => true, :secret => false) article4 = Article.create(:published => false, :secret => false) - Article.accessible_by(@ability).should == [article1] + expect(Article.accessible_by(@ability)).to eq([article1]) end - it "should match gt comparison" do + it "matches gt comparison" do @ability.can :read, Article, :priority.gt => 3 article1 = Article.create(:priority => 4) article2 = Article.create(:priority => 3) - Article.accessible_by(@ability).should == [article1] - @ability.should be_able_to(:read, article1) - @ability.should_not be_able_to(:read, article2) + expect(Article.accessible_by(@ability)).to eq([article1]) + expect(@ability).to be_able_to(:read, article1) + expect(@ability).not_to be_able_to(:read, article2) end - it "should match gte comparison" do + it "matches gte comparison" do @ability.can :read, Article, :priority.gte => 3 article1 = Article.create(:priority => 4) article2 = Article.create(:priority => 3) article3 = Article.create(:priority => 2) - Article.accessible_by(@ability).should == [article1, article2] - @ability.should be_able_to(:read, article1) - @ability.should be_able_to(:read, article2) - @ability.should_not be_able_to(:read, article3) + expect(Article.accessible_by(@ability)).to eq([article1, article2]) + expect(@ability).to be_able_to(:read, article1) + expect(@ability).to be_able_to(:read, article2) + expect(@ability).not_to be_able_to(:read, article3) end # TODO: add more comparison specs diff --git a/spec/cancan/model_adapters/default_adapter_spec.rb b/spec/cancan/model_adapters/default_adapter_spec.rb index b257353c..bc7f0e15 100644 --- a/spec/cancan/model_adapters/default_adapter_spec.rb +++ b/spec/cancan/model_adapters/default_adapter_spec.rb @@ -1,7 +1,7 @@ require "spec_helper" describe CanCan::ModelAdapters::DefaultAdapter do - it "should be default for generic classes" do - CanCan::ModelAdapters::AbstractAdapter.adapter_class(Object).should == CanCan::ModelAdapters::DefaultAdapter + it "is default for generic classes" do + expect(CanCan::ModelAdapters::AbstractAdapter.adapter_class(Object)).to eq(CanCan::ModelAdapters::DefaultAdapter) end end diff --git a/spec/cancan/model_adapters/mongoid_adapter_spec.rb b/spec/cancan/model_adapters/mongoid_adapter_spec.rb index 81ce4a67..1e5ee615 100644 --- a/spec/cancan/model_adapters/mongoid_adapter_spec.rb +++ b/spec/cancan/model_adapters/mongoid_adapter_spec.rb @@ -20,8 +20,7 @@ class MongoidProject describe CanCan::ModelAdapters::MongoidAdapter do context "Mongoid defined" do before(:each) do - @ability = Object.new - @ability.extend(CanCan::Ability) + (@ability = double).extend(CanCan::Ability) end after(:each) do @@ -30,50 +29,50 @@ class MongoidProject end.each(&:drop) end - it "should be for only Mongoid classes" do - CanCan::ModelAdapters::MongoidAdapter.should_not be_for_class(Object) - CanCan::ModelAdapters::MongoidAdapter.should be_for_class(MongoidProject) - CanCan::ModelAdapters::AbstractAdapter.adapter_class(MongoidProject).should == CanCan::ModelAdapters::MongoidAdapter + it "is for only Mongoid classes" do + expect(CanCan::ModelAdapters::MongoidAdapter).not_to be_for_class(Object) + expect(CanCan::ModelAdapters::MongoidAdapter).to be_for_class(MongoidProject) + expect(CanCan::ModelAdapters::AbstractAdapter.adapter_class(MongoidProject)).to eq(CanCan::ModelAdapters::MongoidAdapter) end - it "should find record" do + it "finds record" do project = MongoidProject.create - CanCan::ModelAdapters::MongoidAdapter.find(MongoidProject, project.id).should == project + expect(CanCan::ModelAdapters::MongoidAdapter.find(MongoidProject, project.id)).to eq(project) end - it "should compare properties on mongoid documents with the conditions hash" do + it "compares properties on mongoid documents with the conditions hash" do model = MongoidProject.new @ability.can :read, MongoidProject, :id => model.id - @ability.should be_able_to(:read, model) + expect(@ability).to be_able_to(:read, model) end - it "should be able to read hashes when field is array" do + it "is able to read hashes when field is array" do one_to_three = MongoidProject.create(:numbers => ['one', 'two', 'three']) two_to_five = MongoidProject.create(:numbers => ['two', 'three', 'four', 'five']) @ability.can :foo, MongoidProject, :numbers => 'one' - @ability.should be_able_to(:foo, one_to_three) - @ability.should_not be_able_to(:foo, two_to_five) + expect(@ability).to be_able_to(:foo, one_to_three) + expect(@ability).not_to be_able_to(:foo, two_to_five) end - it "should return [] when no ability is defined so no records are found" do + it "returns [] when no ability is defined so no records are found" do MongoidProject.create(:title => 'Sir') MongoidProject.create(:title => 'Lord') MongoidProject.create(:title => 'Dude') - MongoidProject.accessible_by(@ability, :read).entries.should == [] + expect(MongoidProject.accessible_by(@ability, :read).entries).to eq([]) end - it "should return the correct records based on the defined ability" do + it "returns the correct records based on the defined ability" do @ability.can :read, MongoidProject, :title => "Sir" sir = MongoidProject.create(:title => 'Sir') lord = MongoidProject.create(:title => 'Lord') dude = MongoidProject.create(:title => 'Dude') - MongoidProject.accessible_by(@ability, :read).entries.should == [sir] + expect(MongoidProject.accessible_by(@ability, :read).entries).to eq([sir]) end - it "should return the correct records when a mix of can and cannot rules in defined ability" do + it "returns the correct records when a mix of can and cannot rules in defined ability" do @ability.can :manage, MongoidProject, :title => 'Sir' @ability.cannot :destroy, MongoidProject @@ -81,45 +80,45 @@ class MongoidProject lord = MongoidProject.create(:title => 'Lord') dude = MongoidProject.create(:title => 'Dude') - MongoidProject.accessible_by(@ability, :destroy).entries.should == [sir] + expect(MongoidProject.accessible_by(@ability, :destroy).entries).to eq([sir]) end - it "should be able to mix empty conditions and hashes" do + it "is able to mix empty conditions and hashes" do @ability.can :read, MongoidProject @ability.can :read, MongoidProject, :title => 'Sir' sir = MongoidProject.create(:title => 'Sir') lord = MongoidProject.create(:title => 'Lord') - MongoidProject.accessible_by(@ability, :read).count.should == 2 + expect(MongoidProject.accessible_by(@ability, :read).count).to eq(2) end - it "should return everything when the defined ability is manage all" do + it "returns everything when the defined ability is access all" do @ability.can :manage, :all sir = MongoidProject.create(:title => 'Sir') lord = MongoidProject.create(:title => 'Lord') dude = MongoidProject.create(:title => 'Dude') - MongoidProject.accessible_by(@ability, :read).entries.should == [sir, lord, dude] + expect(MongoidProject.accessible_by(@ability, :read).entries).to eq([sir, lord, dude]) end - it "should allow a scope for conditions" do + it "allows a scope for conditions" do @ability.can :read, MongoidProject, MongoidProject.where(:title => 'Sir') sir = MongoidProject.create(:title => 'Sir') lord = MongoidProject.create(:title => 'Lord') dude = MongoidProject.create(:title => 'Dude') - MongoidProject.accessible_by(@ability, :read).entries.should == [sir] + expect(MongoidProject.accessible_by(@ability, :read).entries).to eq([sir]) end describe "Mongoid::Criteria where clause Symbol extensions using MongoDB expressions" do - it "should handle :field.in" do + it "handles :field.in" do obj = MongoidProject.create(:title => 'Sir') @ability.can :read, MongoidProject, :title.in => ["Sir", "Madam"] - @ability.can?(:read, obj).should == true - MongoidProject.accessible_by(@ability, :read).should == [obj] + expect(@ability.can?(:read, obj)).to eq(true) + expect(MongoidProject.accessible_by(@ability, :read)).to eq([obj]) obj2 = MongoidProject.create(:title => 'Lord') - @ability.can?(:read, obj2).should == false + expect(@ability.can?(:read, obj2)).to be_false end describe "activates only when there are Criteria in the hash" do @@ -128,99 +127,99 @@ class MongoidProject @conditions = {:title.nin => ["Fork", "Spoon"]} @ability.can :read, MongoidProject, @conditions - @ability.should be_able_to(:read, obj) + expect(@ability).to be_able_to(:read, obj) end it "Calls the base version if there are no mongoid criteria" do obj = MongoidProject.new(:title => 'Bird') @conditions = {:id => obj.id} @ability.can :read, MongoidProject, @conditions - @ability.should be_able_to(:read, obj) + expect(@ability).to be_able_to(:read, obj) end end - it "should handle :field.nin" do + it "handles :field.nin" do obj = MongoidProject.create(:title => 'Sir') @ability.can :read, MongoidProject, :title.nin => ["Lord", "Madam"] - @ability.can?(:read, obj).should == true - MongoidProject.accessible_by(@ability, :read).should == [obj] + expect(@ability.can?(:read, obj)).to eq(true) + expect(MongoidProject.accessible_by(@ability, :read)).to eq([obj]) obj2 = MongoidProject.create(:title => 'Lord') - @ability.can?(:read, obj2).should == false + expect(@ability.can?(:read, obj2)).to be_false end - it "should handle :field.size" do + it "handles :field.size" do obj = MongoidProject.create(:titles => ['Palatin', 'Margrave']) @ability.can :read, MongoidProject, :titles.size => 2 - @ability.can?(:read, obj).should == true - MongoidProject.accessible_by(@ability, :read).should == [obj] + expect(@ability.can?(:read, obj)).to eq(true) + expect(MongoidProject.accessible_by(@ability, :read)).to eq([obj]) obj2 = MongoidProject.create(:titles => ['Palatin', 'Margrave', 'Marquis']) - @ability.can?(:read, obj2).should == false + expect(@ability.can?(:read, obj2)).to be_false end - it "should handle :field.exists" do + it "handles :field.exists" do obj = MongoidProject.create(:titles => ['Palatin', 'Margrave']) @ability.can :read, MongoidProject, :titles.exists => true - @ability.can?(:read, obj).should == true - MongoidProject.accessible_by(@ability, :read).should == [obj] + expect(@ability.can?(:read, obj)).to eq(true) + expect(MongoidProject.accessible_by(@ability, :read)).to eq([obj]) obj2 = MongoidProject.create - @ability.can?(:read, obj2).should == false + expect(@ability.can?(:read, obj2)).to be_false end - it "should handle :field.gt" do + it "handles :field.gt" do obj = MongoidProject.create(:age => 50) @ability.can :read, MongoidProject, :age.gt => 45 - @ability.can?(:read, obj).should == true - MongoidProject.accessible_by(@ability, :read).should == [obj] + expect(@ability.can?(:read, obj)).to eq(true) + expect(MongoidProject.accessible_by(@ability, :read)).to eq([obj]) obj2 = MongoidProject.create(:age => 40) - @ability.can?(:read, obj2).should == false + expect(@ability.can?(:read, obj2)).to be_false end - it "should handle instance not saved to database" do + it "handles instance not saved to database" do obj = MongoidProject.new(:title => 'Sir') @ability.can :read, MongoidProject, :title.in => ["Sir", "Madam"] - @ability.can?(:read, obj).should == true + expect(@ability.can?(:read, obj)).to eq(true) # accessible_by only returns saved records - MongoidProject.accessible_by(@ability, :read).entries.should == [] + expect(MongoidProject.accessible_by(@ability, :read).entries).to eq([]) obj2 = MongoidProject.new(:title => 'Lord') - @ability.can?(:read, obj2).should == false + expect(@ability.can?(:read, obj2)).to be_false end end - it "should call where with matching ability conditions" do + it "calls where with matching ability conditions" do obj = MongoidProject.create(:foo => {:bar => 1}) @ability.can :read, MongoidProject, :foo => {:bar => 1} - MongoidProject.accessible_by(@ability, :read).entries.first.should == obj + expect(MongoidProject.accessible_by(@ability, :read).entries.first).to eq(obj) end - it "should exclude from the result if set to cannot" do + it "excludes from the result if set to cannot" do obj = MongoidProject.create(:bar => 1) obj2 = MongoidProject.create(:bar => 2) @ability.can :read, MongoidProject @ability.cannot :read, MongoidProject, :bar => 2 - MongoidProject.accessible_by(@ability, :read).entries.should == [obj] + expect(MongoidProject.accessible_by(@ability, :read).entries).to eq([obj]) end - it "should combine the rules" do + it "combines the rules" do obj = MongoidProject.create(:bar => 1) obj2 = MongoidProject.create(:bar => 2) obj3 = MongoidProject.create(:bar => 3) @ability.can :read, MongoidProject, :bar => 1 @ability.can :read, MongoidProject, :bar => 2 - MongoidProject.accessible_by(@ability, :read).entries.should =~ [obj, obj2] + expect(MongoidProject.accessible_by(@ability, :read).entries).to match_array([obj, obj2]) end - it "should not allow to fetch records when ability with just block present" do + it "does not allow to fetch records when ability with just block present" do @ability.can :read, MongoidProject do false end - lambda { + expect { MongoidProject.accessible_by(@ability) - }.should raise_error(CanCan::Error) + }.to raise_error(CanCan::Error) end end end diff --git a/spec/cancan/rule_spec.rb b/spec/cancan/rule_spec.rb index 9c612cb8..91dab530 100644 --- a/spec/cancan/rule_spec.rb +++ b/spec/cancan/rule_spec.rb @@ -8,45 +8,45 @@ @rule = CanCan::Rule.new(true, :read, Integer, @conditions, nil) end - it "should return no association joins if none exist" do - @rule.associations_hash.should == {} + it "returns no association joins if none exist" do + expect(@rule.associations_hash).to eq({}) end - it "should return no association for joins if just attributes" do + it "returns no association for joins if just attributes" do @conditions[:foo] = :bar - @rule.associations_hash.should == {} + expect(@rule.associations_hash).to eq({}) end - it "should return single association for joins" do + it "returns single association for joins" do @conditions[:foo] = {:bar => 1} - @rule.associations_hash.should == {:foo => {}} + expect(@rule.associations_hash).to eq({:foo => {}}) end - it "should return multiple associations for joins" do + it "returns multiple associations for joins" do @conditions[:foo] = {:bar => 1} @conditions[:test] = {1 => 2} - @rule.associations_hash.should == {:foo => {}, :test => {}} + expect(@rule.associations_hash).to eq({:foo => {}, :test => {}}) end - it "should return nested associations for joins" do + it "returns nested associations for joins" do @conditions[:foo] = {:bar => {1 => 2}} - @rule.associations_hash.should == {:foo => {:bar => {}}} + expect(@rule.associations_hash).to eq({:foo => {:bar => {}}}) end - it "should return no association joins if conditions is nil" do + it "returns no association joins if conditions is nil" do rule = CanCan::Rule.new(true, :read, Integer, nil, nil) - rule.associations_hash.should == {} + expect(rule.associations_hash).to eq({}) end - it "should not be mergeable if conditions are not simple hashes" do + it "is not mergeable if conditions are not simple hashes" do meta_where = OpenStruct.new(:name => 'metawhere', :column => 'test') @conditions[meta_where] = :bar - @rule.should be_unmergeable + expect(@rule).to be_unmergeable end - it "should be mergeable if conditions is an empty hash" do + it "is not mergeable if conditions is an empty hash" do @conditions = {} - @rule.should_not be_unmergeable + expect(@rule).to_not be_unmergeable end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 97169cc1..f45139e4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -12,7 +12,12 @@ config.treat_symbols_as_metadata_keys_with_true_values = true config.filter_run :focus => true config.run_all_when_everything_filtered = true - config.mock_with :rr + config.mock_with :rspec + + config.expect_with :rspec do |c| + c.syntax = :expect + end + config.before(:each) do Project.delete_all Category.delete_all