Instruction:
Write RSpec test file for following ruby class
```ruby
# frozen_string_literal: true

module IncidentManagement
  module TimelineEvents
    # @param timeline_event [IncidentManagement::TimelineEvent]
    # @param user [User]
    # @param params [Hash]
    # @option params [string] note
    # @option params [datetime] occurred_at
    class UpdateService < TimelineEvents::BaseService
      VALIDATION_CONTEXT = :user_input

      def initialize(timeline_event, user, params)
        @timeline_event = timeline_event
        @incident = timeline_event.incident
        @project = incident.project
        @user = user
        @note = params[:note]
        @occurred_at = params[:occurred_at]
        @validation_context = VALIDATION_CONTEXT
        @timeline_event_tags = params[:timeline_event_tag_names]
      end

      def execute
        return error_no_permissions unless allowed?

        unless timeline_event_tags.nil?
          auto_create_predefined_tags(timeline_event_tags)

          # Refetches the tag objects to consider predefined tags as well
          new_tags = timeline_event
                      .project
                      .incident_management_timeline_event_tags
                      .by_names(timeline_event_tags)

          non_existing_tags = validate_tags(new_tags)

          return error("#{_("Following tags don't exist")}: #{non_existing_tags}") if non_existing_tags.any?
        end

        begin
          timeline_event_saved = update_timeline_event_and_event_tags(new_tags)
        rescue ActiveRecord::RecordInvalid
          error_in_save(timeline_event)
        end

        if timeline_event_saved
          add_system_note(timeline_event)

          track_timeline_event('incident_management_timeline_event_edited', timeline_event.project)
          success(timeline_event)
        else
          error_in_save(timeline_event)
        end
      end

      private

      attr_reader :timeline_event, :incident, :project, :user,
        :note, :occurred_at, :validation_context, :timeline_event_tags

      def update_timeline_event_and_event_tags(new_tags)
        ApplicationRecord.transaction do
          timeline_event.timeline_event_tags = new_tags unless timeline_event_tags.nil?

          timeline_event.assign_attributes(update_params)

          timeline_event.save!(context: validation_context)
        end
      end

      def update_params
        { updated_by_user: user, note: note, occurred_at: occurred_at }.compact
      end

      def add_system_note(timeline_event)
        changes = was_changed(timeline_event)
        return if changes == :none

        SystemNoteService.edit_timeline_event(timeline_event, user, was_changed: changes)
      end

      def was_changed(timeline_event)
        changes = timeline_event.previous_changes
        occurred_at_changed = changes.key?('occurred_at')
        note_changed = changes.key?('note')

        return :occurred_at_and_note if occurred_at_changed && note_changed
        return :occurred_at if occurred_at_changed
        return :note if note_changed

        :none
      end

      def validate_tags(new_tags)
        timeline_event_tags.map(&:downcase) - new_tags.map(&:name).map(&:downcase)
      end

      def allowed?
        user&.can?(:edit_incident_management_timeline_event, timeline_event)
      end
    end
  end
end

```

Response:
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe IncidentManagement::TimelineEvents::UpdateService, feature_category: :incident_management do
  let_it_be(:user) { create(:user) }
  let_it_be(:project) { create(:project) }
  let_it_be(:incident) { create(:incident, project: project) }
  let_it_be(:tag1) { create(:incident_management_timeline_event_tag, project: project, name: 'Tag 1') }
  let_it_be(:tag2) { create(:incident_management_timeline_event_tag, project: project, name: 'Tag 2') }
  let_it_be(:tag3) { create(:incident_management_timeline_event_tag, project: project, name: 'Tag 3') }

  let!(:tag_link1) do
    create(:incident_management_timeline_event_tag_link,
      timeline_event: timeline_event,
      timeline_event_tag: tag3
    )
  end

  let!(:timeline_event) { create(:incident_management_timeline_event, project: project, incident: incident) }
  let(:occurred_at) { 1.minute.ago }
  let(:params) { { note: 'Updated note', occurred_at: occurred_at } }
  let(:current_user) { user }

  describe '#execute' do
    shared_examples 'successful tag response' do
      it_behaves_like 'successful response'

      it 'adds the new tag' do
        expect { execute }.to change { timeline_event.timeline_event_tags.count }.by(1)
      end

      it 'adds the new tag link' do
        expect { execute }.to change { IncidentManagement::TimelineEventTagLink.count }.by(1)
      end

      it 'returns the new tag in response' do
        timeline_event = execute.payload[:timeline_event]

        expect(timeline_event.timeline_event_tags.pluck_names).to contain_exactly(tag1.name, tag3.name)
      end
    end

    shared_examples 'successful response' do
      it 'responds with success', :aggregate_failures do
        expect(execute).to be_success
        expect(execute.payload).to eq(timeline_event: timeline_event.reload)
      end

      it_behaves_like 'an incident management tracked event', :incident_management_timeline_event_edited

      it_behaves_like 'Snowplow event tracking with RedisHLL context' do
        let(:namespace) { project.namespace.reload }
        let(:category) { described_class.to_s }
        let(:action) { 'incident_management_timeline_event_edited' }
        let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' }
      end
    end

    shared_examples 'error response' do |message|
      it 'has an informative message' do
        expect(execute).to be_error
        expect(execute.message).to eq(message)
      end

      it 'does not update the note' do
        expect { execute }.not_to change { timeline_event.reload.note }
      end

      it_behaves_like 'does not track incident management event', :incident_management_timeline_event_edited
    end

    shared_examples 'passing the correct was_changed value' do |was_changed|
      it 'passes the correct was_changed value into SysteNoteService.edit_timeline_event' do
        expect(SystemNoteService)
          .to receive(:edit_timeline_event)
          .with(timeline_event, user, was_changed: was_changed)
          .and_call_original

        execute
      end
    end

    subject(:execute) { described_class.new(timeline_event, user, params).execute }

    context 'when user has permissions' do
      before do
        project.add_developer(user)
      end

      it_behaves_like 'successful response'

      it 'updates attributes' do
        expect { execute }.to change { timeline_event.note }.to(params[:note])
          .and change { timeline_event.occurred_at }.to(params[:occurred_at])
      end

      it 'creates a system note' do
        expect { execute }.to change { incident.notes.reload.count }.by(1)
      end

      it_behaves_like 'passing the correct was_changed value', :occurred_at_and_note

      context 'when note is nil' do
        let(:params) { { occurred_at: occurred_at, timeline_event_tag_names: [tag3.name, tag2.name] } }

        it_behaves_like 'successful response'
        it_behaves_like 'passing the correct was_changed value', :occurred_at

        it 'does not update the note' do
          expect { execute }.not_to change { timeline_event.reload.note }
        end

        it 'updates occurred_at' do
          expect { execute }.to change { timeline_event.occurred_at }.to(params[:occurred_at])
        end

        it 'updates the tags' do
          expect { execute }.to change { timeline_event.timeline_event_tags.count }.by(1)
        end
      end

      context 'when note is blank' do
        let(:params) { { note: '', occurred_at: occurred_at, timeline_event_tag_names: [tag3.name, tag2.name] } }

        it_behaves_like 'error response', "Timeline text can't be blank"

        it 'does not add the tags as it rollsback the transaction' do
          expect { execute }.not_to change { timeline_event.timeline_event_tags.count }
        end
      end

      context 'when note is more than 280 characters long' do
        let(:params) { { note: 'n' * 281, occurred_at: occurred_at, timeline_event_tag_names: [tag3.name, tag2.name] } }

        it_behaves_like 'error response', 'Timeline text is too long (maximum is 280 characters)'

        it 'does not add the tags as it rollsback the transaction' do
          expect { execute }.not_to change { timeline_event.timeline_event_tags.count }
        end
      end

      context 'when occurred_at is nil' do
        let(:params) { { note: 'Updated note' } }

        it_behaves_like 'successful response'
        it_behaves_like 'passing the correct was_changed value', :note

        it 'updates the note' do
          expect { execute }.to change { timeline_event.note }.to(params[:note])
        end

        it 'does not update occurred_at' do
          expect { execute }.not_to change { timeline_event.reload.occurred_at }
        end
      end

      context 'when occurred_at is blank' do
        let(:params) { { note: 'Updated note', occurred_at: '', timeline_event_tag_names: [tag3.name, tag2.name] } }

        it_behaves_like 'error response', "Occurred at can't be blank"

        it 'does not add the tags as it rollsback the transaction' do
          expect { execute }.not_to change { timeline_event.timeline_event_tags.count }
        end
      end

      context 'when both occurred_at and note is nil' do
        let(:params) { {} }

        it_behaves_like 'successful response'

        it 'does not update the note' do
          expect { execute }.not_to change { timeline_event.note }
        end

        it 'does not update occurred_at' do
          expect { execute }.not_to change { timeline_event.reload.occurred_at }
        end

        it 'does not call SysteNoteService.edit_timeline_event' do
          expect(SystemNoteService).not_to receive(:edit_timeline_event)

          execute
        end
      end

      context 'when timeline event is non-editable' do
        let!(:timeline_event) do
          create(:incident_management_timeline_event, :non_editable, project: project, incident: incident)
        end

        it_behaves_like 'error response',
          'You have insufficient permissions to manage timeline events for this incident'
      end

      context 'when timeline event tags are passed' do
        context 'when predefined tags are passed' do
          let(:params) do
            {
              note: 'Updated note',
              occurred_at: occurred_at,
              timeline_event_tag_names: ['start time', 'end time', 'response initiated']
            }
          end

          it 'returns the new tag in response' do
            timeline_event = execute.payload[:timeline_event]

            expect(timeline_event.timeline_event_tags.pluck_names).to contain_exactly(
              'Start time', 'End time', 'Response initiated')
          end

          it 'creates the predefined tags on the project' do
            execute

            expect(project.incident_management_timeline_event_tags.pluck_names).to include(
              'Start time', 'End time', 'Response initiated')
          end
        end

        context 'when they exist' do
          let(:params) do
            {
              note: 'Updated note',
              occurred_at: occurred_at,
              timeline_event_tag_names: [tag3.name, tag1.name]
            }
          end

          it_behaves_like 'successful tag response'

          context 'when tag name is of random case' do
            let(:params) do
              {
                note: 'Updated note',
                occurred_at: occurred_at,
                timeline_event_tag_names: ['tAg 3', 'TaG 1']
              }
            end

            it_behaves_like 'successful tag response'
          end

          context 'when tag is removed' do
            let(:params) { { note: 'Updated note', occurred_at: occurred_at, timeline_event_tag_names: [tag2.name] } }

            it_behaves_like 'successful response'

            it 'adds the new tag and removes the old tag' do
              # Since it adds a tag (+1) and removes old tag (-1) so next change in count in 0
              expect { execute }.to change { timeline_event.timeline_event_tags.count }.by(0)
            end

            it 'adds the new tag link and removes the old tag link' do
              # Since it adds a tag link (+1) and removes old tag link (-1) so next change in count in 0
              expect { execute }.to change { IncidentManagement::TimelineEventTagLink.count }.by(0)
            end

            it 'returns the new tag and does not contain the old tag in response' do
              timeline_event = execute.payload[:timeline_event]

              expect(timeline_event.timeline_event_tags.pluck_names).to contain_exactly(tag2.name)
            end
          end

          context 'when all assigned tags are removed' do
            let(:params) { { note: 'Updated note', occurred_at: occurred_at, timeline_event_tag_names: [] } }

            it_behaves_like 'successful response'

            it 'removes all the assigned tags' do
              expect { execute }.to change { timeline_event.timeline_event_tags.count }.by(-1)
            end

            it 'removes all the assigned tag links' do
              expect { execute }.to change { IncidentManagement::TimelineEventTagLink.count }.by(-1)
            end

            it 'does not contain any tags in response' do
              timeline_event = execute.payload[:timeline_event]

              expect(timeline_event.timeline_event_tags.pluck_names).to be_empty
            end
          end
        end

        context 'when they do not exist' do
          let(:params) do
            {
              note: 'Updated note 2',
              occurred_at: occurred_at,
              timeline_event_tag_names: ['non existing tag']
            }
          end

          it_behaves_like 'error response', "Following tags don't exist: [\"non existing tag\"]"

          it 'does not update the note' do
            expect { execute }.not_to change { timeline_event.reload.note }
          end
        end
      end
    end

    context 'when user does not have permissions' do
      before do
        project.add_reporter(user)
      end

      it_behaves_like 'error response',
        'You have insufficient permissions to manage timeline events for this incident'
    end
  end
end


Instruction:
Write RSpec test file for following ruby class
```ruby
# frozen_string_literal: true

module IncidentManagement
  module TimelineEvents
    DEFAULT_ACTION = 'comment'
    DEFAULT_EDITABLE = false
    DEFAULT_AUTO_CREATED = false

    class CreateService < TimelineEvents::BaseService
      def initialize(incident, user, params)
        @project = incident.project
        @incident = incident
        @user = user
        @params = params
        @auto_created = !!params.fetch(:auto_created, DEFAULT_AUTO_CREATED)
      end

      class << self
        def create_incident(incident, user)
          note = "@#{user.username} created the incident"
          occurred_at = incident.created_at
          action = 'issues'

          new(incident, user, note: note, occurred_at: occurred_at, action: action, auto_created: true).execute
        end

        def reopen_incident(incident, user)
          note = "@#{user.username} reopened the incident"
          occurred_at = incident.updated_at
          action = 'issues'

          new(incident, user, note: note, occurred_at: occurred_at, action: action, auto_created: true).execute
        end

        def resolve_incident(incident, user)
          note = "@#{user.username} resolved the incident"
          occurred_at = incident.updated_at
          action = 'status'

          new(incident, user, note: note, occurred_at: occurred_at, action: action, auto_created: true).execute
        end

        def change_incident_status(incident, user, escalation_status)
          status = escalation_status.status_name.to_s.titleize
          note = "@#{user.username} changed the incident status to **#{status}**"
          occurred_at = incident.updated_at
          action = 'status'

          new(incident, user, note: note, occurred_at: occurred_at, action: action, auto_created: true).execute
        end

        def change_severity(incident, user)
          severity_label = IssuableSeverity::SEVERITY_LABELS[incident.severity.to_sym]
          note = "@#{user.username} changed the incident severity to **#{severity_label}**"
          occurred_at = incident.updated_at
          action = 'severity'

          new(incident, user, note: note, occurred_at: occurred_at, action: action, auto_created: true).execute
        end

        def change_labels(incident, user, added_labels: [], removed_labels: [])
          return if Feature.disabled?(:incident_timeline_events_from_labels, incident.project)

          if added_labels.blank? && removed_labels.blank?
            return ServiceResponse.error(message: _('There are no changed labels'))
          end

          labels_note = -> (verb, labels) {
            "#{verb} #{labels.map(&:to_reference).join(' ')} #{'label'.pluralize(labels.count)}" if labels.present?
          }

          added_note = labels_note.call('added', added_labels)
          removed_note = labels_note.call('removed', removed_labels)
          note = "@#{user.username} #{[added_note, removed_note].compact.join(' and ')}"
          occurred_at = incident.updated_at
          action = 'label'

          new(incident, user, note: note, occurred_at: occurred_at, action: action, auto_created: true).execute
        end
      end

      def execute
        return error_no_permissions unless allowed?

        timeline_event_params = {
          project: project,
          incident: incident,
          author: user,
          note: params[:note],
          action: params.fetch(:action, DEFAULT_ACTION),
          note_html: params[:note_html].presence || params[:note],
          occurred_at: params[:occurred_at],
          promoted_from_note: params[:promoted_from_note],
          editable: params.fetch(:editable, DEFAULT_EDITABLE)
        }

        non_existing_tags = validate_tags(project, params[:timeline_event_tag_names])

        return error("#{_("Following tags don't exist")}: #{non_existing_tags}") unless non_existing_tags.empty?

        timeline_event = IncidentManagement::TimelineEvent.new(timeline_event_params)

        if timeline_event.save(context: validation_context)
          add_system_note(timeline_event)

          create_timeline_event_tag_links(timeline_event, params[:timeline_event_tag_names])

          track_timeline_event("incident_management_timeline_event_created", project)

          success(timeline_event)
        else
          error_in_save(timeline_event)
        end
      end

      private

      attr_reader :project, :user, :incident, :params, :auto_created

      def allowed?
        return true if auto_created

        super
      end

      def add_system_note(timeline_event)
        return if auto_created

        SystemNoteService.add_timeline_event(timeline_event)
      end

      def validation_context
        :user_input if !auto_created && params[:promoted_from_note].blank?
      end

      def create_timeline_event_tag_links(timeline_event, tag_names)
        return unless tag_names&.any?

        auto_create_predefined_tags(tag_names)

        # Refetches the tag objects to consider predefined tags as well
        tags = project.incident_management_timeline_event_tags.by_names(tag_names)

        tag_links = tags.select(:id).map do |tag|
          {
            timeline_event_id: timeline_event.id,
            timeline_event_tag_id: tag.id,
            created_at: DateTime.current
          }
        end

        IncidentManagement::TimelineEventTagLink.insert_all(tag_links) if tag_links.any?
      end

      def validate_tags(project, tag_names)
        return [] unless tag_names&.any?

        predefined_tags = TimelineEventTag::PREDEFINED_TAGS.map(&:downcase)

        tag_names_downcased = tag_names.map(&:downcase)

        tags = project.incident_management_timeline_event_tags.by_names(tag_names).pluck_names.map(&:downcase)

        # remove tags from given tag_names and also remove predefined tags which can be auto created
        tag_names_downcased - tags - predefined_tags
      end
    end
  end
end

```

