require 'spec_helper' describe Cancannible do let(:grantee_class) { Member } let(:grantee) { grantee_class.create! } let(:cached_object) do abilities = Ability.new(grantee) abilities.can :read, :all abilities end describe "#abilities" do subject { grantee.abilities } context "when get_cached_abilities provided" do before do Cancannible.get_cached_abilities = proc { |grantee| cached_object } end it "returns the cached object" do expect(cached_object.instance_variable_defined?(:@rules_index)).to eql(true) expect(subject).to eql(cached_object) end context 'when incompatible cached_object' do let(:cached_object) { 'bogative' } it 'returns a new object' do expect(subject).to be_an(Ability) expect(subject).to_not eql(cached_object) end end context "unless reload requested" do subject { grantee.abilities(true) } it 'returns a new object' do expect(subject).to be_an(Ability) expect(subject).to_not eql(cached_object) end end end context "when store_cached_abilities provided" do before do @stored = nil Cancannible.store_cached_abilities = proc { |grantee, ability| @stored = { grantee_id: grantee.id, ability: cached_object } } end it "stores the cached object" do expect { subject }.to change { @stored }.from(nil) expect(@stored[:grantee_id]).to eql(grantee.id) expect(@stored[:ability]).to be_an(Ability) end end context "when get and store cached_abilities provided" do before do @stored = nil @store = 0 Cancannible.get_cached_abilities = proc { |grantee| @stored && cached_object } Cancannible.store_cached_abilities = proc { |grantee, ability| @store += 1 ; @stored = { grantee_id: grantee.id, ability: ability } } end it "stores the cached object on the first call" do expect { subject }.to change { @stored }.from(nil) expect(@store).to eql(1) expect(grantee.abilities.instance_variable_get(:@rules).size).to eql(1) expect(grantee.abilities.instance_variable_get(:@rules_index).size).to eql(1) end it "returns the cached object on the second call" do expect { subject }.to change { @stored }.from(nil) expect(@store).to eql(1) expect { grantee.abilities }.to_not change { @store } expect(grantee.abilities).to be_an(Ability) end it "should re-cache object on the second call if refresh requested" do expect { subject }.to change { @stored }.from(nil) expect(@store).to eql(1) expect { grantee.abilities(true) }.to change { @store }.from(1).to(2) expect(grantee.abilities).to be_an(Ability) end end end end