# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Gitlab::Graphql::Aggregations::VulnerabilityStatistics::LazyAggregate do
  let(:query_ctx) do
    {}
  end

  let(:vulnerable) { create(:group) }
  let(:blocks_vulnerable) { 18 }
  let(:blocking_vulnerable) { 38 }

  describe '#initialize' do
    it 'adds the vulnerable to the lazy state' do
      subject = described_class.new(query_ctx, vulnerable)

      expect(subject.lazy_state[:pending_vulnerables]).to match [vulnerable]
      expect(subject.vulnerable).to match vulnerable
    end
  end

  describe '#execute' do
    subject { described_class.new(query_ctx, vulnerable) }

    before do
      subject.instance_variable_set(:@lazy_state, fake_state)
    end

    context 'if the record has already been loaded' do
      let(:fake_state) do
        { pending_vulnerables: Set.new, loaded_objects: { vulnerable => [::Vulnerabilities::ProjectsGrade.new(vulnerable, 'a', [])] } }
      end

      it 'does not make the query again' do
        expect(::Vulnerabilities::ProjectsGrade).not_to receive(:grades_for)

        subject.execute
      end
    end

    context 'if the record has not been loaded' do
      let(:other_vulnerable) { create(:group) }
      let(:fake_state) do
        { pending_vulnerables: Set.new([vulnerable, other_vulnerable]), loaded_objects: {} }
      end

      let(:fake_data) do
        {
          vulnerable => [::Vulnerabilities::ProjectsGrade.new(vulnerable, 'a', [])],
          other_vulnerable => [::Vulnerabilities::ProjectsGrade.new(other_vulnerable, 'b', [])]
        }
      end

      before do
        allow(::Vulnerabilities::ProjectsGrade).to receive(:grades_for).and_return(fake_data)
      end

      it 'makes the query' do
        expect(::Vulnerabilities::ProjectsGrade).to receive(:grades_for).with([vulnerable, other_vulnerable])

        subject.execute
      end

      it 'clears the pending IDs' do
        subject.execute

        expect(subject.lazy_state[:pending_vulnerables]).to be_empty
      end
    end
  end
end