Response:
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe IncidentManagement::TimelineEvents::CreateService, feature_category: :incident_management do
  let_it_be(:user_with_permissions) { create(:user) }
  let_it_be(:user_without_permissions) { create(:user) }
  let_it_be(:project) { create(:project) }
  let_it_be_with_refind(:incident) { create(:incident, project: project) }
  let_it_be(:comment) { create(:note, project: project, noteable: incident) }
  let_it_be(:timeline_event_tag) do
    create(:incident_management_timeline_event_tag, name: 'Test tag 1', project: project)
  end

  let(:args) do
    {
      note: 'note',
      occurred_at: Time.current,
      action: 'new comment',
      promoted_from_note: comment
    }
  end

  let(:editable) { false }
  let(:current_user) { user_with_permissions }
  let(:service) { described_class.new(incident, current_user, args) }

  before_all do
    project.add_developer(user_with_permissions)
    project.add_reporter(user_without_permissions)
  end

  describe '#execute' do
    shared_examples 'error response' do |message|
      it 'has an informative message' do
        expect(execute).to be_error
        expect(execute.message).to eq(message)
      end

      it_behaves_like 'does not track incident management event', :incident_management_timeline_event_created
    end

    shared_examples 'success response' do
      it 'has timeline event', :aggregate_failures do
        expect(execute).to be_success

        result = execute.payload[:timeline_event]
        expect(result).to be_a(::IncidentManagement::TimelineEvent)
        expect(result.author).to eq(current_user)
        expect(result.incident).to eq(incident)
        expect(result.project).to eq(project)
        expect(result.note).to eq(args[:note])
        expect(result.promoted_from_note).to eq(comment)
        expect(result.editable).to eq(editable)
      end

      it_behaves_like 'an incident management tracked event', :incident_management_timeline_event_created

      it_behaves_like 'Snowplow event tracking with RedisHLL context' do
        let(:namespace) { project.namespace.reload }
        let(:category) { described_class.to_s }
        let(:user) { current_user }
        let(:action) { 'incident_management_timeline_event_created' }
        let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' }
      end
    end

    subject(:execute) { service.execute }

    context 'when current user is blank' do
      let(:current_user) { nil }

      it_behaves_like 'error response', 'You have insufficient permissions to manage timeline events for this incident'
    end

    context 'when user does not have permissions to create timeline events' do
      let(:current_user) { user_without_permissions }

      it_behaves_like 'error response', 'You have insufficient permissions to manage timeline events for this incident'
    end

    context 'when error occurs during creation' do
      let(:args) { {} }

      it_behaves_like 'error response', "Occurred at can't be blank and Timeline text can't be blank"
    end

    context 'with default action' do
      let(:args) { { note: 'note', occurred_at: Time.current, promoted_from_note: comment } }

      it_behaves_like 'success response'

      it 'matches the default action', :aggregate_failures do
        result = execute.payload[:timeline_event]

        expect(result.action).to eq(IncidentManagement::TimelineEvents::DEFAULT_ACTION)
      end

      it 'creates a system note' do
        expect { execute }.to change { incident.notes.reload.count }.by(1)
      end

      context 'with auto_created param' do
        let(:args) do
          {
            note: 'note',
            occurred_at: Time.current,
            action: 'new comment',
            promoted_from_note: comment,
            auto_created: auto_created
          }
        end

        context 'when auto_created is true' do
          let(:auto_created) { true }

          it 'does not create a system note' do
            expect { execute }.not_to change { incident.notes.reload.count }
          end

          context 'when user does not have permissions' do
            let(:current_user) { user_without_permissions }

            it_behaves_like 'success response'
          end
        end

        context 'when auto_created is false' do
          let(:auto_created) { false }

          it 'creates a system note' do
            expect { execute }.to change { incident.notes.reload.count }.by(1)
          end
        end
      end
    end

    context 'with non_default action' do
      it_behaves_like 'success response'

      it 'matches the action from arguments', :aggregate_failures do
        result = execute.payload[:timeline_event]

        expect(result.action).to eq(args[:action])
      end
    end

    context 'when timeline event tag names are passed' do
      let(:args) do
        {
          note: 'note',
          occurred_at: Time.current,
          action: 'new comment',
          promoted_from_note: comment,
          timeline_event_tag_names: ['Test tag 1']
        }
      end

      it_behaves_like 'success response'

      it 'matches the tag name' do
        result = execute.payload[:timeline_event]
        expect(result.timeline_event_tags.first).to eq(timeline_event_tag)
      end

      context 'when predefined tags are passed' do
        let(:args) do
          {
            note: 'note',
            occurred_at: Time.current,
            action: 'new comment',
            promoted_from_note: comment,
            timeline_event_tag_names: ['start time', 'end time', 'Impact mitigated']
          }
        end

        it_behaves_like 'success response'

        it 'matches the two tags on the event and creates on project' do
          result = execute.payload[:timeline_event]

          expect(result.timeline_event_tags.count).to eq(3)
          expect(result.timeline_event_tags.by_names(['Start time', 'End time', 'Impact mitigated']).pluck_names)
            .to match_array(['Start time', 'End time', 'Impact mitigated'])
          expect(project.incident_management_timeline_event_tags.pluck_names)
            .to include('Start time', 'End time', 'Impact mitigated')
        end
      end

      context 'when invalid tag names are passed' do
        let(:args) do
          {
            note: 'note',
            occurred_at: Time.current,
            action: 'new comment',
            promoted_from_note: comment,
            timeline_event_tag_names: ['some other time']
          }
        end

        it_behaves_like 'error response', "Following tags don't exist: [\"some other time\"]"

        it 'does not create timeline event' do
          expect { execute }.not_to change(IncidentManagement::TimelineEvent, :count)
        end
      end
    end

    context 'with editable param' do
      let(:args) do
        {
          note: 'note',
          occurred_at: Time.current,
          action: 'new comment',
          promoted_from_note: comment,
          editable: editable
        }
      end

      context 'when editable is true' do
        let(:editable) { true }

        it_behaves_like 'success response'
      end

      context 'when editable is false' do
        let(:editable) { false }

        it_behaves_like 'success response'
      end
    end

    it 'successfully creates a database record', :aggregate_failures do
      expect { execute }.to change { ::IncidentManagement::TimelineEvent.count }.by(1)
    end

    context 'when note is more than 280 characters long' do
      let(:args) do
        {
          note: 'a' * 281,
          occurred_at: Time.current,
          action: 'new comment',
          promoted_from_note: comment,
          auto_created: auto_created
        }
      end

      let(:auto_created) { false }

      context 'when was not promoted from note' do
        let(:comment) { nil }

        context 'when auto_created is true' do
          let(:auto_created) { true }

          it_behaves_like 'success response'
        end

        context 'when auto_created is false' do
          it_behaves_like 'error response', 'Timeline text is too long (maximum is 280 characters)'
        end
      end

      context 'when promoted from note' do
        it_behaves_like 'success response'
      end
    end
  end

  describe 'automatically created timeline events' do
    shared_examples 'successfully created timeline event' do
      it 'creates a timeline event', :aggregate_failures do
        expect(execute).to be_success

        result = execute.payload[:timeline_event]
        expect(result).to be_a(::IncidentManagement::TimelineEvent)
        expect(result.author).to eq(current_user)
        expect(result.incident).to eq(incident)
        expect(result.project).to eq(project)
        expect(result.note).to eq(expected_note)
        expect(result.editable).to eq(false)
        expect(result.action).to eq(expected_action)
      end

      it_behaves_like 'an incident management tracked event', :incident_management_timeline_event_created

      it_behaves_like 'Snowplow event tracking with RedisHLL context' do
        let(:namespace) { project.namespace.reload }
        let(:category) { described_class.to_s }
        let(:user) { current_user }
        let(:action) { 'incident_management_timeline_event_created' }
        let(:label) { 'redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly' }
      end

      it 'successfully creates a database record', :aggregate_failures do
        expect { execute }.to change { ::IncidentManagement::TimelineEvent.count }.by(1)
      end

      it 'does not create a system note' do
        expect { execute }.not_to change { incident.notes.reload.count }
      end
    end

    describe '.create_incident' do
      subject(:execute) { described_class.create_incident(incident, current_user) }

      let(:expected_note) { "@#{current_user.username} created the incident" }
      let(:expected_action) { 'issues' }

      it_behaves_like 'successfully created timeline event'
    end

    describe '.reopen_incident' do
      subject(:execute) { described_class.reopen_incident(incident, current_user) }

      let(:expected_note) { "@#{current_user.username} reopened the incident" }
      let(:expected_action) { 'issues' }

      it_behaves_like 'successfully created timeline event'
    end

    describe '.resolve_incident' do
      subject(:execute) { described_class.resolve_incident(incident, current_user) }

      let(:expected_note) { "@#{current_user.username} resolved the incident" }
      let(:expected_action) { 'status' }

      it_behaves_like 'successfully created timeline event'
    end

    describe '.change_incident_status' do
      subject(:execute) { described_class.change_incident_status(incident, current_user, escalation_status) }

      let(:escalation_status) do
        instance_double('IncidentManagement::IssuableEscalationStatus', status_name: 'acknowledged')
      end

      let(:expected_note) { "@#{current_user.username} changed the incident status to **Acknowledged**" }
      let(:expected_action) { 'status' }

      it_behaves_like 'successfully created timeline event'
    end

    describe '.change_severity' do
      subject(:execute) { described_class.change_severity(incident, current_user) }

      let_it_be(:severity) { create(:issuable_severity, severity: :critical, issue: incident) }

      let(:expected_note) { "@#{current_user.username} changed the incident severity to **Critical - S1**" }
      let(:expected_action) { 'severity' }

      it_behaves_like 'successfully created timeline event'
    end

    describe '.change_labels' do
      subject(:execute) do
        described_class.change_labels(incident, current_user, added_labels: added, removed_labels: removed)
      end

      let_it_be(:labels) { create_list(:label, 4, project: project) }

      let(:expected_action) { 'label' }

      context 'when there are neither added nor removed labels' do
        let(:added) { [] }
        let(:removed) { [] }

        it 'responds with error', :aggregate_failures do
          expect(execute).to be_error
          expect(execute.message).to eq(_('There are no changed labels'))
        end

        it 'does not create timeline event' do
          expect { execute }.not_to change { incident.incident_management_timeline_events.count }
        end
      end

      context 'when there are only added labels' do
        let(:added) { [labels[0], labels[1]] }
        let(:removed) { [] }

        let(:expected_note) { "@#{current_user.username} added #{added.map(&:to_reference).join(' ')} labels" }

        it_behaves_like 'successfully created timeline event'
      end

      context 'when there are only removed labels' do
        let(:added) { [] }
        let(:removed) { [labels[2], labels[3]] }

        let(:expected_note) { "@#{current_user.username} removed #{removed.map(&:to_reference).join(' ')} labels" }

        it_behaves_like 'successfully created timeline event'
      end

      context 'when there are both added and removed labels' do
        let(:added) { [labels[0], labels[1]] }
        let(:removed) { [labels[2], labels[3]] }

        let(:expected_note) do
          added_note = "added #{added.map(&:to_reference).join(' ')} labels"
          removed_note = "removed #{removed.map(&:to_reference).join(' ')} labels"

          "@#{current_user.username} #{added_note} and #{removed_note}"
        end

        it_behaves_like 'successfully created timeline event'
      end

      context 'when there is a single added and single removed labels' do
        let(:added) { [labels[0]] }
        let(:removed) { [labels[3]] }

        let(:expected_note) do
          added_note = "added #{added.first.to_reference} label"
          removed_note = "removed #{removed.first.to_reference} label"

          "@#{current_user.username} #{added_note} and #{removed_note}"
        end

        it_behaves_like 'successfully created timeline event'
      end

      context 'when feature flag is disabled' do
        let(:added) { [labels[0], labels[1]] }
        let(:removed) { [labels[2], labels[3]] }

        before do
          stub_feature_flags(incident_timeline_events_from_labels: false)
        end

        it 'does not create timeline event' do
          expect { execute }.not_to change { incident.incident_management_timeline_events.count }
        end
      end
    end
  end
end


Instruction:
Write RSpec test file for following ruby class
```ruby
# frozen_string_literal: true

module IncidentManagement
  module IssuableEscalationStatuses
    class AfterUpdateService < ::BaseProjectService
      def initialize(issuable, current_user, **params)
        @issuable = issuable
        @escalation_status = issuable.escalation_status

        super(project: issuable.project, current_user: current_user, params: params)
      end

      def execute
        after_update

        ServiceResponse.success(payload: { escalation_status: escalation_status })
      end

      private

      attr_reader :issuable, :escalation_status

      def after_update
        add_status_system_note
        add_timeline_event
      end

      def add_status_system_note
        return unless escalation_status.status_previously_changed?

        SystemNoteService.change_incident_status(issuable, current_user, params[:status_change_reason])
      end

      def add_timeline_event
        return unless escalation_status.status_previously_changed?

        IncidentManagement::TimelineEvents::CreateService
          .change_incident_status(issuable, current_user, escalation_status)
      end
    end
  end
end

::IncidentManagement::IssuableEscalationStatuses::AfterUpdateService.prepend_mod

```

