summaryrefslogtreecommitdiff
path: root/spec/features/merge_requests/conflicts_spec.rb
blob: b0432ed8fc6f1e8a839e70fe6cfb77ca444f543f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
require 'spec_helper'

feature 'Merge request conflict resolution', :js do
  let(:user) { create(:user) }
  let(:project) { create(:project, :repository) }

  before do
    # In order to have the diffs collapsed, we need to disable the increase feature
    stub_feature_flags(gitlab_git_diff_size_limit_increase: false)
  end

  def create_merge_request(source_branch)
    create(:merge_request, source_branch: source_branch, target_branch: 'conflict-start', source_project: project) do |mr|
      mr.mark_as_unmergeable
    end
  end

  shared_examples "conflicts are resolved in Interactive mode" do
    it 'conflicts are resolved in Interactive mode' do
      within find('.files-wrapper .diff-file', text: 'files/ruby/popen.rb') do
        click_button 'Use ours'
      end

      within find('.files-wrapper .diff-file', text: 'files/ruby/regex.rb') do
        all('button', text: 'Use ours').each do |button|
          button.trigger('click')
        end
      end

      click_button 'Commit conflict resolution'

      expect(page).to have_content('All merge conflicts were resolved')
      merge_request.reload_diff

      wait_for_requests

      click_on 'Changes'
      wait_for_requests

      within find('.diff-file', text: 'files/ruby/popen.rb') do
        expect(page).to have_selector('.line_content.new', text: "vars = { 'PWD' => path }")
        expect(page).to have_selector('.line_content.new', text: "options = { chdir: path }")
      end

      within find('.diff-file', text: 'files/ruby/regex.rb') do
        expect(page).to have_selector('.line_content.new', text: "def username_regexp")
        expect(page).to have_selector('.line_content.new', text: "def project_name_regexp")
        expect(page).to have_selector('.line_content.new', text: "def path_regexp")
        expect(page).to have_selector('.line_content.new', text: "def archive_formats_regexp")
        expect(page).to have_selector('.line_content.new', text: "def git_reference_regexp")
        expect(page).to have_selector('.line_content.new', text: "def default_regexp")
      end
    end
  end

  shared_examples "conflicts are resolved in Edit inline mode" do
    it 'conflicts are resolved in Edit inline mode' do
      expect(find('#conflicts')).to have_content('popen.rb')

      within find('.files-wrapper .diff-file', text: 'files/ruby/popen.rb') do
        click_button 'Edit inline'
        wait_for_requests
        execute_script('ace.edit($(".files-wrapper .diff-file pre")[0]).setValue("One morning");')
      end

      within find('.files-wrapper .diff-file', text: 'files/ruby/regex.rb') do
        click_button 'Edit inline'
        wait_for_requests
        execute_script('ace.edit($(".files-wrapper .diff-file pre")[1]).setValue("Gregor Samsa woke from troubled dreams");')
      end

      click_button 'Commit conflict resolution'

      expect(page).to have_content('All merge conflicts were resolved')
      merge_request.reload_diff

      wait_for_requests

      click_on 'Changes'
      wait_for_requests

      expect(page).to have_content('One morning')
      expect(page).to have_content('Gregor Samsa woke from troubled dreams')
    end
  end

  context 'can be resolved in the UI' do
    before do
      project.team << [user, :developer]
      sign_in(user)
    end

    context 'the conflicts are resolvable' do
      let(:merge_request) { create_merge_request('conflict-resolvable') }

      before do
        visit project_merge_request_path(project, merge_request)
      end

      it 'shows a link to the conflict resolution page' do
        expect(page).to have_link('conflicts', href: /\/conflicts\Z/)
      end

      context 'in Inline view mode' do
        before do
          click_link('conflicts', href: /\/conflicts\Z/)
        end

        include_examples "conflicts are resolved in Interactive mode"
        include_examples "conflicts are resolved in Edit inline mode"
      end

      context 'in Parallel view mode' do
        before do
          click_link('conflicts', href: /\/conflicts\Z/)
          click_button 'Side-by-side'
        end

        include_examples "conflicts are resolved in Interactive mode"
        include_examples "conflicts are resolved in Edit inline mode"
      end
    end

    context 'the conflict contain markers' do
      let(:merge_request) { create_merge_request('conflict-contains-conflict-markers') }

      before do
        visit project_merge_request_path(project, merge_request)
        click_link('conflicts', href: /\/conflicts\Z/)
      end

      it 'conflicts can not be resolved in Interactive mode' do
        within find('.files-wrapper .diff-file', text: 'files/markdown/ruby-style-guide.md') do
          expect(page).not_to have_content 'Interactive mode'
          expect(page).not_to have_content 'Edit inline'
        end
      end

      it 'conflicts are resolved in Edit inline mode' do
        within find('.files-wrapper .diff-file', text: 'files/markdown/ruby-style-guide.md') do
          wait_for_requests
          execute_script('ace.edit($(".files-wrapper .diff-file pre")[0]).setValue("Gregor Samsa woke from troubled dreams");')
        end

        click_button 'Commit conflict resolution'

        expect(page).to have_content('All merge conflicts were resolved')

        merge_request.reload_diff

        wait_for_requests

        click_on 'Changes'
        wait_for_requests
        click_link 'Expand all'
        wait_for_requests

        expect(page).to have_content('Gregor Samsa woke from troubled dreams')
      end
    end
  end

  UNRESOLVABLE_CONFLICTS = {
    'conflict-too-large' => 'when the conflicts contain a large file',
    'conflict-binary-file' => 'when the conflicts contain a binary file',
    'conflict-missing-side' => 'when the conflicts contain a file edited in one branch and deleted in another',
    'conflict-non-utf8' => 'when the conflicts contain a non-UTF-8 file'
  }.freeze

  UNRESOLVABLE_CONFLICTS.each do |source_branch, description|
    context description do
      let(:merge_request) { create_merge_request(source_branch) }

      before do
        project.team << [user, :developer]
        sign_in(user)

        visit project_merge_request_path(project, merge_request)
      end

      it 'does not show a link to the conflict resolution page' do
        expect(page).not_to have_link('conflicts', href: /\/conflicts\Z/)
      end

      it 'shows an error if the conflicts page is visited directly' do
        visit current_url + '/conflicts'
        wait_for_requests

        expect(find('#conflicts')).to have_content('Please try to resolve them locally.')
      end
    end
  end
end