# frozen_string_literal: true require 'spec_helper' describe Grafana::ProxyService do include ReactiveCachingHelpers let_it_be(:project) { create(:project) } let_it_be(:grafana_integration) { create(:grafana_integration, project: project) } let(:proxy_path) { 'api/v1/query_range' } let(:datasource_id) { '1' } let(:query_params) do { 'query' => 'rate(relevant_metric)', 'start' => '1570441248', 'end' => '1570444848', 'step' => '900' } end let(:cache_params) { [project.id, datasource_id, proxy_path, query_params] } let(:service) do described_class.new(project, datasource_id, proxy_path, query_params) end shared_examples_for 'initializes an instance' do it 'initializes an instance of ProxyService class' do expect(subject).to be_an_instance_of(described_class) expect(subject.project).to eq(project) expect(subject.datasource_id).to eq('1') expect(subject.proxy_path).to eq('api/v1/query_range') expect(subject.query_params).to eq(query_params) end end describe '.from_cache' do subject { described_class.from_cache(*cache_params) } it_behaves_like 'initializes an instance' end describe '#initialize' do subject { service } it_behaves_like 'initializes an instance' end describe '#execute' do subject(:result) { service.execute } context 'when grafana integration is not configured' do before do allow(project).to receive(:grafana_integration).and_return(nil) end it 'returns error' do expect(result).to eq( status: :error, message: 'Proxy support for this API is not available currently' ) end end context 'with caching', :use_clean_rails_memory_store_caching do context 'when value not present in cache' do it 'returns nil' do expect(ExternalServiceReactiveCachingWorker) .to receive(:perform_async) .with(service.class, service.id, *cache_params) expect(result).to eq(nil) end end context 'when value present in cache' do let(:return_value) { { 'http_status' => 200, 'body' => 'body' } } before do stub_reactive_cache(service, return_value, cache_params) end it 'returns cached value' do expect(ReactiveCachingWorker) .not_to receive(:perform_async) .with(service.class, service.id, *cache_params) expect(result[:http_status]).to eq(return_value[:http_status]) expect(result[:body]).to eq(return_value[:body]) end end end context 'call prometheus api' do let(:client) { service.send(:client) } before do synchronous_reactive_cache(service) end context 'connection to grafana datasource succeeds' do let(:response) { instance_double(Gitlab::HTTP::Response) } let(:status_code) { 400 } let(:body) { 'body' } before do allow(client).to receive(:proxy_datasource).and_return(response) allow(response).to receive(:code).and_return(status_code) allow(response).to receive(:body).and_return(body) end it 'returns the http status code and body from prometheus' do expect(result).to eq( http_status: status_code, body: body, status: :success ) end end context 'connection to grafana datasource fails' do before do allow(client).to receive(:proxy_datasource) .and_raise(Grafana::Client::Error, 'Network connection error') end it 'returns error' do expect(result).to eq( status: :error, message: 'Network connection error', http_status: :service_unavailable ) end end end end end