Response:
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe IncidentManagement::IssuableEscalationStatuses::AfterUpdateService,
  feature_category: :incident_management do
  let_it_be(:current_user) { create(:user) }
  let_it_be(:escalation_status, reload: true) { create(:incident_management_issuable_escalation_status, :triggered) }
  let_it_be(:issue, reload: true) { escalation_status.issue }
  let_it_be(:project) { issue.project }

  let(:service) { described_class.new(issue, current_user) }

  subject(:result) do
    issue.update!(incident_management_issuable_escalation_status_attributes: update_params)
    service.execute
  end

  before do
    issue.project.add_developer(current_user)
  end

  context 'with status attributes' do
    let(:status_event) { :acknowledge }
    let(:update_params) { { status_event: status_event } }

    it 'adds a status change system note' do
      expect { result }.to change { issue.reload.notes.count }.by(1)
    end

    it 'adds a status change timeline event' do
      expect(IncidentManagement::TimelineEvents::CreateService)
        .to receive(:change_incident_status)
        .with(issue, current_user, escalation_status)
        .and_call_original

      expect { result }.to change { issue.reload.incident_management_timeline_events.count }.by(1)
    end
  end

  context 'with non-status attributes' do
    let(:update_params) { { updated_at: Time.current } }

    it 'does not add a status change system note or timeline event' do
      expect { result }
        .to not_change { issue.reload.notes.count }
        .and not_change { issue.reload.incident_management_timeline_events.count }
    end
  end
end


Instruction:
Write RSpec test file for following ruby class
```ruby
# frozen_string_literal: true

module IncidentManagement
  module IssuableEscalationStatuses
    class BuildService < ::BaseProjectService
      def initialize(issue)
        @issue = issue

        super(project: issue.project)
      end

      def execute
        issue.escalation_status || issue.build_incident_management_issuable_escalation_status
      end

      private

      attr_reader :issue
    end
  end
end

```

Response:
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe IncidentManagement::IssuableEscalationStatuses::BuildService, feature_category: :incident_management do
  let_it_be(:project) { create(:project) }
  let_it_be(:incident, reload: true) { create(:incident, project: project) }

  let(:service) { described_class.new(incident) }

  subject(:execute) { service.execute }

  it_behaves_like 'initializes new escalation status with expected attributes'
end


Instruction:
Write RSpec test file for following ruby class
```ruby
# frozen_string_literal: true

module IncidentManagement
  module IssuableEscalationStatuses
    class PrepareUpdateService < ::BaseProjectService
      include Gitlab::Utils::StrongMemoize

      SUPPORTED_PARAMS = %i[status].freeze

      def initialize(issuable, current_user, params)
        @issuable = issuable
        @param_errors = []

        super(project: issuable.project, current_user: current_user, params: params)
      end

      def execute
        return availability_error unless available?

        filter_unsupported_params
        filter_attributes
        filter_redundant_params

        return invalid_param_error if param_errors.any?

        ServiceResponse.success(payload: { escalation_status: params })
      end

      private

      attr_reader :issuable, :param_errors

      def available?
        issuable.supports_escalation? && user_has_permissions?
      end

      def user_has_permissions?
        current_user&.can?(:update_escalation_status, issuable)
      end

      def escalation_status
        strong_memoize(:escalation_status) do
          issuable.escalation_status || BuildService.new(issuable).execute
        end
      end

      def filter_unsupported_params
        params.slice!(*supported_params)
      end

      def supported_params
        SUPPORTED_PARAMS
      end

      def filter_attributes
        filter_status
      end

      def filter_status
        status = params.delete(:status)
        return unless status

        status_event = escalation_status.status_event_for(status)
        add_param_error(:status) && return unless status_event

        params[:status_event] = status_event
      end

      def filter_redundant_params
        params.delete_if do |key, value|
          current_params.key?(key) && current_params[key] == value
        end
      end

      def current_params
        strong_memoize(:current_params) do
          {
            status_event: escalation_status.status_event_for(escalation_status.status_name)
          }
        end
      end

      def add_param_error(param)
        param_errors << param
      end

      def availability_error
        ServiceResponse.error(message: 'Escalation status updates are not available for this issue, user, or project.')
      end

      def invalid_param_error
        ServiceResponse.error(message: "Invalid value was provided for parameters: #{param_errors.join(', ')}")
      end
    end
  end
end

::IncidentManagement::IssuableEscalationStatuses::PrepareUpdateService.prepend_mod

```

Response:
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe IncidentManagement::IssuableEscalationStatuses::PrepareUpdateService, factory_default: :keep,
  feature_category: :incident_management do
  let_it_be(:project) { create_default(:project) }
  let_it_be(:escalation_status) { create(:incident_management_issuable_escalation_status, :triggered) }
  let_it_be(:user_with_permissions) { create(:user) }

  let(:current_user) { user_with_permissions }
  let(:issue) { escalation_status.issue }
  let(:status) { :acknowledged }
  let(:params) { { status: status } }
  let(:service) { described_class.new(issue, current_user, params) }

  subject(:result) { service.execute }

  before do
    issue.project.add_developer(user_with_permissions)
  end

  shared_examples 'successful response' do |payload|
    it 'returns valid parameters which can be used to update the issue' do
      expect(result).to be_success
      expect(result.payload).to eq(escalation_status: payload)
    end
  end

  shared_examples 'error response' do |message|
    specify do
      expect(result).to be_error
      expect(result.message).to eq(message)
    end
  end

  shared_examples 'availability error response' do
    include_examples 'error response', 'Escalation status updates are not available for this issue, user, or project.'
  end

  shared_examples 'invalid params error response' do
    include_examples 'error response', 'Invalid value was provided for parameters: status'
  end

  it_behaves_like 'successful response', { status_event: :acknowledge }

  context 'when user is anonymous' do
    let(:current_user) { nil }

    it_behaves_like 'availability error response'
  end

  context 'when user does not have permissions' do
    let(:current_user) { create(:user) }

    it_behaves_like 'availability error response'
  end

  context 'when called with an unsupported issue type' do
    let(:issue) { create(:issue) }

    it_behaves_like 'availability error response'
  end

  context 'when an IssuableEscalationStatus record for the issue does not exist' do
    let(:issue) { create(:incident) }

    it_behaves_like 'successful response', { status_event: :acknowledge }

    it 'initializes an issuable escalation status record' do
      expect { result }.not_to change(::IncidentManagement::IssuableEscalationStatus, :count)
      expect(issue.escalation_status).to be_present
    end
  end

  context 'when called nil params' do
    let(:params) { nil }

    it 'raises an exception' do
      expect { result }.to raise_error NoMethodError
    end
  end

  context 'when called without params' do
    let(:params) { {} }

    it_behaves_like 'successful response', {}
  end

  context 'when called with unsupported params' do
    let(:params) { { escalations_started_at: Time.current } }

    it_behaves_like 'successful response', {}
  end

  context 'with status param' do
    context 'when status matches the current status' do
      let(:params) { { status: :triggered } }

      it_behaves_like 'successful response', {}
    end

    context 'when status is unsupported' do
      let(:params) { { status: :mitigated } }

      it_behaves_like 'invalid params error response'
    end

    context 'when status is a String' do
      let(:params) { { status: 'acknowledged' } }

      it_behaves_like 'successful response', { status_event: :acknowledge }
    end
  end
end


Instruction:
Write RSpec test file for following ruby class
```ruby
# frozen_string_literal: true

module IncidentManagement
  module IssuableEscalationStatuses
    class CreateService < ::BaseProjectService
      def initialize(issue)
        @issue = issue

        super(project: issue.project)
      end

      def execute
        escalation_status = BuildService.new(issue).execute

        if escalation_status.save
          ServiceResponse.success(payload: { escalation_status: escalation_status })
        else
          ServiceResponse.error(message: escalation_status.errors&.full_messages)
        end
      end

      private

      attr_reader :issue
    end
  end
end

```

Response:
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe IncidentManagement::IssuableEscalationStatuses::CreateService, feature_category: :incident_management do
  let_it_be(:project) { create(:project) }

  let(:incident) { create(:incident, project: project) }
  let(:service) { described_class.new(incident) }

  subject(:execute) { service.execute }

  it 'creates an escalation status for the incident with no policy set' do
    expect { execute }.to change { incident.reload.escalation_status }.from(nil)

    status = incident.escalation_status

    expect(status.policy_id).to eq(nil)
    expect(status.escalations_started_at).to eq(nil)
    expect(status.status_name).to eq(:triggered)
  end

  context 'existing escalation status' do
    let!(:existing_status) { create(:incident_management_issuable_escalation_status, issue: incident) }

    it 'exits without changing anything' do
      expect { execute }.not_to change { incident.reload.escalation_status }
    end
  end
end


Instruction:
Write RSpec test file for following ruby class
```ruby
# frozen_string_literal: true

module IncidentManagement
  module PagerDuty
    class ProcessWebhookService < ::BaseProjectService
      include Gitlab::Utils::StrongMemoize
      include IncidentManagement::Settings

      # https://developer.pagerduty.com/docs/webhooks/webhook-behavior/#size-limit
      PAGER_DUTY_PAYLOAD_SIZE_LIMIT = 55.kilobytes

      # https://developer.pagerduty.com/docs/db0fa8c8984fc-overview#event-types
      PAGER_DUTY_PROCESSABLE_EVENT_TYPES = %w[incident.triggered].freeze

      def initialize(project, payload)
        super(project: project)

        @payload = payload
      end

      def execute(token)
        return forbidden unless webhook_setting_active?
        return unauthorized unless valid_token?(token)
        return bad_request unless valid_payload_size?

        process_incidents

        accepted
      end

      private

      attr_reader :payload

      def process_incidents
        event = pager_duty_processable_event
        return unless event

        ::IncidentManagement::PagerDuty::ProcessIncidentWorker
          .perform_async(project.id, event['incident'])
      end

      def pager_duty_processable_event
        strong_memoize(:pager_duty_processable_event) do
          event = ::PagerDuty::WebhookPayloadParser.call(payload.to_h)

          event if event['event'].to_s.in?(PAGER_DUTY_PROCESSABLE_EVENT_TYPES)
        end
      end

      def webhook_setting_active?
        incident_management_setting.pagerduty_active?
      end

      def valid_token?(token)
        token && incident_management_setting.pagerduty_token == token
      end

      def valid_payload_size?
        Gitlab::Utils::DeepSize.new(payload, max_size: PAGER_DUTY_PAYLOAD_SIZE_LIMIT).valid?
      end

      def accepted
        ServiceResponse.success(http_status: :accepted)
      end

      def forbidden
        ServiceResponse.error(message: 'Forbidden', http_status: :forbidden)
      end

      def unauthorized
        ServiceResponse.error(message: 'Unauthorized', http_status: :unauthorized)
      end

      def bad_request
        ServiceResponse.error(message: 'Bad Request', http_status: :bad_request)
      end
    end
  end
end

```

