145 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Ruby
		
	
	
	
# frozen_string_literal: true
 | 
						|
 | 
						|
require 'spec_helper'
 | 
						|
 | 
						|
RSpec.describe Gitlab::ExternalAuthorization::Access, :clean_gitlab_redis_cache do
 | 
						|
  subject(:access) { described_class.new(build(:user), 'dummy_label') }
 | 
						|
 | 
						|
  describe '#loaded?' do
 | 
						|
    it 'is `true` when it was loaded recently' do
 | 
						|
      freeze_time do
 | 
						|
        allow(access).to receive(:loaded_at).and_return(5.minutes.ago)
 | 
						|
 | 
						|
        expect(access).to be_loaded
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    it 'is `false` when there is no loading time' do
 | 
						|
      expect(access).not_to be_loaded
 | 
						|
    end
 | 
						|
 | 
						|
    it 'is `false` when there the result was loaded a long time ago' do
 | 
						|
      freeze_time do
 | 
						|
        allow(access).to receive(:loaded_at).and_return(2.weeks.ago)
 | 
						|
 | 
						|
        expect(access).not_to be_loaded
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  describe 'load!' do
 | 
						|
    let(:fake_client) { double('ExternalAuthorization::Client') }
 | 
						|
    let(:fake_response) do
 | 
						|
      double(
 | 
						|
        'Response',
 | 
						|
        'successful?' => true,
 | 
						|
        'valid?' => true,
 | 
						|
        'reason' => nil
 | 
						|
      )
 | 
						|
    end
 | 
						|
 | 
						|
    before do
 | 
						|
      allow(access).to receive(:load_from_cache)
 | 
						|
      allow(fake_client).to receive(:request_access).and_return(fake_response)
 | 
						|
      allow(Gitlab::ExternalAuthorization::Client).to receive(:new) { fake_client }
 | 
						|
    end
 | 
						|
 | 
						|
    context 'when loading from the webservice' do
 | 
						|
      it 'loads from the webservice it the cache was empty' do
 | 
						|
        expect(access).to receive(:load_from_cache)
 | 
						|
        expect(access).to receive(:load_from_service).and_call_original
 | 
						|
 | 
						|
        access.load!
 | 
						|
 | 
						|
        expect(access).to be_loaded
 | 
						|
      end
 | 
						|
 | 
						|
      it 'assigns the accessibility, reason and loaded_at' do
 | 
						|
        allow(fake_response).to receive(:successful?).and_return(false)
 | 
						|
        allow(fake_response).to receive(:reason).and_return('Inaccessible label')
 | 
						|
 | 
						|
        access.load!
 | 
						|
 | 
						|
        expect(access.reason).to eq('Inaccessible label')
 | 
						|
        expect(access).not_to have_access
 | 
						|
        expect(access.loaded_at).not_to be_nil
 | 
						|
      end
 | 
						|
 | 
						|
      it 'returns itself' do
 | 
						|
        expect(access.load!).to eq(access)
 | 
						|
      end
 | 
						|
 | 
						|
      it 'stores the result in redis' do
 | 
						|
        freeze_time do
 | 
						|
          fake_cache = double
 | 
						|
          expect(fake_cache).to receive(:store).with(true, nil, Time.now)
 | 
						|
          expect(access).to receive(:cache).and_return(fake_cache)
 | 
						|
 | 
						|
          access.load!
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      context 'when the request fails' do
 | 
						|
        before do
 | 
						|
          allow(fake_client).to receive(:request_access) do
 | 
						|
            raise ::Gitlab::ExternalAuthorization::RequestFailed, 'Service unavailable'
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        it 'is loaded' do
 | 
						|
          access.load!
 | 
						|
 | 
						|
          expect(access).to be_loaded
 | 
						|
        end
 | 
						|
 | 
						|
        it 'assigns the correct accessibility, reason and loaded_at' do
 | 
						|
          access.load!
 | 
						|
 | 
						|
          expect(access.reason).to eq('Service unavailable')
 | 
						|
          expect(access).not_to have_access
 | 
						|
          expect(access.loaded_at).not_to be_nil
 | 
						|
        end
 | 
						|
 | 
						|
        it 'does not store the result in redis' do
 | 
						|
          fake_cache = double
 | 
						|
          expect(fake_cache).not_to receive(:store)
 | 
						|
          allow(access).to receive(:cache).and_return(fake_cache)
 | 
						|
 | 
						|
          access.load!
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context 'When loading from cache' do
 | 
						|
      let(:fake_cache) { double('ExternalAuthorization::Cache') }
 | 
						|
 | 
						|
      before do
 | 
						|
        allow(access).to receive(:cache).and_return(fake_cache)
 | 
						|
      end
 | 
						|
 | 
						|
      it 'does not load from the webservice' do
 | 
						|
        freeze_time do
 | 
						|
          expect(fake_cache).to receive(:load).and_return([true, nil, Time.now])
 | 
						|
 | 
						|
          expect(access).to receive(:load_from_cache).and_call_original
 | 
						|
          expect(access).not_to receive(:load_from_service)
 | 
						|
 | 
						|
          access.load!
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      it 'loads from the webservice when the cached result was too old' do
 | 
						|
        freeze_time do
 | 
						|
          expect(fake_cache).to receive(:load).and_return([true, nil, 2.days.ago])
 | 
						|
 | 
						|
          expect(access).to receive(:load_from_cache).and_call_original
 | 
						|
          expect(access).to receive(:load_from_service).and_call_original
 | 
						|
          allow(fake_cache).to receive(:store)
 | 
						|
 | 
						|
          access.load!
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |