# frozen_string_literal: true

require 'spec_helper'

describe ReleaseTools::Security::Prepare::FixesVerifier do
  subject(:verifier) { described_class.new }

  let(:client) { stub_const('ReleaseTools::GitlabClient', spy) }
  let(:security_fixes) { [] }
  let(:tracking_issue) { create(:issue) }
  let(:task_issue) { create(:issue) }

  let(:fetcher) do
    instance_double(ReleaseTools::Security::IssuesFetcher, execute: security_fixes)
  end

  let(:notifier) do
    stub_const('ReleaseTools::Slack::ReleaseJobEndNotifier', spy)
  end

  let(:schedule) do
    instance_double(
      ReleaseTools::ReleaseManagers::Schedule,
      active_release_managers: release_managers,
      active_appsec_release_managers: appsec_release_managers
    )
  end

  let(:release_managers) do
    [create(:user, username: 'foo'), create(:user, username: 'baz')]
  end

  let(:appsec_release_managers) do
    [create(:user, username: 'bar'), create(:user, username: 'bat')]
  end

  before do
    allow(ReleaseTools::Security::IssuesFetcher)
      .to receive(:new)
      .and_return(fetcher)

    allow(ReleaseTools::ReleaseManagers::Schedule)
      .to receive(:new)
      .and_return(schedule)

    allow(ReleaseTools::Versions)
      .to receive(:next_versions)
      .and_return(['16.11.1', '16.10.4', '16.9.6'])

    allow(client)
      .to receive_messages(
        current_security_task_issue: task_issue,
        next_security_tracking_issue: tracking_issue,
        security_communication_issue: create(:issue)
      )
  end

  describe '#execute' do
    context 'without security fixes' do
      it 'notifies Delivery and AppSec release managers' do
        expect(client)
          .to receive(:create_issue_note)
          .with(
            ReleaseTools::Project::Release::Tasks,
            {
              issue: task_issue,
              body: a_string_matching(/@foo, @baz :wave/)
            }
          )

        expect(client)
          .to receive(:create_issue_note)
          .with(
            ReleaseTools::Project::GitlabEe,
            {
              issue: tracking_issue,
              body: a_string_matching(/@bar, @bat :wave:/)
            }
          )

        expect(notifier).to receive(:send_notification)

        without_dry_run { verifier.execute }
      end

      it 'requests Delivery to perform a patch release with bug fixes only' do
        expect(client)
          .to receive(:create_issue_note)
          .with(
            ReleaseTools::Project::Release::Tasks,
            {
              issue: task_issue,
              body: a_string_matching(/Perform the patch release with only bug fixes/)
            }
          )

        expect(notifier).to receive(:send_notification)

        without_dry_run { verifier.execute }
      end
    end

    context 'with security issues' do
      let(:security_fixes) do
        [
          ReleaseTools::Security::ImplementationIssue.new(create(:issue), []),
          ReleaseTools::Security::ImplementationIssue.new(create(:issue), [])
        ]
      end

      it 'does nothing' do
        expect(client).not_to receive(:create_issue_note)
        expect(notifier).to receive(:send_notification)

        without_dry_run { verifier.execute }
      end
    end

    context 'with dry-run' do
      it 'does nothing' do
        expect(client).not_to receive(:create_issue_note)
        expect(notifier).to receive(:send_notification)

        verifier.execute
      end
    end
  end
end