Response:
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe IncidentManagement::PagerDuty::ProcessWebhookService, feature_category: :incident_management do
  let_it_be(:project, reload: true) { create(:project) }

  describe '#execute' do
    shared_examples 'does not process incidents' do
      it 'does not process incidents' do
        expect(::IncidentManagement::PagerDuty::ProcessIncidentWorker).not_to receive(:perform_async)

        execute
      end
    end

    let(:webhook_payload) { Gitlab::Json.parse(fixture_file('pager_duty/webhook_incident_trigger.json')) }
    let(:token) { nil }

    subject(:execute) { described_class.new(project, webhook_payload).execute(token) }

    context 'when PagerDuty webhook setting is active' do
      let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: true) }

      context 'when token is valid' do
        let(:token) { incident_management_setting.pagerduty_token }

        context 'when webhook payload has acceptable size' do
          it 'responds with Accepted' do
            result = execute

            expect(result).to be_success
            expect(result.http_status).to eq(:accepted)
          end

          it 'processes issues' do
            incident_payload = ::PagerDuty::WebhookPayloadParser.call(webhook_payload)['incident']

            expect(::IncidentManagement::PagerDuty::ProcessIncidentWorker)
              .to receive(:perform_async)
              .with(project.id, incident_payload)
              .once

            execute
          end
        end

        context 'when webhook payload is too big' do
          let(:deep_size) { instance_double(Gitlab::Utils::DeepSize, valid?: false) }

          before do
            allow(Gitlab::Utils::DeepSize)
              .to receive(:new)
              .with(webhook_payload, max_size: described_class::PAGER_DUTY_PAYLOAD_SIZE_LIMIT)
              .and_return(deep_size)
          end

          it 'responds with Bad Request' do
            result = execute

            expect(result).to be_error
            expect(result.http_status).to eq(:bad_request)
          end

          it_behaves_like 'does not process incidents'
        end

        context 'when webhook payload is blank' do
          let(:webhook_payload) { nil }

          it 'responds with Accepted' do
            result = execute

            expect(result).to be_success
            expect(result.http_status).to eq(:accepted)
          end

          it_behaves_like 'does not process incidents'
        end
      end

      context 'when token is invalid' do
        let(:token) { 'invalid-token' }

        it 'responds with Unauthorized' do
          result = execute

          expect(result).to be_error
          expect(result.http_status).to eq(:unauthorized)
        end

        it_behaves_like 'does not process incidents'
      end
    end

    context 'when both tokens are nil' do
      let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: false) }

      let(:token) { nil }

      before do
        incident_management_setting.update_column(:pagerduty_active, true)
      end

      it 'responds with Unauthorized' do
        result = execute

        expect(result).to be_error
        expect(result.http_status).to eq(:unauthorized)
      end

      it_behaves_like 'does not process incidents'
    end

    context 'when PagerDuty webhook setting is not active' do
      let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: false) }

      it 'responds with Forbidden' do
        result = execute

        expect(result).to be_error
        expect(result.http_status).to eq(:forbidden)
      end

      it_behaves_like 'does not process incidents'
    end
  end
end


Instruction:
Write RSpec test file for following ruby class
```ruby
# frozen_string_literal: true

module IncidentManagement
  module PagerDuty
    class CreateIncidentIssueService < BaseService
      include IncidentManagement::Settings

      def initialize(project, incident_payload)
        super(project, Users::Internal.alert_bot, incident_payload)
      end

      def execute
        return forbidden unless webhook_available?

        create_incident
      end

      private

      alias_method :incident_payload, :params

      def create_incident
        ::IncidentManagement::Incidents::CreateService.new(
          project,
          current_user,
          title: issue_title,
          description: issue_description
        ).execute
      end

      def webhook_available?
        incident_management_setting.pagerduty_active?
      end

      def forbidden
        ServiceResponse.error(message: 'Forbidden', http_status: :forbidden)
      end

      def issue_title
        incident_payload['title']
      end

      def issue_description
        Gitlab::IncidentManagement::PagerDuty::IncidentIssueDescription.new(incident_payload).to_s
      end
    end
  end
end

```

