diff --git a/spec/cancan/active_record_additions_spec.rb b/spec/cancan/active_record_additions_spec.rb deleted file mode 100644 index fc77cf4..0000000 --- a/spec/cancan/active_record_additions_spec.rb +++ /dev/null @@ -1,75 +0,0 @@ -require "spec_helper" - -describe CanCan::ActiveRecordAdditions do - before(:each) do - @model_class = Class.new(Project) - stub(@model_class).scoped { :scoped_stub } - @model_class.send(:include, CanCan::ActiveRecordAdditions) - @ability = Object.new - @ability.extend(CanCan::Ability) - end - - it "should call where('true=false') when no ability is defined so no records are found" do - stub(@model_class).joins { true } # just so it responds to .joins as well - stub(@model_class).where('true=false').stub!.joins(nil) { :no_match } - @model_class.accessible_by(@ability, :read).should == :no_match - end - - it "should call where with matching ability conditions" do - @ability.can :read, @model_class, :foo => {:bar => 1} - stub(@model_class).joins { true } # just so it responds to .joins as well - stub(@model_class).where(:foos => { :bar => 1 }).stub!.joins([:foo]) { :found_records } - @model_class.accessible_by(@ability, :read).should == :found_records - end - - it "should default to :read ability and use scoped when where isn't available" do - @ability.can :read, @model_class, :foo => {:bar => 1} - stub(@model_class).scoped(:conditions => {:foos => {:bar => 1}}, :joins => [:foo]) { :found_records } - @model_class.accessible_by(@ability).should == :found_records - end - - it "should merge association joins and sanitize conditions" do - @ability.can :read, @model_class, :foo => {:bar => 1} - @ability.can :read, @model_class, :too => {:car => 1, :far => {:bar => 1}} - - condition_variants = [ - '(toos.fars.bar=1 AND toos.car=1) OR (foos.bar=1)', # faked sql sanitizer is stupid ;-) - '(toos.car=1 AND toos.fars.bar=1) OR (foos.bar=1)' - ] - joins_variants = [ - [:foo, {:too => [:far]}], - [{:too => [:far]}, :foo] - ] - - condition_variants.each do |condition| - joins_variants.each do |joins| - stub(@model_class).scoped( :conditions => condition, :joins => joins ) { :found_records } - end - end - # @ability.conditions(:read, @model_class).should == '(too.car=1 AND too.far.bar=1) OR (foo.bar=1)' - # @ability.associations_hash(:read, @model_class).should == [{:too => [:far]}, :foo] - @model_class.accessible_by(@ability).should == :found_records - end - - it "should allow to define sql conditions by not hash" do - @ability.can :read, @model_class, :foo => 1 - @ability.can :read, @model_class, ['bar = ?', 1] - stub(@model_class).scoped( :conditions => '(bar = 1) OR (foo=1)', :joins => nil ) { :found_records } - stub(@model_class).scoped{|*args| args.inspect} - @model_class.accessible_by(@ability).should == :found_records - end - - it "should not allow to fetch records when ability with just block present" do - @ability.can :read, @model_class do false end - lambda { - @model_class.accessible_by(@ability) - }.should raise_error(CanCan::Error) - end - - it "should not allow to check ability on object when nonhash sql ability definition without block present" do - @ability.can :read, @model_class, ['bar = ?', 1] - lambda { - @ability.can? :read, @model_class.new - }.should raise_error(CanCan::Error) - end -end diff --git a/spec/cancan/data_mapper_additions_spec.rb b/spec/cancan/data_mapper_additions_spec.rb deleted file mode 100644 index 7671dab..0000000 --- a/spec/cancan/data_mapper_additions_spec.rb +++ /dev/null @@ -1,59 +0,0 @@ -require "spec_helper" -require 'cancan/data_mapper_additions' - -describe CanCan::DataMapperAdditions do - before(:each) do - @model_class = Class.new - @model_class.class_eval do - include DataMapper::Resource - end - stub(@model_class).all(:conditions => ['true=false']) { 'no-match:' } - - @ability = Object.new - @ability.extend(CanCan::Ability) - end - - it "should return no records when no ability is defined so no records are found" do - @model_class.accessible_by(@ability, :read).should == 'no-match:' - end - - it "should call all with matching ability conditions" do - @ability.can :read, @model_class, :foo => {:bar => 1} - stub(@model_class).all(:conditions => {:foo => {:bar => 1}}) { 'found-records:' } - @model_class.accessible_by(@ability, :read).should == 'no-match:found-records:' - end - - it "should merge association joins and sanitize conditions" do - @ability.can :read, @model_class, :foo => {:bar => 1} - @ability.can :read, @model_class, :too => {:car => 1, :far => {:bar => 1}} - - stub(@model_class).all(:conditions => {:foo => {:bar => 1}}) { 'foo:' } - stub(@model_class).all(:conditions => {:too => {:car => 1, :far => {:bar => 1}}}) { 'too:' } - - @model_class.accessible_by(@ability).should == 'no-match:too:foo:' - end - - it "should allow to define sql conditions by not hash" do - @ability.can :read, @model_class, :foo => 1 - @ability.can :read, @model_class, ['bar = ?', 1] - - stub(@model_class).all(:conditions => {:foo => 1}) { 'foo:' } - stub(@model_class).all(:conditions => ['bar = ?', 1]) { 'bar:' } - - @model_class.accessible_by(@ability).should == 'no-match:bar:foo:' - end - - it "should not allow to fetch records when ability with just block present" do - @ability.can :read, @model_class do false end - lambda { - @model_class.accessible_by(@ability) - }.should raise_error(CanCan::Error) - end - - it "should not allow to check ability on object when nonhash sql ability definition without block present" do - @ability.can :read, @model_class, ['bar = ?', 1] - lambda { - @ability.can? :read, @model_class.new - }.should raise_error(CanCan::Error) - end -end diff --git a/spec/cancan/model_adapters/active_record_adapter_spec.rb b/spec/cancan/model_adapters/active_record_adapter_spec.rb new file mode 100644 index 0000000..14143c2 --- /dev/null +++ b/spec/cancan/model_adapters/active_record_adapter_spec.rb @@ -0,0 +1,77 @@ +if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record" + require "spec_helper" + + describe CanCan::ActiveRecordAdditions do + before(:each) do + @model_class = Class.new(Project) + stub(@model_class).scoped { :scoped_stub } + @model_class.send(:include, CanCan::ActiveRecordAdditions) + @ability = Object.new + @ability.extend(CanCan::Ability) + end + + it "should call where('true=false') when no ability is defined so no records are found" do + stub(@model_class).joins { true } # just so it responds to .joins as well + stub(@model_class).where('true=false').stub!.joins(nil) { :no_match } + @model_class.accessible_by(@ability, :read).should == :no_match + end + + it "should call where with matching ability conditions" do + @ability.can :read, @model_class, :foo => {:bar => 1} + stub(@model_class).joins { true } # just so it responds to .joins as well + stub(@model_class).where(:foos => { :bar => 1 }).stub!.joins([:foo]) { :found_records } + @model_class.accessible_by(@ability, :read).should == :found_records + end + + it "should default to :read ability and use scoped when where isn't available" do + @ability.can :read, @model_class, :foo => {:bar => 1} + stub(@model_class).scoped(:conditions => {:foos => {:bar => 1}}, :joins => [:foo]) { :found_records } + @model_class.accessible_by(@ability).should == :found_records + end + + it "should merge association joins and sanitize conditions" do + @ability.can :read, @model_class, :foo => {:bar => 1} + @ability.can :read, @model_class, :too => {:car => 1, :far => {:bar => 1}} + + condition_variants = [ + '(toos.fars.bar=1 AND toos.car=1) OR (foos.bar=1)', # faked sql sanitizer is stupid ;-) + '(toos.car=1 AND toos.fars.bar=1) OR (foos.bar=1)' + ] + joins_variants = [ + [:foo, {:too => [:far]}], + [{:too => [:far]}, :foo] + ] + + condition_variants.each do |condition| + joins_variants.each do |joins| + stub(@model_class).scoped( :conditions => condition, :joins => joins ) { :found_records } + end + end + # @ability.conditions(:read, @model_class).should == '(too.car=1 AND too.far.bar=1) OR (foo.bar=1)' + # @ability.associations_hash(:read, @model_class).should == [{:too => [:far]}, :foo] + @model_class.accessible_by(@ability).should == :found_records + end + + it "should allow to define sql conditions by not hash" do + @ability.can :read, @model_class, :foo => 1 + @ability.can :read, @model_class, ['bar = ?', 1] + stub(@model_class).scoped( :conditions => '(bar = 1) OR (foo=1)', :joins => nil ) { :found_records } + stub(@model_class).scoped{|*args| args.inspect} + @model_class.accessible_by(@ability).should == :found_records + end + + it "should not allow to fetch records when ability with just block present" do + @ability.can :read, @model_class do false end + lambda { + @model_class.accessible_by(@ability) + }.should raise_error(CanCan::Error) + end + + it "should not allow to check ability on object when nonhash sql ability definition without block present" do + @ability.can :read, @model_class, ['bar = ?', 1] + lambda { + @ability.can? :read, @model_class.new + }.should raise_error(CanCan::Error) + 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 new file mode 100644 index 0000000..4abe8ba --- /dev/null +++ b/spec/cancan/model_adapters/data_mapper_adapter_spec.rb @@ -0,0 +1,61 @@ +if ENV["MODEL_ADAPTER"] == "data_mapper" + require "spec_helper" + require 'cancan/data_mapper_additions' + + describe CanCan::DataMapperAdditions do + before(:each) do + @model_class = Class.new + @model_class.class_eval do + include DataMapper::Resource + end + stub(@model_class).all(:conditions => ['true=false']) { 'no-match:' } + + @ability = Object.new + @ability.extend(CanCan::Ability) + end + + it "should return no records when no ability is defined so no records are found" do + @model_class.accessible_by(@ability, :read).should == 'no-match:' + end + + it "should call all with matching ability conditions" do + @ability.can :read, @model_class, :foo => {:bar => 1} + stub(@model_class).all(:conditions => {:foo => {:bar => 1}}) { 'found-records:' } + @model_class.accessible_by(@ability, :read).should == 'no-match:found-records:' + end + + it "should merge association joins and sanitize conditions" do + @ability.can :read, @model_class, :foo => {:bar => 1} + @ability.can :read, @model_class, :too => {:car => 1, :far => {:bar => 1}} + + stub(@model_class).all(:conditions => {:foo => {:bar => 1}}) { 'foo:' } + stub(@model_class).all(:conditions => {:too => {:car => 1, :far => {:bar => 1}}}) { 'too:' } + + @model_class.accessible_by(@ability).should == 'no-match:too:foo:' + end + + it "should allow to define sql conditions by not hash" do + @ability.can :read, @model_class, :foo => 1 + @ability.can :read, @model_class, ['bar = ?', 1] + + stub(@model_class).all(:conditions => {:foo => 1}) { 'foo:' } + stub(@model_class).all(:conditions => ['bar = ?', 1]) { 'bar:' } + + @model_class.accessible_by(@ability).should == 'no-match:bar:foo:' + end + + it "should not allow to fetch records when ability with just block present" do + @ability.can :read, @model_class do false end + lambda { + @model_class.accessible_by(@ability) + }.should raise_error(CanCan::Error) + end + + it "should not allow to check ability on object when nonhash sql ability definition without block present" do + @ability.can :read, @model_class, ['bar = ?', 1] + lambda { + @ability.can? :read, @model_class.new + }.should raise_error(CanCan::Error) + end + end +end diff --git a/spec/cancan/model_adapters/mongoid_adapter_spec.rb b/spec/cancan/model_adapters/mongoid_adapter_spec.rb new file mode 100644 index 0000000..66bb568 --- /dev/null +++ b/spec/cancan/model_adapters/mongoid_adapter_spec.rb @@ -0,0 +1,192 @@ +if ENV["MODEL_ADAPTER"] == "mongoid" + require 'mongoid' # require mongoid first so MongoidAdditions are loaded + require "spec_helper" + + class MongoidCategory + include Mongoid::Document + include CanCan::MongoidAdditions + + references_many :mongoid_projects + end + + class MongoidProject + include Mongoid::Document + include CanCan::MongoidAdditions + + referenced_in :mongoid_category + + class << self + protected + + def sanitize_sql(hash_cond) + hash_cond + end + + def sanitize_hash(hash) + hash.map do |name, value| + if Hash === value + sanitize_hash(value).map{|cond| "#{name}.#{cond}"} + else + "#{name}=#{value}" + end + end.flatten + end + end + end + + Mongoid.configure do |config| + config.master = Mongo::Connection.new('127.0.0.1', 27017).db("cancan_mongoid_additions_spec") + end + + describe CanCan::MongoidAdditions do + context "Mongoid not defined" do + before(:all) do + @mongoid_class = Object.send(:remove_const, :Mongoid) + end + + after(:all) do + Object.const_set(:Mongoid, @mongoid_class) + end + it "should not raise an error for ActiveRecord models" do + @model_class = Class.new(Project) + stub(@model_class).scoped { :scoped_stub } + @model_class.send(:include, CanCan::ActiveRecordAdditions) + @ability = Object.new + @ability.extend(CanCan::Ability) + + @ability.can :read, @model_class + lambda { + @ability.can? :read, @model_class.new + }.should_not raise_error + end + end + + context "Mongoid defined" do + before(:each) do + @model_class = MongoidProject + @ability = Object.new + @ability.extend(CanCan::Ability) + end + + after(:each) do + Mongoid.master.collections.select do |collection| + collection.name !~ /system/ + end.each(&:drop) + end + + it "should compare properties on mongoid documents with the conditions hash" do + model = @model_class.new + @ability.can :read, @model_class, :id => model.id + @ability.should be_able_to :read, model + end + + it "should return [] when no ability is defined so no records are found" do + @model_class.create :title => 'Sir' + @model_class.create :title => 'Lord' + @model_class.create :title => 'Dude' + + @model_class.accessible_by(@ability, :read).entries.should == [] + end + + it "should return the correct records based on the defined ability" do + @ability.can :read, @model_class, :title => "Sir" + sir = @model_class.create :title => 'Sir' + lord = @model_class.create :title => 'Lord' + dude = @model_class.create :title => 'Dude' + + @model_class.accessible_by(@ability, :read).should == [sir] + end + + it "should return everything when the defined ability is manage all" do + @ability.can :manage, :all + sir = @model_class.create :title => 'Sir' + lord = @model_class.create :title => 'Lord' + dude = @model_class.create :title => 'Dude' + + @model_class.accessible_by(@ability, :read).entries.should == [sir, lord, dude] + end + + + describe "Mongoid::Criteria where clause Symbol extensions using MongoDB expressions" do + it "should handle :field.in" do + obj = @model_class.create :title => 'Sir' + @ability.can :read, @model_class, :title.in => ["Sir", "Madam"] + @ability.can?(:read, obj).should == true + @model_class.accessible_by(@ability, :read).should == [obj] + + obj2 = @model_class.create :title => 'Lord' + @ability.can?(:read, obj2).should == false + end + + describe "activates only when there are Criteria in the hash" do + it "Calls where on the model class when there are criteria" do + obj = @model_class.create :title => 'Bird' + @conditions = {:title.nin => ["Fork", "Spoon"]} + mock(@model_class).where(@conditions) {[obj]} + @ability.can :read, @model_class, @conditions + @ability.should be_able_to(:read, obj) + end + it "Calls the base version if there are no mongoid criteria" do + obj = @model_class.new :title => 'Bird' + @conditions = {:id => obj.id} + @ability.can :read, @model_class, @conditions + @ability.should be_able_to(:read, obj) + end + end + + it "should handle :field.nin" do + obj = @model_class.create :title => 'Sir' + @ability.can :read, @model_class, :title.nin => ["Lord", "Madam"] + @ability.can?(:read, obj).should == true + @model_class.accessible_by(@ability, :read).should == [obj] + + obj2 = @model_class.create :title => 'Lord' + @ability.can?(:read, obj2).should == false + end + + it "should handle :field.size" do + obj = @model_class.create :titles => ['Palatin', 'Margrave'] + @ability.can :read, @model_class, :titles.size => 2 + @ability.can?(:read, obj).should == true + @model_class.accessible_by(@ability, :read).should == [obj] + + obj2 = @model_class.create :titles => ['Palatin', 'Margrave', 'Marquis'] + @ability.can?(:read, obj2).should == false + end + + it "should handle :field.exists" do + obj = @model_class.create :titles => ['Palatin', 'Margrave'] + @ability.can :read, @model_class, :titles.exists => true + @ability.can?(:read, obj).should == true + @model_class.accessible_by(@ability, :read).should == [obj] + + obj2 = @model_class.create + @ability.can?(:read, obj2).should == false + end + + it "should handle :field.gt" do + obj = @model_class.create :age => 50 + @ability.can :read, @model_class, :age.gt => 45 + @ability.can?(:read, obj).should == true + @model_class.accessible_by(@ability, :read).should == [obj] + + obj2 = @model_class.create :age => 40 + @ability.can?(:read, obj2).should == false + end + end + + it "should call where with matching ability conditions" do + obj = @model_class.create :foo => {:bar => 1} + @ability.can :read, @model_class, :foo => {:bar => 1} + @model_class.accessible_by(@ability, :read).entries.first.should == obj + end + + it "should not allow to fetch records when ability with just block present" do + @ability.can :read, @model_class do false end + lambda { + @model_class.accessible_by(@ability) + }.should raise_error(CanCan::Error) + end + end + end +end diff --git a/spec/cancan/mongoid_additions_spec.rb b/spec/cancan/mongoid_additions_spec.rb deleted file mode 100644 index 7d5309c..0000000 --- a/spec/cancan/mongoid_additions_spec.rb +++ /dev/null @@ -1,190 +0,0 @@ -require 'mongoid' # require mongoid first so MongoidAdditions are loaded -require "spec_helper" - -class MongoidCategory - include Mongoid::Document - include CanCan::MongoidAdditions - - references_many :mongoid_projects -end - -class MongoidProject - include Mongoid::Document - include CanCan::MongoidAdditions - - referenced_in :mongoid_category - - class << self - protected - - def sanitize_sql(hash_cond) - hash_cond - end - - def sanitize_hash(hash) - hash.map do |name, value| - if Hash === value - sanitize_hash(value).map{|cond| "#{name}.#{cond}"} - else - "#{name}=#{value}" - end - end.flatten - end - end -end - -Mongoid.configure do |config| - config.master = Mongo::Connection.new('127.0.0.1', 27017).db("cancan_mongoid_additions_spec") -end - -describe CanCan::MongoidAdditions do - context "Mongoid not defined" do - before(:all) do - @mongoid_class = Object.send(:remove_const, :Mongoid) - end - - after(:all) do - Object.const_set(:Mongoid, @mongoid_class) - end - it "should not raise an error for ActiveRecord models" do - @model_class = Class.new(Project) - stub(@model_class).scoped { :scoped_stub } - @model_class.send(:include, CanCan::ActiveRecordAdditions) - @ability = Object.new - @ability.extend(CanCan::Ability) - - @ability.can :read, @model_class - lambda { - @ability.can? :read, @model_class.new - }.should_not raise_error - end - end - - context "Mongoid defined" do - before(:each) do - @model_class = MongoidProject - @ability = Object.new - @ability.extend(CanCan::Ability) - end - - after(:each) do - Mongoid.master.collections.select do |collection| - collection.name !~ /system/ - end.each(&:drop) - end - - it "should compare properties on mongoid documents with the conditions hash" do - model = @model_class.new - @ability.can :read, @model_class, :id => model.id - @ability.should be_able_to :read, model - end - - it "should return [] when no ability is defined so no records are found" do - @model_class.create :title => 'Sir' - @model_class.create :title => 'Lord' - @model_class.create :title => 'Dude' - - @model_class.accessible_by(@ability, :read).entries.should == [] - end - - it "should return the correct records based on the defined ability" do - @ability.can :read, @model_class, :title => "Sir" - sir = @model_class.create :title => 'Sir' - lord = @model_class.create :title => 'Lord' - dude = @model_class.create :title => 'Dude' - - @model_class.accessible_by(@ability, :read).should == [sir] - end - - it "should return everything when the defined ability is manage all" do - @ability.can :manage, :all - sir = @model_class.create :title => 'Sir' - lord = @model_class.create :title => 'Lord' - dude = @model_class.create :title => 'Dude' - - @model_class.accessible_by(@ability, :read).entries.should == [sir, lord, dude] - end - - - describe "Mongoid::Criteria where clause Symbol extensions using MongoDB expressions" do - it "should handle :field.in" do - obj = @model_class.create :title => 'Sir' - @ability.can :read, @model_class, :title.in => ["Sir", "Madam"] - @ability.can?(:read, obj).should == true - @model_class.accessible_by(@ability, :read).should == [obj] - - obj2 = @model_class.create :title => 'Lord' - @ability.can?(:read, obj2).should == false - end - - describe "activates only when there are Criteria in the hash" do - it "Calls where on the model class when there are criteria" do - obj = @model_class.create :title => 'Bird' - @conditions = {:title.nin => ["Fork", "Spoon"]} - mock(@model_class).where(@conditions) {[obj]} - @ability.can :read, @model_class, @conditions - @ability.should be_able_to(:read, obj) - end - it "Calls the base version if there are no mongoid criteria" do - obj = @model_class.new :title => 'Bird' - @conditions = {:id => obj.id} - @ability.can :read, @model_class, @conditions - @ability.should be_able_to(:read, obj) - end - end - - it "should handle :field.nin" do - obj = @model_class.create :title => 'Sir' - @ability.can :read, @model_class, :title.nin => ["Lord", "Madam"] - @ability.can?(:read, obj).should == true - @model_class.accessible_by(@ability, :read).should == [obj] - - obj2 = @model_class.create :title => 'Lord' - @ability.can?(:read, obj2).should == false - end - - it "should handle :field.size" do - obj = @model_class.create :titles => ['Palatin', 'Margrave'] - @ability.can :read, @model_class, :titles.size => 2 - @ability.can?(:read, obj).should == true - @model_class.accessible_by(@ability, :read).should == [obj] - - obj2 = @model_class.create :titles => ['Palatin', 'Margrave', 'Marquis'] - @ability.can?(:read, obj2).should == false - end - - it "should handle :field.exists" do - obj = @model_class.create :titles => ['Palatin', 'Margrave'] - @ability.can :read, @model_class, :titles.exists => true - @ability.can?(:read, obj).should == true - @model_class.accessible_by(@ability, :read).should == [obj] - - obj2 = @model_class.create - @ability.can?(:read, obj2).should == false - end - - it "should handle :field.gt" do - obj = @model_class.create :age => 50 - @ability.can :read, @model_class, :age.gt => 45 - @ability.can?(:read, obj).should == true - @model_class.accessible_by(@ability, :read).should == [obj] - - obj2 = @model_class.create :age => 40 - @ability.can?(:read, obj2).should == false - end - end - - it "should call where with matching ability conditions" do - obj = @model_class.create :foo => {:bar => 1} - @ability.can :read, @model_class, :foo => {:bar => 1} - @model_class.accessible_by(@ability, :read).entries.first.should == obj - end - - it "should not allow to fetch records when ability with just block present" do - @ability.can :read, @model_class do false end - lambda { - @model_class.accessible_by(@ability) - }.should raise_error(CanCan::Error) - end - end -end