# frozen_string_literal: true

require 'spec_helper'

describe ReleaseTools::Security::ComponentsUpdateTask do
  subject(:components_update_task) { described_class.new(action: action) }

  let(:client) { stub_const('ReleaseTools::GitlabOpsClient', spy) }
  let(:project) { ReleaseTools::Project::ReleaseTools }
  let(:action) { :disable }

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

  let(:pipeline_schedule) do
    create(:pipeline_schedule, id: described_class::PIPELINE_SCHEDULE_ID, description: 'components:update_managed_versioning_projects')
  end

  describe '#execute' do
    before do
      allow(client)
        .to receive(:pipeline_schedule)
        .and_return(pipeline_schedule)
    end

    context 'when disabling the components update task' do
      it 'updates pipelines schedules and sends slack notification' do
        allow(client)
          .to receive(:edit_pipeline_schedule)

        expect(client)
          .to receive(:pipeline_schedule)
          .with(project, 112)

        expect(client)
          .to receive(:pipeline_schedule_take_ownership)
          .with(project, 112)

        expect(client)
          .to receive(:edit_pipeline_schedule)
          .with('gitlab-org/release/tools', 112, active: false)

        expect(notifier)
          .to receive(:send_notification)

        without_dry_run do
          components_update_task.execute
        end
      end
    end

    context 'when enabling the components update task' do
      let(:action) { :enable }

      it 'updates pipelines schedules and sends slack notification' do
        allow(client)
          .to receive(:edit_pipeline_schedule)

        expect(client)
          .to receive(:pipeline_schedule)
          .with(project, 112)

        expect(client)
          .to receive(:pipeline_schedule_take_ownership)
          .with(project, 112)

        expect(client)
          .to receive(:edit_pipeline_schedule)
          .with('gitlab-org/release/tools', 112, active: true)

        expect(notifier)
          .to receive(:send_notification)

        without_dry_run do
          components_update_task.execute
        end
      end
    end

    context 'when something goes wrong' do
      it 'sends a slack notification and raises exception' do
        allow(client)
          .to receive(:edit_pipeline_schedule)
          .and_raise(Gitlab::Error::Error)

        expect(client)
          .to receive(:pipeline_schedule)
          .with(project, 112)

        expect(notifier)
          .to receive(:send_notification)

        without_dry_run do
          expect { components_update_task.execute }
            .to raise_error(described_class::CouldNotUpdateError)
        end
      end
    end

    context 'with a dry-run' do
      it 'only fetches the pipeline schedules' do
        allow(client)
          .to receive(:edit_pipeline_schedule)

        expect(client)
          .to receive(:pipeline_schedule)
          .with(project, 112)

        expect(client)
          .not_to receive(:pipeline_schedule_take_ownership)

        expect(client)
          .not_to receive(:edit_pipeline_schedule)

        allow(notifier)
          .to receive(:send_notification)

        components_update_task.execute
      end
    end
  end
end
