1# frozen_string_literal: true 2 3require 'spec_helper' 4 5RSpec.describe 'Projects > Files > User edits files', :js do 6 include ProjectForksHelper 7 include BlobSpecHelpers 8 9 let(:project) { create(:project, :repository, name: 'Shop') } 10 let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') } 11 let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } 12 let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) } 13 let(:user) { create(:user) } 14 15 before do 16 sign_in(user) 17 end 18 19 after do 20 unset_default_button 21 end 22 23 shared_examples 'unavailable for an archived project' do 24 it 'does not show the edit link for an archived project', :js do 25 project.update!(archived: true) 26 visit project_tree_path(project, project.repository.root_ref) 27 28 click_link('.gitignore') 29 30 aggregate_failures 'available edit buttons' do 31 expect(page).not_to have_text('Edit') 32 expect(page).not_to have_text('Web IDE') 33 34 expect(page).not_to have_text('Replace') 35 expect(page).not_to have_text('Delete') 36 end 37 end 38 end 39 40 context 'when an user has write access', :js do 41 before do 42 project.add_maintainer(user) 43 visit(project_tree_path_root_ref) 44 wait_for_requests 45 end 46 47 it 'inserts a content of a file' do 48 set_default_button('edit') 49 click_link('.gitignore') 50 click_link_or_button('Edit') 51 find('.file-editor', match: :first) 52 53 find('#editor') 54 set_editor_value('*.rbca') 55 56 expect(editor_value).to eq('*.rbca') 57 end 58 59 it 'does not show the edit link if a file is binary' do 60 binary_file = File.join(project.repository.root_ref, 'files/images/logo-black.png') 61 visit(project_blob_path(project, binary_file)) 62 wait_for_requests 63 64 page.within '.content' do 65 expect(page).not_to have_link('edit') 66 end 67 end 68 69 it 'commits an edited file' do 70 set_default_button('edit') 71 click_link('.gitignore') 72 click_link_or_button('Edit') 73 find('.file-editor', match: :first) 74 75 find('#editor') 76 set_editor_value('*.rbca') 77 fill_in(:commit_message, with: 'New commit message', visible: true) 78 click_button('Commit changes') 79 80 expect(current_path).to eq(project_blob_path(project, 'master/.gitignore')) 81 82 wait_for_requests 83 84 expect(page).to have_content('*.rbca') 85 end 86 87 it 'commits an edited file to a new branch' do 88 set_default_button('edit') 89 click_link('.gitignore') 90 click_link_or_button('Edit') 91 92 find('.file-editor', match: :first) 93 94 find('#editor') 95 set_editor_value('*.rbca') 96 fill_in(:commit_message, with: 'New commit message', visible: true) 97 fill_in(:branch_name, with: 'new_branch_name', visible: true) 98 click_button('Commit changes') 99 100 expect(current_path).to eq(project_new_merge_request_path(project)) 101 102 click_link('Changes') 103 104 expect(page).to have_content('*.rbca') 105 end 106 107 it 'shows the diff of an edited file' do 108 set_default_button('edit') 109 click_link('.gitignore') 110 click_link_or_button('Edit') 111 find('.file-editor', match: :first) 112 113 find('#editor') 114 set_editor_value('*.rbca') 115 click_link('Preview changes') 116 117 expect(page).to have_css('.line_holder.new') 118 end 119 120 it_behaves_like 'unavailable for an archived project' 121 end 122 123 context 'when an user does not have write access', :js do 124 before do 125 project2.add_reporter(user) 126 visit(project2_tree_path_root_ref) 127 wait_for_requests 128 end 129 130 def expect_fork_prompt 131 expect(page).to have_selector(:link_or_button, 'Fork') 132 expect(page).to have_selector(:link_or_button, 'Cancel') 133 expect(page).to have_content( 134 "You can’t edit files directly in this project. "\ 135 "Fork this project and submit a merge request with your changes." 136 ) 137 end 138 139 def expect_fork_status 140 expect(page).to have_content( 141 "You're not allowed to make changes to this project directly. "\ 142 "A fork of this project has been created that you can make changes in, so you can submit a merge request." 143 ) 144 end 145 146 it 'inserts a content of a file in a forked project', :sidekiq_might_not_need_inline do 147 set_default_button('edit') 148 click_link('.gitignore') 149 click_link_or_button('Edit') 150 151 expect_fork_prompt 152 153 click_link_or_button('Fork project') 154 155 expect_fork_status 156 157 find('.file-editor', match: :first) 158 159 find('#editor') 160 set_editor_value('*.rbca') 161 162 expect(editor_value).to eq('*.rbca') 163 end 164 165 it 'opens the Web IDE in a forked project', :sidekiq_might_not_need_inline do 166 set_default_button('webide') 167 click_link('.gitignore') 168 click_link_or_button('Web IDE') 169 170 expect_fork_prompt 171 172 click_link_or_button('Fork project') 173 174 expect_fork_status 175 176 expect(page).to have_css('.ide-sidebar-project-title', text: "#{project2.name} #{user.namespace.full_path}/#{project2.path}") 177 expect(page).to have_css('.ide .multi-file-tab', text: '.gitignore') 178 end 179 180 it 'commits an edited file in a forked project', :sidekiq_might_not_need_inline do 181 set_default_button('edit') 182 click_link('.gitignore') 183 click_link_or_button('Edit') 184 185 expect_fork_prompt 186 click_link_or_button('Fork project') 187 188 find('.file-editor', match: :first) 189 190 find('#editor') 191 set_editor_value('*.rbca') 192 fill_in(:commit_message, with: 'New commit message', visible: true) 193 click_button('Commit changes') 194 195 fork = user.fork_of(project2.reload) 196 197 expect(current_path).to eq(project_new_merge_request_path(fork)) 198 199 wait_for_requests 200 201 expect(page).to have_content('New commit message') 202 end 203 204 context 'when the user already had a fork of the project', :js do 205 let!(:forked_project) { fork_project(project2, user, namespace: user.namespace, repository: true) } 206 207 before do 208 visit(project2_tree_path_root_ref) 209 wait_for_requests 210 end 211 212 it 'links to the forked project for editing', :sidekiq_might_not_need_inline do 213 set_default_button('edit') 214 click_link('.gitignore') 215 click_link_or_button('Edit') 216 217 expect(page).not_to have_link('Fork project') 218 219 find('#editor') 220 set_editor_value('*.rbca') 221 fill_in(:commit_message, with: 'Another commit', visible: true) 222 click_button('Commit changes') 223 224 fork = user.fork_of(project2) 225 226 expect(current_path).to eq(project_new_merge_request_path(fork)) 227 228 wait_for_requests 229 230 expect(page).to have_content('Another commit') 231 expect(page).to have_content("From #{forked_project.full_path}") 232 expect(page).to have_content("into #{project2.full_path}") 233 end 234 235 it_behaves_like 'unavailable for an archived project' do 236 let(:project) { project2 } 237 end 238 end 239 240 context 'when feature flag :consolidated_edit_button is off' do 241 before do 242 stub_feature_flags(consolidated_edit_button: false) 243 end 244 245 context 'when an user does not have write access', :js do 246 before do 247 project2.add_reporter(user) 248 visit(project2_tree_path_root_ref) 249 wait_for_requests 250 end 251 252 it 'inserts a content of a file in a forked project', :sidekiq_might_not_need_inline do 253 set_default_button('edit') 254 click_link('.gitignore') 255 click_link_or_button('Edit') 256 257 expect_fork_prompt 258 259 click_link_or_button('Fork') 260 261 expect_fork_status 262 263 find('.file-editor', match: :first) 264 265 find('#editor') 266 set_editor_value('*.rbca') 267 268 expect(editor_value).to eq('*.rbca') 269 end 270 271 it 'opens the Web IDE in a forked project', :sidekiq_might_not_need_inline do 272 set_default_button('webide') 273 click_link('.gitignore') 274 click_link_or_button('Web IDE') 275 276 expect_fork_prompt 277 278 click_link_or_button('Fork') 279 280 expect_fork_status 281 282 expect(page).to have_css('.ide-sidebar-project-title', text: "#{project2.name} #{user.namespace.full_path}/#{project2.path}") 283 expect(page).to have_css('.ide .multi-file-tab', text: '.gitignore') 284 end 285 286 it 'commits an edited file in a forked project', :sidekiq_might_not_need_inline do 287 set_default_button('edit') 288 click_link('.gitignore') 289 click_link_or_button('Edit') 290 291 expect_fork_prompt 292 293 click_link_or_button('Fork') 294 295 expect_fork_status 296 297 find('.file-editor', match: :first) 298 299 find('#editor') 300 set_editor_value('*.rbca') 301 fill_in(:commit_message, with: 'New commit message', visible: true) 302 click_button('Commit changes') 303 304 fork = user.fork_of(project2.reload) 305 306 expect(current_path).to eq(project_new_merge_request_path(fork)) 307 308 wait_for_requests 309 310 expect(page).to have_content('New commit message') 311 end 312 313 context 'when the user already had a fork of the project', :js do 314 let!(:forked_project) { fork_project(project2, user, namespace: user.namespace, repository: true) } 315 316 before do 317 visit(project2_tree_path_root_ref) 318 wait_for_requests 319 end 320 321 it 'links to the forked project for editing', :sidekiq_might_not_need_inline do 322 set_default_button('edit') 323 click_link('.gitignore') 324 click_link_or_button('Edit') 325 326 expect(page).not_to have_link('Fork') 327 328 find('#editor') 329 set_editor_value('*.rbca') 330 fill_in(:commit_message, with: 'Another commit', visible: true) 331 click_button('Commit changes') 332 333 fork = user.fork_of(project2) 334 335 expect(current_path).to eq(project_new_merge_request_path(fork)) 336 337 wait_for_requests 338 339 expect(page).to have_content('Another commit') 340 expect(page).to have_content("From #{forked_project.full_path}") 341 expect(page).to have_content("into #{project2.full_path}") 342 end 343 344 it_behaves_like 'unavailable for an archived project' do 345 let(:project) { project2 } 346 end 347 end 348 end 349 end 350 end 351end 352