Response:
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe IncidentManagement::PagerDuty::CreateIncidentIssueService, feature_category: :incident_management do
  let_it_be(:project, reload: true) { create(:project) }
  let_it_be(:user) { Users::Internal.alert_bot }

  let(:webhook_payload) { Gitlab::Json.parse(fixture_file('pager_duty/webhook_incident_trigger.json')) }
  let(:parsed_payload) { ::PagerDuty::WebhookPayloadParser.call(webhook_payload) }
  let(:incident_payload) { parsed_payload['incident'] }

  subject(:execute) { described_class.new(project, incident_payload).execute }

  describe '#execute' do
    context 'when PagerDuty webhook setting is active' do
      let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: true) }

      context 'when issue can be created' do
        it 'creates a new issue' do
          expect { execute }.to change(Issue, :count).by(1)
        end

        it 'responds with success' do
          response = execute

          expect(response).to be_success
          expect(response.payload[:issue]).to be_kind_of(Issue)
        end

        it 'the issue author is Alert bot' do
          expect(execute.payload[:issue].author).to eq(Users::Internal.alert_bot)
        end

        it 'issue has a correct title' do
          expect(execute.payload[:issue].title).to eq(incident_payload['title'])
        end

        it 'issue has a correct description' do
          markdown_line_break = '  '

          expect(execute.payload[:issue].description).to eq(
            <<~MARKDOWN.chomp
              **Incident:** [[FILTERED]](https://gitlab-1.pagerduty.com/incidents/Q1XZUF87W1HB5A)#{markdown_line_break}
              **Incident number:** 2#{markdown_line_break}
              **Urgency:** high#{markdown_line_break}
              **Status:** triggered#{markdown_line_break}
              **Incident key:** [FILTERED]#{markdown_line_break}
              **Created at:** 30 November 2022, 8:46AM (UTC)#{markdown_line_break}
              **Assignees:** [Rajendra Kadam](https://gitlab-1.pagerduty.com/users/PIN0B5C)#{markdown_line_break}
              **Impacted service:** [Test service](https://gitlab-1.pagerduty.com/services/PK6IKMT)
            MARKDOWN
          )
        end
      end

      context 'when the payload does not contain a title' do
        let(:incident_payload) { {} }

        it 'does not create a GitLab issue' do
          expect { execute }.not_to change(Issue, :count)
        end

        it 'responds with error' do
          expect(execute).to be_error
          expect(execute.errors).to contain_exactly("Title can't be blank")
        end
      end
    end

    context 'when PagerDuty webhook setting is not active' do
      let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: false) }

      it 'does not create a GitLab issue' do
        expect { execute }.not_to change(Issue, :count)
      end

      it 'responds with forbidden' do
        expect(execute).to be_error
        expect(execute.http_status).to eq(:forbidden)
      end
    end
  end
end


Instruction:
Write RSpec test file for following ruby class
```ruby
# frozen_string_literal: true

module IncidentManagement
  module Incidents
    class CreateService < ::BaseProjectService
      ISSUE_TYPE = 'incident'

      def initialize(project, current_user, title:, description:, severity: IssuableSeverity::DEFAULT, alert: nil)
        super(project: project, current_user: current_user)

        @title = title
        @description = description
        @severity = severity
        @alert = alert
      end

      def execute
        create_result = Issues::CreateService.new(
          container: project,
          current_user: current_user,
          params: {
            title: title,
            description: description,
            issue_type: ISSUE_TYPE,
            severity: severity,
            alert_management_alerts: [alert].compact
          },
          perform_spam_check: false
        ).execute

        if alert
          return error(alert.errors.full_messages, create_result[:issue]) unless alert.valid?
        end

        create_result
      end

      private

      attr_reader :title, :description, :severity, :alert

      def error(message, issue = nil)
        ServiceResponse.error(payload: { issue: issue }, message: message)
      end
    end
  end
end

```

Response:
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe IncidentManagement::Incidents::CreateService, feature_category: :incident_management do
  let_it_be(:project) { create(:project) }
  let_it_be(:user) { Users::Internal.alert_bot }

  let(:description) { 'Incident description' }

  describe '#execute' do
    subject(:create_incident) { described_class.new(project, user, title: title, description: description).execute }

    context 'when incident has title and description' do
      let(:title) { 'Incident title' }
      let(:new_issue) { Issue.last! }

      it 'responds with success' do
        expect(create_incident).to be_success
      end

      it 'creates an incident issue' do
        expect { create_incident }.to change(Issue, :count).by(1)
      end

      it 'created issue has correct attributes', :aggregate_failures do
        create_incident

        expect(new_issue.title).to eq(title)
        expect(new_issue.description).to eq(description)
        expect(new_issue.author).to eq(user)
      end

      it_behaves_like 'incident issue' do
        before do
          create_incident
        end

        let(:issue) { new_issue }
      end

      context 'with default severity' do
        it 'sets the correct severity level to "unknown"' do
          create_incident
          expect(new_issue.severity).to eq(IssuableSeverity::DEFAULT)
        end
      end

      context 'with severity' do
        using RSpec::Parameterized::TableSyntax

        subject(:create_incident) { described_class.new(project, user, title: title, description: description, severity: severity).execute }

        where(:severity, :incident_severity) do
          'critical' | 'critical'
          'high'     | 'high'
          'medium'   | 'medium'
          'low'      | 'low'
          'unknown'  | 'unknown'
        end

        with_them do
          it 'sets the correct severity level' do
            create_incident
            expect(new_issue.severity).to eq(incident_severity)
          end
        end
      end

      context 'with an alert' do
        subject(:create_incident) { described_class.new(project, user, title: title, description: description, alert: alert).execute }

        context 'when the alert is valid' do
          let(:alert) { create(:alert_management_alert, project: project) }

          it 'associates the alert with the incident' do
            expect(create_incident[:issue].reload.alert_management_alerts).to match_array([alert])
          end
        end

        context 'when the alert is not valid' do
          let(:alert) { create(:alert_management_alert, :with_validation_errors, project: project) }

          it 'does not associate the alert with the incident' do
            expect(create_incident[:issue].reload.alert_management_alerts).to be_empty
          end
        end
      end
    end

    context 'when incident has no title' do
      let(:title) { '' }

      it 'does not create an issue' do
        expect { create_incident }.not_to change(Issue, :count)
      end

      it 'responds with errors' do
        expect(create_incident).to be_error
        expect(create_incident.errors).to contain_exactly("Title can't be blank")
      end

      it 'result payload contains an Issue object' do
        expect(create_incident.payload[:issue]).to be_kind_of(Issue)
      end

      context 'with alert' do
        let(:alert) { create(:alert_management_alert, project: project) }

        subject(:create_incident) { described_class.new(project, user, title: title, description: description, alert: alert).execute }

        context 'the alert prevents the issue from saving' do
          let(:alert) { create(:alert_management_alert, :with_validation_errors, project: project) }

          it 'responds with errors' do
            expect(create_incident).to be_error
            expect(create_incident.errors).to contain_exactly('Hosts hosts array is over 255 chars')
          end
        end
      end
    end
  end
end


Instruction:
Write RSpec test file for following ruby class
```ruby
# frozen_string_literal: true

module Labels
  class FindOrCreateService
    def initialize(current_user, parent, params = {})
      @current_user = current_user
      @parent = parent
      @available_labels = params.delete(:available_labels)
      @existing_labels_by_title = params.delete(:existing_labels_by_title)
      @params = params.dup.with_indifferent_access
    end

    def execute(skip_authorization: false, find_only: false)
      @skip_authorization = skip_authorization
      find_or_create_label(find_only: find_only)
    end

    private

    attr_reader :current_user, :parent, :params, :skip_authorization, :existing_labels_by_title

    def available_labels
      @available_labels ||= LabelsFinder.new(
        current_user,
        "#{parent_type}_id".to_sym => parent.id,
        include_ancestor_groups: include_ancestor_groups?,
        only_group_labels: parent_is_group?
      ).execute(skip_authorization: skip_authorization)
    end

    # Only creates the label if current_user can do so, if the label does not exist
    # and the user can not create the label, nil is returned
    def find_or_create_label(find_only: false)
      new_label = find_existing_label(title)

      return new_label if find_only

      if new_label.nil? && (skip_authorization || Ability.allowed?(current_user, :admin_label, parent))
        create_params = params.except(:include_ancestor_groups)
        new_label = Labels::CreateService.new(create_params).execute(parent_type.to_sym => parent)
      end

      new_label
    end

    # rubocop: disable CodeReuse/ActiveRecord
    def find_existing_label(title)
      return existing_labels_by_title[title] if existing_labels_by_title

      available_labels.find_by(title: title)
    end
    # rubocop: enable CodeReuse/ActiveRecord

    def title
      params[:title] || params[:name]
    end

    def parent_type
      parent.model_name.param_key
    end

    def parent_is_group?
      parent_type == "group"
    end

    def include_ancestor_groups?
      params[:include_ancestor_groups] == true
    end
  end
end

```

Response:
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Labels::FindOrCreateService, feature_category: :team_planning do
  describe '#execute' do
    let(:group)   { create(:group) }
    let(:project) { create(:project, namespace: group) }

    let(:params) do
      {
        title: 'Security',
        description: 'Security related stuff.',
        color: '#FF0000'
      }
    end

    context 'when acting on behalf of a specific user' do
      let(:user) { create(:user) }

      context 'when finding labels on project level' do
        subject(:service) { described_class.new(user, project, params) }

        before do
          project.add_developer(user)
        end

        context 'when existing_labels_by_title is provided' do
          let(:preloaded_label) { build(:label, title: 'Security') }

          before do
            params.merge!(
              existing_labels_by_title: {
                'Security' => preloaded_label
              })
          end

          context 'when label exists' do
            it 'returns preloaded label' do
              expect(service.execute).to eq preloaded_label
            end
          end

          context 'when label does not exists' do
            before do
              params[:title] = 'Audit'
            end

            it 'does not generates additional label search' do
              service.execute

              expect(LabelsFinder).not_to receive(:new)
            end
          end
        end

        context 'when label does not exist at group level' do
          it 'creates a new label at project level' do
            expect { service.execute }.to change(project.labels, :count).by(1)
          end
        end

        context 'when label exists at group level' do
          it 'returns the group label' do
            group_label = create(:group_label, group: group, title: 'Security')

            expect(service.execute).to eq group_label
          end
        end

        context 'when label exists at project level' do
          it 'returns the project label' do
            project_label = create(:label, project: project, title: 'Security')

            expect(service.execute).to eq project_label
          end
        end

        context 'when include_ancestor_groups is true' do
          let(:group) { create(:group, :nested) }
          let(:params) do
            {
              title: 'Audit',
              include_ancestor_groups: true
            }
          end

          it 'returns the ancestor group labels' do
            group_label = create(:group_label, group: group.parent, title: 'Audit')

            expect(service.execute).to eq group_label
          end

          it 'creates new labels if labels are not found' do
            expect { service.execute }.to change(project.labels, :count).by(1)
          end
        end
      end

      context 'when finding labels on group level' do
        subject(:service) { described_class.new(user, group, params) }

        before do
          group.add_developer(user)
        end

        context 'when label does not exist at group level' do
          it 'creates a new label at group level' do
            expect { service.execute }.to change(group.labels, :count).by(1)
          end
        end

        context 'when label exists at group level' do
          it 'returns the group label' do
            group_label = create(:group_label, group: group, title: 'Security')

            expect(service.execute).to eq group_label
          end
        end
      end
    end

    context 'when authorization is not required' do
      context 'when finding labels on project level' do
        subject(:service) { described_class.new(nil, project, params) }

        it 'returns the project label' do
          project_label = create(:label, project: project, title: 'Security')

          expect(service.execute(skip_authorization: true)).to eq project_label
        end
      end

      context 'when finding labels on group level' do
        subject(:service) { described_class.new(nil, group, params) }

        it 'returns the group label' do
          group_label = create(:group_label, group: group, title: 'Security')

          expect(service.execute(skip_authorization: true)).to eq group_label
        end
      end
    end
  end
end


Instruction:
Write RSpec test file for following ruby class
```ruby
# frozen_string_literal: true

module Labels
  class PromoteService < BaseService
    BATCH_SIZE = 1000

    # rubocop: disable CodeReuse/ActiveRecord
    def execute(label)
      return unless project.group &&
          label.is_a?(ProjectLabel)

      ProjectLabel.transaction do
        # use the existing group label if it exists
        group_label = find_or_create_group_label(label)

        label_ids_for_merge(group_label).find_in_batches(batch_size: BATCH_SIZE) do |batched_ids|
          update_old_label_relations(group_label, batched_ids)
          destroy_project_labels(batched_ids)
        end

        group_label
      end
    end
    # rubocop: enable CodeReuse/ActiveRecord

    private

    def update_old_label_relations(group_label, old_label_ids)
      update_issuables(group_label, old_label_ids)
      update_resource_label_events(group_label, old_label_ids)
      update_issue_board_lists(group_label, old_label_ids)
      update_priorities(group_label, old_label_ids)
      subscribe_users(group_label, old_label_ids)
    end

    # rubocop: disable CodeReuse/ActiveRecord
    def subscribe_users(group_label, label_ids)
      # users can be subscribed to multiple labels that will be merged into the group one
      # we want to keep only one subscription / user
      ids_to_update = Subscription.where(subscribable_id: label_ids, subscribable_type: 'Label')
        .group(:user_id)
        .pluck('MAX(id)')
      Subscription.where(id: ids_to_update).update_all(subscribable_id: group_label.id)
    end
    # rubocop: enable CodeReuse/ActiveRecord

    # rubocop: disable CodeReuse/ActiveRecord
    def label_ids_for_merge(group_label)
      LabelsFinder
        .new(current_user, title: group_label.title, group_id: project.group.id)
        .execute(skip_authorization: true)
        .where.not(id: group_label)
        .select(:id, :project_id, :group_id, :type) # Can't use pluck() to avoid object-creation because of the batching
    end
    # rubocop: enable CodeReuse/ActiveRecord

    # rubocop: disable CodeReuse/ActiveRecord
    def update_issuables(group_label, label_ids)
      LabelLink
        .where(label: label_ids)
        .update_all(label_id: group_label.id)
    end
    # rubocop: enable CodeReuse/ActiveRecord

    # rubocop: disable CodeReuse/ActiveRecord
    def update_resource_label_events(group_label, label_ids)
      ResourceLabelEvent
        .where(label: label_ids)
        .update_all(label_id: group_label.id)
    end
    # rubocop: enable CodeReuse/ActiveRecord

    # rubocop: disable CodeReuse/ActiveRecord
    def update_issue_board_lists(group_label, label_ids)
      List
        .where(label: label_ids)
        .update_all(label_id: group_label.id)
    end
    # rubocop: enable CodeReuse/ActiveRecord

    # rubocop: disable CodeReuse/ActiveRecord
    def update_priorities(group_label, label_ids)
      LabelPriority
        .where(label: label_ids)
        .update_all(label_id: group_label.id)
    end
    # rubocop: enable CodeReuse/ActiveRecord

    # rubocop: disable CodeReuse/ActiveRecord
    def destroy_project_labels(label_ids)
      Label.where(id: label_ids).destroy_all # rubocop: disable Cop/DestroyAll
    end

    def find_or_create_group_label(label)
      params = label.attributes.slice('title', 'description', 'color')
      new_label = GroupLabel.create_with(params).find_or_initialize_by(group_id: project.group.id, title: label.title)

      new_label.save! unless new_label.persisted?
      new_label
    end
  end
end

Labels::PromoteService.prepend_mod_with('Labels::PromoteService')

```

Response:
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Labels::PromoteService, feature_category: :team_planning do
  describe '#execute' do
    let_it_be(:user) { create(:user) }

    context 'without a group' do
      let!(:project_1) { create(:project) }

      let!(:project_label_1_1) { create(:label, project: project_1) }

      subject(:service) { described_class.new(project_1, user) }

      it 'fails on project without group' do
        expect(service.execute(project_label_1_1)).to be_falsey
      end
    end

    context 'with a group' do
      let_it_be(:promoted_label_name)  { "Promoted Label" }
      let_it_be(:untouched_label_name) { "Untouched Label" }
      let_it_be(:promoted_description) { "Promoted Description" }
      let_it_be(:promoted_color)       { "#0000FF" }
      let_it_be(:label_2_1_priority)   { 1 }
      let_it_be(:label_3_1_priority)   { 2 }

      let_it_be(:group_1)  { create(:group) }
      let_it_be(:group_2)  { create(:group) }

      let_it_be(:project_1)  { create(:project, :repository, namespace: group_1) }
      let_it_be(:project_2)  { create(:project, :repository, namespace: group_1) }
      let_it_be(:project_3)  { create(:project, :repository, namespace: group_1) }
      let_it_be(:project_4)  { create(:project, :repository, namespace: group_2) }

      # Labels/issues can't be lazily created so we might as well eager initialize
      # all other objects too since we use them inside
      let_it_be(:project_label_1_1)  { create(:label, project: project_1, name: promoted_label_name, color: promoted_color, description: promoted_description) }
      let_it_be(:project_label_1_2)  { create(:label, project: project_1, name: untouched_label_name) }
      let_it_be(:project_label_2_1)  { create(:label, project: project_2, priority: label_2_1_priority, name: promoted_label_name, color: "#FF0000") }
      let_it_be(:project_label_3_1)  { create(:label, project: project_3, priority: label_3_1_priority, name: promoted_label_name) }
      let_it_be(:project_label_3_2)  { create(:label, project: project_3, priority: 1, name: untouched_label_name) }
      let_it_be(:project_label_4_1)  { create(:label, project: project_4, name: promoted_label_name) }

      let_it_be(:issue_1_1)  { create(:labeled_issue, project: project_1, labels: [project_label_1_1, project_label_1_2]) }
      let_it_be(:issue_1_2)  { create(:labeled_issue, project: project_1, labels: [project_label_1_2]) }
      let_it_be(:issue_2_1)  { create(:labeled_issue, project: project_2, labels: [project_label_2_1]) }
      let_it_be(:issue_4_1)  { create(:labeled_issue, project: project_4, labels: [project_label_4_1]) }

      let_it_be(:merge_3_1)  { create(:labeled_merge_request, source_project: project_3, target_project: project_3, labels: [project_label_3_1, project_label_3_2]) }

      let_it_be(:issue_board_2_1)      { create(:board, project: project_2) }
      let_it_be(:issue_board_list_2_1) { create(:list, board: issue_board_2_1, label: project_label_2_1) }

      let(:new_label) { group_1.labels.find_by(title: promoted_label_name) }

      subject(:service) { described_class.new(project_1, user) }

      it 'fails on group label' do
        group_label = create(:group_label, group: group_1)

        expect(service.execute(group_label)).to be_falsey
      end

      shared_examples 'promoting a project label to a group label' do
        it 'is truthy on success' do
          expect(service.execute(project_label_1_1)).to be_truthy
        end

        it 'removes all project labels with that title within the group' do
          expect { service.execute(project_label_1_1) }.to change(project_2.labels, :count).by(-1).and \
            change(project_3.labels, :count).by(-1)
        end

        it 'keeps users\' subscriptions' do
          user2 = create(:user)
          project_label_1_1.subscriptions.create!(user: user, subscribed: true)
          project_label_2_1.subscriptions.create!(user: user, subscribed: true)
          project_label_3_2.subscriptions.create!(user: user, subscribed: true)
          project_label_2_1.subscriptions.create!(user: user2, subscribed: true)

          expect { service.execute(project_label_1_1) }.to change { Subscription.count }.from(4).to(3)

          expect(new_label).to be_subscribed(user)
          expect(new_label).to be_subscribed(user2)
        end

        it 'recreates priorities' do
          service.execute(project_label_1_1)

          expect(new_label.priority(project_1)).to be_nil
          expect(new_label.priority(project_2)).to eq(label_2_1_priority)
          expect(new_label.priority(project_3)).to eq(label_3_1_priority)
        end

        it 'does not touch project out of promoted group' do
          service.execute(project_label_1_1)
          project_4_new_label = project_4.labels.find_by(title: promoted_label_name)

          expect(project_4_new_label).not_to be_nil
          expect(project_4_new_label.id).to eq(project_label_4_1.id)
        end

        it 'does not touch out of group priority' do
          service.execute(project_label_1_1)

          expect(new_label.priority(project_4)).to be_nil
        end

        it 'relinks issue with the promoted label' do
          service.execute(project_label_1_1)
          issue_label = issue_1_1.labels.find_by(title: promoted_label_name)

          expect(issue_label).not_to be_nil
          expect(issue_label.id).to eq(new_label.id)
        end

        it 'does not remove untouched labels from issue' do
          expect { service.execute(project_label_1_1) }.not_to change(issue_1_1.labels, :count)
        end

        it 'does not relink untouched label in issue' do
          service.execute(project_label_1_1)
          issue_label = issue_1_2.labels.find_by(title: untouched_label_name)

          expect(issue_label).not_to be_nil
          expect(issue_label.id).to eq(project_label_1_2.id)
        end

        it 'relinks issues with merged labels' do
          service.execute(project_label_1_1)
          issue_label = issue_2_1.labels.find_by(title: promoted_label_name)

          expect(issue_label).not_to be_nil
          expect(issue_label.id).to eq(new_label.id)
        end

        it 'does not relink issues from other group' do
          service.execute(project_label_1_1)
          issue_label = issue_4_1.labels.find_by(title: promoted_label_name)

          expect(issue_label).not_to be_nil
          expect(issue_label.id).to eq(project_label_4_1.id)
        end

        it 'updates merge request' do
          service.execute(project_label_1_1)
          merge_label = merge_3_1.labels.find_by(title: promoted_label_name)

          expect(merge_label).not_to be_nil
          expect(merge_label.id).to eq(new_label.id)
        end

        it 'updates board lists' do
          service.execute(project_label_1_1)
          list = issue_board_2_1.lists.find_by(label: new_label)

          expect(list).not_to be_nil
        end

        # In case someone adds a new relation to Label.rb and forgets to relink it
        # and the database doesn't have foreign key constraints
        it 'relinks all relations' do
          service.execute(project_label_1_1)

          Label.reflect_on_all_associations.each do |association|
            expect(project_label_1_1.send(association.name).reset).not_to be_any
          end
        end
      end

      context 'when there is an existing identical group label' do
        let!(:existing_group_label) { create(:group_label, group: group_1, title: project_label_1_1.title) }

        it 'uses the existing group label' do
          expect { service.execute(project_label_1_1) }
            .to change(project_1.labels, :count).by(-1)
            .and not_change(group_1.labels, :count)
          expect(new_label).not_to be_nil
        end

        it 'does not create a new group label clone' do
          expect { service.execute(project_label_1_1) }.not_to change { GroupLabel.maximum(:id) }
        end

        it_behaves_like 'promoting a project label to a group label'
      end

      context 'when there is no existing identical group label' do
        let(:existing_group_label) { nil }

        it 'recreates the label as a group label' do
          expect { service.execute(project_label_1_1) }
            .to change(project_1.labels, :count).by(-1)
            .and change(group_1.labels, :count).by(1)
          expect(new_label).not_to be_nil
        end

        it 'copies title, description and color to cloned group label' do
          service.execute(project_label_1_1)

          expect(new_label.title).to eq(promoted_label_name)
          expect(new_label.description).to eq(promoted_description)
          expect(new_label.color).to be_color(promoted_color)
        end

        it_behaves_like 'promoting a project label to a group label'
      end
    end
  end
end


Instruction:
Write RSpec test file for following ruby class
```ruby
# frozen_string_literal: true

# Labels::TransferService class
#
# User for recreate the missing group labels at project level
#
module Labels
  class TransferService
    def initialize(current_user, old_group, project)
      @current_user = current_user
      @old_group = old_group
      @project = project
    end

    def execute
      return unless old_group.present?

      # rubocop: disable CodeReuse/ActiveRecord
      link_ids = group_labels_applied_to_issues.pluck("label_links.id") +
                 group_labels_applied_to_merge_requests.pluck("label_links.id")
      # rubocop: disable CodeReuse/ActiveRecord

      Label.transaction do
        labels_to_transfer.find_each do |label|
          new_label_id = find_or_create_label!(label)

          next if new_label_id == label.id

          update_label_links(link_ids, old_label_id: label.id, new_label_id: new_label_id)
          update_label_priorities(old_label_id: label.id, new_label_id: new_label_id)
        end
      end
    end

    private

    attr_reader :current_user, :old_group, :project

    # rubocop: disable CodeReuse/ActiveRecord
    def labels_to_transfer
      Label
        .from_union([
                      group_labels_applied_to_issues,
                      group_labels_applied_to_merge_requests
                    ])
        .reorder(nil)
        .distinct
    end
    # rubocop: enable CodeReuse/ActiveRecord

    # rubocop: disable CodeReuse/ActiveRecord
    def group_labels_applied_to_issues
      @labels_applied_to_issues ||= Label.joins(:issues)
        .joins("INNER JOIN namespaces on namespaces.id = labels.group_id AND namespaces.type = 'Group'")
        .where(issues: { project_id: project.id }).reorder(nil)
    end
    # rubocop: enable CodeReuse/ActiveRecord

    # rubocop: disable CodeReuse/ActiveRecord
    def group_labels_applied_to_merge_requests
      @labels_applied_to_mrs ||= Label.joins(:merge_requests)
        .joins("INNER JOIN namespaces on namespaces.id = labels.group_id AND namespaces.type = 'Group'")
        .where(merge_requests: { target_project_id: project.id }).reorder(nil)
    end
    # rubocop: enable CodeReuse/ActiveRecord

    def find_or_create_label!(label)
      params    = label.attributes.slice('title', 'description', 'color')
      new_label = FindOrCreateService.new(current_user, project, params.merge(include_ancestor_groups: true)).execute

      new_label.id
    end

    # rubocop: disable CodeReuse/ActiveRecord
    def update_label_links(link_ids, old_label_id:, new_label_id:)
      LabelLink.where(id: link_ids, label_id: old_label_id)
        .update_all(label_id: new_label_id)
    end
    # rubocop: enable CodeReuse/ActiveRecord

    # rubocop: disable CodeReuse/ActiveRecord
    def update_label_priorities(old_label_id:, new_label_id:)
      LabelPriority.where(project_id: project.id, label_id: old_label_id)
        .update_all(label_id: new_label_id)
    end
    # rubocop: enable CodeReuse/ActiveRecord
  end
end

```

Response:
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Labels::TransferService, feature_category: :team_planning do
  shared_examples 'transfer labels' do
    describe '#execute' do
      let_it_be(:user) { create(:user) }

      let_it_be(:old_group_ancestor) { create(:group) }
      let_it_be(:old_group) { create(:group, parent: old_group_ancestor) }

      let_it_be(:new_group) { create(:group) }

      let_it_be(:project) { create(:project, :repository, group: new_group) }

      subject(:service) { described_class.new(user, old_group, project) }

      before do
        old_group_ancestor.add_developer(user)
        new_group.add_developer(user)
      end

      it 'recreates missing group labels at project level and assigns them to the issuables' do
        old_group_label_1 = create(:group_label, group: old_group)
        old_group_label_2 = create(:group_label, group: old_group)

        labeled_issue = create(:labeled_issue, project: project, labels: [old_group_label_1])
        labeled_merge_request = create(:labeled_merge_request, source_project: project, labels: [old_group_label_2])

        expect { service.execute }.to change(project.labels, :count).by(2)
        expect(labeled_issue.reload.labels).to contain_exactly(project.labels.find_by_title(old_group_label_1.title))
        expect(labeled_merge_request.reload.labels).to contain_exactly(project.labels.find_by_title(old_group_label_2.title))
      end

      it 'recreates missing ancestor group labels at project level and assigns them to the issuables' do
        old_group_ancestor_label_1 = create(:group_label, group: old_group_ancestor)
        old_group_ancestor_label_2 = create(:group_label, group: old_group_ancestor)

        labeled_issue = create(:labeled_issue, project: project, labels: [old_group_ancestor_label_1])
        labeled_merge_request = create(:labeled_merge_request, source_project: project, labels: [old_group_ancestor_label_2])

        expect { service.execute }.to change(project.labels, :count).by(2)
        expect(labeled_issue.reload.labels).to contain_exactly(project.labels.find_by_title(old_group_ancestor_label_1.title))
        expect(labeled_merge_request.reload.labels).to contain_exactly(project.labels.find_by_title(old_group_ancestor_label_2.title))
      end

      it 'recreates label priorities related to the missing group labels' do
        old_group_label = create(:group_label, group: old_group)
        create(:labeled_issue, project: project, labels: [old_group_label])
        create(:label_priority, project: project, label: old_group_label, priority: 1)

        service.execute

        new_project_label = project.labels.find_by(title: old_group_label.title)
        expect(new_project_label.id).not_to eq old_group_label.id
        expect(new_project_label.priorities).not_to be_empty
      end

      it 'does not recreate missing group labels that are not applied to issues or merge requests' do
        old_group_label = create(:group_label, group: old_group)

        service.execute

        expect(project.labels.where(title: old_group_label.title)).to be_empty
      end

      it 'does not recreate missing group labels that already exist in the project group' do
        old_group_label = create(:group_label, group: old_group)
        labeled_issue = create(:labeled_issue, project: project, labels: [old_group_label])

        new_group_label = create(:group_label, group: new_group, title: old_group_label.title)

        service.execute

        expect(project.labels.where(title: old_group_label.title)).to be_empty
        expect(labeled_issue.reload.labels).to contain_exactly(new_group_label)
      end

      it 'updates only label links in the given project' do
        old_group_label = create(:group_label, group: old_group)
        other_project = create(:project, group: old_group)

        labeled_issue = create(:labeled_issue, project: project, labels: [old_group_label])
        other_project_labeled_issue = create(:labeled_issue, project: other_project, labels: [old_group_label])

        service.execute

        expect(labeled_issue.reload.labels).not_to include(old_group_label)
        expect(other_project_labeled_issue.reload.labels).to contain_exactly(old_group_label)
      end

      context 'when moving within the same ancestor group' do
        let(:other_subgroup) { create(:group, parent: old_group_ancestor) }
        let(:project) { create(:project, :repository, group: other_subgroup) }

        it 'does not recreate ancestor group labels' do
          old_group_ancestor_label_1 = create(:group_label, group: old_group_ancestor)
          old_group_ancestor_label_2 = create(:group_label, group: old_group_ancestor)

          labeled_issue = create(:labeled_issue, project: project, labels: [old_group_ancestor_label_1])
          labeled_merge_request = create(:labeled_merge_request, source_project: project, labels: [old_group_ancestor_label_2])

          expect { service.execute }.not_to change(project.labels, :count)
          expect(labeled_issue.reload.labels).to contain_exactly(old_group_ancestor_label_1)
          expect(labeled_merge_request.reload.labels).to contain_exactly(old_group_ancestor_label_2)
        end
      end
    end
  end

  it_behaves_like 'transfer labels'
end


Instruction:
Write RSpec test file for following ruby class
```ruby
# frozen_string_literal: true
module Labels
  class AvailableLabelsService
    attr_reader :current_user, :parent, :params

    def initialize(current_user, parent, params)
      @current_user = current_user
      @parent = parent
      @params = params
    end

    def find_or_create_by_titles(key = :labels, find_only: false)
      labels = params.delete(key)

      return [] unless labels

      labels = labels.split(',').map(&:strip) if labels.is_a?(String)
      existing_labels = LabelsFinder.new(current_user, finder_params(labels)).execute.index_by(&:title)

      labels.map do |label_name|
        label = Labels::FindOrCreateService.new(
          current_user,
          parent,
          include_ancestor_groups: true,
          title: label_name,
          existing_labels_by_title: existing_labels
        ).execute(find_only: find_only)

        label
      end.compact
    end

    def filter_labels_ids_in_param(key)
      ids = Array.wrap(params[key])
      return [] if ids.empty?

      # rubocop:disable CodeReuse/ActiveRecord
      existing_ids = available_labels.id_in(ids).pluck(:id)
      # rubocop:enable CodeReuse/ActiveRecord
      ids.map(&:to_i) & existing_ids
    end

    def filter_locked_label_ids(ids)
      available_labels.with_lock_on_merge.id_in(ids).pluck(:id) # rubocop:disable CodeReuse/ActiveRecord
    end

    def available_labels
      @available_labels ||= LabelsFinder.new(current_user, finder_params).execute
    end

    private

    def finder_params(titles = nil)
      finder_params = { include_ancestor_groups: true }
      finder_params[:title] = titles if titles

      case parent
      when Group
        finder_params[:group_id] = parent.id
        finder_params[:only_group_labels] = true
      when Project
        finder_params[:project_id] = parent.id
      end

      finder_params
    end
  end
end

```

Response:
# frozen_string_literal: true
require 'spec_helper'

RSpec.describe Labels::AvailableLabelsService, feature_category: :team_planning do
  let_it_be(:user) { create(:user) }
  let(:project) { create(:project, :public, group: group) }
  let(:group) { create(:group) }

  let(:project_label) { create(:label, project: project) }
  let(:project_label_locked) { create(:label, project: project, lock_on_merge: true) }
  let(:other_project_label) { create(:label) }
  let(:other_project_label_locked) { create(:label, lock_on_merge: true) }
  let(:group_label) { create(:group_label, group: group) }
  let(:group_label_locked) { create(:group_label, group: group, lock_on_merge: true) }
  let(:other_group_label) { create(:group_label) }
  let!(:labels) { [project_label, other_project_label, group_label, other_group_label, project_label_locked, other_project_label_locked, group_label_locked] }

  describe '#find_or_create_by_titles' do
    let(:label_titles) { labels.map(&:title).push('non existing title') }

    context 'when parent is a project' do
      context 'when a user is not a project member' do
        it 'returns only relevant label ids' do
          result = described_class.new(user, project, labels: label_titles).find_or_create_by_titles

          expect(result).to match_array([project_label, group_label, project_label_locked, group_label_locked])
        end
      end

      context 'when a user is a project member' do
        before do
          project.add_developer(user)
        end

        it 'creates new labels for not found titles' do
          result = described_class.new(user, project, labels: label_titles).find_or_create_by_titles

          expect(result.count).to eq(8)
          expect(result).to include(project_label, group_label)
          expect(result).not_to include(other_project_label, other_group_label)
        end

        it 'do not cause additional query for finding labels' do
          label_titles = [project_label.title]
          control_count = ActiveRecord::QueryRecorder.new { described_class.new(user, project, labels: label_titles).find_or_create_by_titles }

          new_label = create(:label, project: project)
          label_titles = [project_label.title, new_label.title]
          expect { described_class.new(user, project, labels: label_titles).find_or_create_by_titles }.not_to exceed_query_limit(control_count)
        end
      end
    end

    context 'when parent is a group' do
      context 'when a user is not a group member' do
        it 'returns only relevant label ids' do
          result = described_class.new(user, group, labels: label_titles).find_or_create_by_titles

          expect(result).to match_array([group_label, group_label_locked])
        end
      end

      context 'when a user is a group member' do
        before do
          group.add_developer(user)
        end

        it 'creates new labels for not found titles' do
          result = described_class.new(user, group, labels: label_titles).find_or_create_by_titles

          expect(result.count).to eq(8)
          expect(result).to include(group_label, group_label_locked)
          expect(result).not_to include(project_label, other_project_label, other_group_label, project_label_locked, other_project_label_locked)
        end
      end
    end
  end

  describe '#filter_labels_ids_in_param' do
    let(:label_ids) { labels.map(&:id).push(non_existing_record_id) }

    context 'when parent is a project' do
      it 'returns only relevant label ids' do
        result = described_class.new(user, project, ids: label_ids).filter_labels_ids_in_param(:ids)

        expect(result).to match_array([project_label.id, group_label.id, project_label_locked.id, group_label_locked.id])
      end

      it 'returns labels in preserved order' do
        result = described_class.new(user, project, ids: label_ids.reverse).filter_labels_ids_in_param(:ids)

        expect(result).to eq([group_label_locked.id, project_label_locked.id, group_label.id, project_label.id])
      end
    end

    context 'when parent is a group' do
      it 'returns only relevant label ids' do
        result = described_class.new(user, group, ids: label_ids).filter_labels_ids_in_param(:ids)

        expect(result).to match_array([group_label.id, group_label_locked.id])
      end
    end

    it 'accepts a single id parameter' do
      result = described_class.new(user, project, label_id: project_label.id).filter_labels_ids_in_param(:label_id)

      expect(result).to match_array([project_label.id])
    end
  end

  describe '#filter_locked_label_ids' do
    let(:label_ids) { labels.map(&:id) }

    context 'when parent is a project' do
      it 'returns only relevant label ids' do
        result = described_class.new(user, project, ids: label_ids).filter_locked_label_ids(label_ids)

        expect(result).to match_array([project_label_locked.id, group_label_locked.id])
      end
    end

    context 'when parent is a group' do
      it 'returns only relevant label ids' do
        result = described_class.new(user, group, ids: label_ids).filter_locked_label_ids(label_ids)

        expect(result).to match_array([group_label_locked.id])
      end
    end
  end

  describe '#available_labels' do
    context 'when parent is a project' do
      it 'returns only relevant labels' do
        result = described_class.new(user, project, {}).available_labels

        expect(result.count).to eq(4)
        expect(result).to include(project_label, group_label, project_label_locked, group_label_locked)
        expect(result).not_to include(other_project_label, other_group_label, other_project_label_locked)
      end
    end

    context 'when parent is a group' do
      it 'returns only relevant labels' do
        result = described_class.new(user, group, {}).available_labels

        expect(result.count).to eq(2)
        expect(result).to include(group_label, group_label_locked)
        expect(result).not_to include(project_label, other_project_label, other_group_label, project_label_locked, other_project_label_locked)
      end
    end
  end
end