process_commit_worker_spec.rb 6.15 KB
Newer Older
1 2
# frozen_string_literal: true

3 4 5
require 'spec_helper'

describe ProcessCommitWorker do
6 7
  include ProjectForksHelper

8 9
  let(:worker) { described_class.new }
  let(:user) { create(:user) }
10
  let(:project) { create(:project, :public, :repository) }
11 12 13 14 15 16 17
  let(:issue) { create(:issue, project: project, author: user) }
  let(:commit) { project.commit }

  describe '#perform' do
    it 'does not process the commit when the project does not exist' do
      expect(worker).not_to receive(:close_issues)

18
      worker.perform(-1, user.id, commit.to_hash)
19 20 21 22 23
    end

    it 'does not process the commit when the user does not exist' do
      expect(worker).not_to receive(:close_issues)

24
      worker.perform(project.id, -1, commit.to_hash)
25 26 27 28 29
    end

    it 'processes the commit message' do
      expect(worker).to receive(:process_commit_message).and_call_original

30
      worker.perform(project.id, user.id, commit.to_hash)
31 32 33 34 35
    end

    it 'updates the issue metrics' do
      expect(worker).to receive(:update_issue_metrics).and_call_original

36
      worker.perform(project.id, user.id, commit.to_hash)
37
    end
38

39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
    context 'when the project is forked' do
      context 'when commit already exists in the upstream project' do
        it 'does not process the commit message' do
          forked = fork_project(project, user, repository: true)

          expect(worker).not_to receive(:process_commit_message)

          worker.perform(forked.id, user.id, forked.commit.to_hash)
        end
      end

      context 'when the commit does not exist in the upstream project' do
        it 'processes the commit message' do
          empty_project = create(:project, :public)
          forked = fork_project(empty_project, user, repository: true)

          TestEnv.copy_repo(forked,
                            bare_repo: TestEnv.factory_repo_path_bare,
                            refs: TestEnv::BRANCH_SHA)

          expect(worker).to receive(:process_commit_message)

          worker.perform(forked.id, user.id, forked.commit.to_hash)
        end
      end
64

65 66 67 68
      context 'when the upstream project no longer exists' do
        it 'processes the commit message' do
          forked = fork_project(project, user, repository: true)
          project.destroy!
69

70
          expect(worker).to receive(:process_commit_message)
71

72 73
          worker.perform(forked.id, user.id, forked.commit.to_hash)
        end
74 75
      end
    end
76 77 78 79
  end

  describe '#process_commit_message' do
    context 'when pushing to the default branch' do
80
      before do
Micaël Bergeron's avatar
Micaël Bergeron committed
81
        allow(commit).to receive(:safe_message).and_return("Closes #{issue.to_reference}")
82
      end
83

84
      it 'closes issues that should be closed per the commit message' do
Micaël Bergeron's avatar
Micaël Bergeron committed
85
        expect(worker).to receive(:close_issues).with(project, user, user, commit, [issue])
86 87 88

        worker.process_commit_message(project, commit, user, user, true)
      end
89 90 91 92 93 94

      it 'creates cross references' do
        expect(commit).to receive(:create_cross_references!).with(user, [issue])

        worker.process_commit_message(project, commit, user, user, true)
      end
95 96 97 98
    end

    context 'when pushing to a non-default branch' do
      it 'does not close any issues' do
Micaël Bergeron's avatar
Micaël Bergeron committed
99
        allow(commit).to receive(:safe_message).and_return("Closes #{issue.to_reference}")
100 101 102 103 104

        expect(worker).not_to receive(:close_issues)

        worker.process_commit_message(project, commit, user, user, false)
      end
105 106 107 108 109 110

      it 'does not create cross references' do
        expect(commit).to receive(:create_cross_references!).with(user, [])

        worker.process_commit_message(project, commit, user, user, false)
      end
111 112
    end

113 114 115 116 117 118 119 120
    context 'when commit is a merge request merge commit to the default branch' do
      let(:merge_request) do
        create(:merge_request,
               description: "Closes #{issue.to_reference}",
               source_branch: 'feature-merged',
               target_branch: 'master',
               source_project: project)
      end
121

122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
      let(:commit) do
        project.repository.create_branch('feature-merged', 'feature')

        MergeRequests::MergeService
          .new(project, merge_request.author)
          .execute(merge_request)

        merge_request.reload.merge_commit
      end

      it 'does not close any issues from the commit message' do
        expect(worker).not_to receive(:close_issues)

        worker.process_commit_message(project, commit, user, user, true)
      end

      it 'still creates cross references' do
        expect(commit).to receive(:create_cross_references!).with(user, [])

        worker.process_commit_message(project, commit, user, user, true)
      end
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
    end
  end

  describe '#close_issues' do
    context 'when the user can update the issues' do
      it 'closes the issues' do
        worker.close_issues(project, user, user, commit, [issue])

        issue.reload

        expect(issue.closed?).to eq(true)
      end
    end

    context 'when the user can not update the issues' do
      it 'does not close the issues' do
        other_user = create(:user)

        worker.close_issues(project, other_user, other_user, commit, [issue])

        issue.reload

        expect(issue.closed?).to eq(false)
      end
    end
  end

  describe '#update_issue_metrics' do
    it 'updates any existing issue metrics' do
Micaël Bergeron's avatar
Micaël Bergeron committed
172
      allow(commit).to receive(:safe_message).and_return("Closes #{issue.to_reference}")
173 174 175 176 177 178 179

      worker.update_issue_metrics(commit, user)

      metric = Issue::Metrics.first

      expect(metric.first_mentioned_in_commit_at).to eq(commit.committed_date)
    end
180 181

    it "doesn't execute any queries with false conditions" do
Micaël Bergeron's avatar
Micaël Bergeron committed
182
      allow(commit).to receive(:safe_message).and_return("Lorem Ipsum")
183

Micaël Bergeron's avatar
Micaël Bergeron committed
184 185
      expect { worker.update_issue_metrics(commit, user) }
        .not_to make_queries_matching(/WHERE (?:1=0|0=1)/)
186
    end
187
  end
188 189 190 191 192 193 194 195 196

  describe '#build_commit' do
    it 'returns a Commit' do
      commit = worker.build_commit(project, id: '123')

      expect(commit).to be_an_instance_of(Commit)
    end

    it 'parses date strings into Time instances' do
Micaël Bergeron's avatar
Micaël Bergeron committed
197 198 199
      commit = worker.build_commit(project,
                                   id: '123',
                                   authored_date: Time.now.to_s)
200 201 202 203

      expect(commit.authored_date).to be_an_instance_of(Time)
    end
  end
204
end