348 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			348 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Ruby
		
	
	
	
# frozen_string_literal: true
 | 
						|
 | 
						|
require 'spec_helper'
 | 
						|
 | 
						|
RSpec.describe Gitlab::QuickActions::CommandDefinition do
 | 
						|
  let(:mock_command) { :command }
 | 
						|
 | 
						|
  subject { described_class.new(mock_command) }
 | 
						|
 | 
						|
  describe "#all_names" do
 | 
						|
    context "when the command has aliases" do
 | 
						|
      before do
 | 
						|
        subject.aliases = [:alias1, :alias2]
 | 
						|
      end
 | 
						|
 | 
						|
      it "returns an array with the name and aliases" do
 | 
						|
        expect(subject.all_names).to eq([:command, :alias1, :alias2])
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context "when the command doesn't have aliases" do
 | 
						|
      it "returns an array with the name" do
 | 
						|
        expect(subject.all_names).to eq([:command])
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  describe "#noop?" do
 | 
						|
    context "when the command has an action block" do
 | 
						|
      before do
 | 
						|
        subject.action_block = proc {}
 | 
						|
      end
 | 
						|
 | 
						|
      it "returns false" do
 | 
						|
        expect(subject.noop?).to be false
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context "when the command doesn't have an action block" do
 | 
						|
      it "returns true" do
 | 
						|
        expect(subject.noop?).to be true
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  describe "#available?" do
 | 
						|
    let(:opts) { ActiveSupport::InheritableOptions.new(go: false) }
 | 
						|
 | 
						|
    context "when the command has a condition block" do
 | 
						|
      before do
 | 
						|
        subject.condition_block = proc { go }
 | 
						|
      end
 | 
						|
 | 
						|
      context "when the condition block returns true" do
 | 
						|
        before do
 | 
						|
          opts[:go] = true
 | 
						|
        end
 | 
						|
 | 
						|
        it "returns true" do
 | 
						|
          expect(subject.available?(opts)).to be true
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      context "when the condition block returns false" do
 | 
						|
        it "returns false" do
 | 
						|
          expect(subject.available?(opts)).to be false
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context "when the command doesn't have a condition block" do
 | 
						|
      it "returns true" do
 | 
						|
        expect(subject.available?(opts)).to be true
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context "when the command has types" do
 | 
						|
      before do
 | 
						|
        subject.types = [Issue, Commit, WorkItem]
 | 
						|
      end
 | 
						|
 | 
						|
      context "when the command target type is allowed" do
 | 
						|
        it "returns true" do
 | 
						|
          opts[:quick_action_target] = Issue.new
 | 
						|
          expect(subject.available?(opts)).to be true
 | 
						|
        end
 | 
						|
 | 
						|
        context 'when the command target type is Work Item' do
 | 
						|
          context 'when the command is not allowed' do
 | 
						|
            it "returns false" do
 | 
						|
              opts[:quick_action_target] = build(:work_item)
 | 
						|
              expect(subject.available?(opts)).to be false
 | 
						|
            end
 | 
						|
          end
 | 
						|
 | 
						|
          context 'when the command is allowed' do
 | 
						|
            it "returns true" do
 | 
						|
              allow_next_instance_of(WorkItem) do |work_item|
 | 
						|
                allow(work_item).to receive(:supported_quick_action_commands).and_return([mock_command])
 | 
						|
              end
 | 
						|
 | 
						|
              opts[:quick_action_target] = build(:work_item)
 | 
						|
              expect(subject.available?(opts)).to be true
 | 
						|
            end
 | 
						|
          end
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      context "when the command target type is not allowed" do
 | 
						|
        it "returns true" do
 | 
						|
          opts[:quick_action_target] = MergeRequest.new
 | 
						|
          expect(subject.available?(opts)).to be false
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context "when the command has no types" do
 | 
						|
      it "any target type is allowed" do
 | 
						|
        opts[:quick_action_target] = Issue.new
 | 
						|
        expect(subject.available?(opts)).to be true
 | 
						|
 | 
						|
        opts[:quick_action_target] = MergeRequest.new
 | 
						|
        expect(subject.available?(opts)).to be true
 | 
						|
 | 
						|
        opts[:quick_action_target] = build(:work_item)
 | 
						|
        expect(subject.available?(opts)).to be true
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  describe "#execute" do
 | 
						|
    let(:fake_context) { Struct.new(:run, :commands_executed_count, :received_arg) }
 | 
						|
    let(:context) { fake_context.new(false, nil, nil) }
 | 
						|
 | 
						|
    context "when the command is a noop" do
 | 
						|
      it "doesn't execute the command" do
 | 
						|
        expect(context).not_to receive(:instance_exec)
 | 
						|
 | 
						|
        subject.execute(context, nil)
 | 
						|
 | 
						|
        expect(context.commands_executed_count).to be_nil
 | 
						|
        expect(context.run).to be false
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context "when the command is not a noop" do
 | 
						|
      before do
 | 
						|
        subject.action_block = proc { self.run = true }
 | 
						|
      end
 | 
						|
 | 
						|
      context "when the command is not available" do
 | 
						|
        before do
 | 
						|
          subject.condition_block = proc { false }
 | 
						|
        end
 | 
						|
 | 
						|
        it "counts the command as executed" do
 | 
						|
          subject.execute(context, nil)
 | 
						|
 | 
						|
          expect(context.commands_executed_count).to eq(1)
 | 
						|
          expect(context.run).to be false
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      context "when the command is available" do
 | 
						|
        context "when the commnd has no arguments" do
 | 
						|
          before do
 | 
						|
            subject.action_block = proc { self.run = true }
 | 
						|
          end
 | 
						|
 | 
						|
          context "when the command is provided an argument" do
 | 
						|
            it "executes the command" do
 | 
						|
              subject.execute(context, true)
 | 
						|
 | 
						|
              expect(context.run).to be true
 | 
						|
              expect(context.commands_executed_count).to eq(1)
 | 
						|
            end
 | 
						|
          end
 | 
						|
 | 
						|
          context "when the command is not provided an argument" do
 | 
						|
            it "executes the command" do
 | 
						|
              subject.execute(context, nil)
 | 
						|
 | 
						|
              expect(context.run).to be true
 | 
						|
              expect(context.commands_executed_count).to eq(1)
 | 
						|
            end
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        context "when the command has 1 required argument" do
 | 
						|
          before do
 | 
						|
            subject.action_block = ->(arg) { self.run = arg }
 | 
						|
          end
 | 
						|
 | 
						|
          context "when the command is provided an argument" do
 | 
						|
            it "executes the command" do
 | 
						|
              subject.execute(context, true)
 | 
						|
 | 
						|
              expect(context.run).to be true
 | 
						|
              expect(context.commands_executed_count).to eq(1)
 | 
						|
            end
 | 
						|
          end
 | 
						|
 | 
						|
          context "when the command is not provided an argument" do
 | 
						|
            it "doesn't execute the command" do
 | 
						|
              subject.execute(context, nil)
 | 
						|
 | 
						|
              expect(context.run).to be false
 | 
						|
            end
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        context "when the command has 1 optional argument" do
 | 
						|
          before do
 | 
						|
            subject.action_block = proc { |arg = nil| self.run = arg || true }
 | 
						|
          end
 | 
						|
 | 
						|
          context "when the command is provided an argument" do
 | 
						|
            it "executes the command" do
 | 
						|
              subject.execute(context, true)
 | 
						|
 | 
						|
              expect(context.run).to be true
 | 
						|
            end
 | 
						|
          end
 | 
						|
 | 
						|
          context "when the command is not provided an argument" do
 | 
						|
            it "executes the command" do
 | 
						|
              subject.execute(context, nil)
 | 
						|
 | 
						|
              expect(context.run).to be true
 | 
						|
            end
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        context 'when the command defines parse_params block' do
 | 
						|
          before do
 | 
						|
            subject.parse_params_block = ->(raw) { raw.strip }
 | 
						|
            subject.action_block = ->(parsed) { self.received_arg = parsed }
 | 
						|
          end
 | 
						|
 | 
						|
          it 'executes the command passing the parsed param' do
 | 
						|
            subject.execute(context, 'something   ')
 | 
						|
 | 
						|
            expect(context.received_arg).to eq('something')
 | 
						|
          end
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  describe "#execute_message" do
 | 
						|
    context "when the command is a noop" do
 | 
						|
      it 'returns nil' do
 | 
						|
        expect(subject.execute_message({}, nil)).to be_nil
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context "when the command is not a noop" do
 | 
						|
      before do
 | 
						|
        subject.action_block = proc { self.run = true }
 | 
						|
      end
 | 
						|
 | 
						|
      context "when the command is not available" do
 | 
						|
        before do
 | 
						|
          subject.condition_block = proc { false }
 | 
						|
        end
 | 
						|
 | 
						|
        it 'returns an error message' do
 | 
						|
          expect(subject.execute_message({}, nil)).to eq('Could not apply command command.')
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      context "when the command is available" do
 | 
						|
        context 'when the execution_message is a static string' do
 | 
						|
          before do
 | 
						|
            subject.execution_message = 'Assigned jacopo'
 | 
						|
          end
 | 
						|
 | 
						|
          it 'returns this static string' do
 | 
						|
            expect(subject.execute_message({}, nil)).to eq('Assigned jacopo')
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        context 'when the explanation is dynamic' do
 | 
						|
          before do
 | 
						|
            subject.execution_message = proc { |arg| "Assigned #{arg}" }
 | 
						|
          end
 | 
						|
 | 
						|
          it 'invokes the proc' do
 | 
						|
            expect(subject.execute_message({}, 'Jacopo')).to eq('Assigned Jacopo')
 | 
						|
          end
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  describe '#explain' do
 | 
						|
    context 'when the command is not available' do
 | 
						|
      before do
 | 
						|
        subject.condition_block = proc { false }
 | 
						|
        subject.explanation = 'Explanation'
 | 
						|
      end
 | 
						|
 | 
						|
      it 'returns nil' do
 | 
						|
        result = subject.explain({}, nil)
 | 
						|
 | 
						|
        expect(result).to be_nil
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context 'when the explanation is a static string' do
 | 
						|
      before do
 | 
						|
        subject.explanation = 'Explanation'
 | 
						|
      end
 | 
						|
 | 
						|
      it 'returns this static string' do
 | 
						|
        result = subject.explain({}, nil)
 | 
						|
 | 
						|
        expect(result).to eq 'Explanation'
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context 'when warning is set' do
 | 
						|
      before do
 | 
						|
        subject.explanation = 'Explanation'
 | 
						|
        subject.warning = 'dangerous!'
 | 
						|
      end
 | 
						|
 | 
						|
      it 'returns this static string' do
 | 
						|
        result = subject.explain({}, nil)
 | 
						|
 | 
						|
        expect(result).to eq 'Explanation (dangerous!)'
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context 'when the explanation is dynamic' do
 | 
						|
      before do
 | 
						|
        subject.explanation = proc { |arg| "Dynamic #{arg}" }
 | 
						|
      end
 | 
						|
 | 
						|
      it 'invokes the proc' do
 | 
						|
        result = subject.explain({}, 'explanation')
 | 
						|
 | 
						|
        expect(result).to eq 'Dynamic explanation'
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |