diff options
Diffstat (limited to 'spec/features/projects')
74 files changed, 1335 insertions, 955 deletions
diff --git a/spec/features/projects/active_tabs_spec.rb b/spec/features/projects/active_tabs_spec.rb index b8c928004ed..2601dcf55c9 100644 --- a/spec/features/projects/active_tabs_spec.rb +++ b/spec/features/projects/active_tabs_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe 'Project active tab' do let_it_be(:project) { create(:project, :repository) } - let(:user) { project.owner } + let(:user) { project.first_owner } before do sign_in(user) diff --git a/spec/features/projects/activity/rss_spec.rb b/spec/features/projects/activity/rss_spec.rb index 9012b335bf4..a3e511b5c22 100644 --- a/spec/features/projects/activity/rss_spec.rb +++ b/spec/features/projects/activity/rss_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe 'Project Activity RSS' do let(:project) { create(:project, :public) } - let(:user) { project.owner } + let(:user) { project.first_owner } let(:path) { activity_project_path(project) } before do @@ -13,7 +13,7 @@ RSpec.describe 'Project Activity RSS' do context 'when signed in' do before do - sign_in(project.owner) + sign_in(project.first_owner) visit path end diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb index 62994d19fc0..77194fd6ca1 100644 --- a/spec/features/projects/blobs/blob_show_spec.rb +++ b/spec/features/projects/blobs/blob_show_spec.rb @@ -29,443 +29,421 @@ RSpec.describe 'File blob', :js do ).execute end - before do - stub_feature_flags(refactor_blob_viewer: false) # This stub will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/350455 - end - - context 'Ruby file' do - before do - visit_blob('files/ruby/popen.rb') - - wait_for_requests - end - - it 'displays the blob' do - aggregate_failures do - # shows highlighted Ruby code - expect(page).to have_css(".js-syntax-highlight") - expect(page).to have_content("require 'fileutils'") - - # does not show a viewer switcher - expect(page).not_to have_selector('.js-blob-viewer-switcher') - - # shows an enabled copy button - expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') - - # shows a raw button - expect(page).to have_link('Open raw') - end - end - - it 'displays file actions on all screen sizes' do - file_actions_selector = '.file-actions' - - resize_screen_sm - expect(page).to have_selector(file_actions_selector, visible: true) - - resize_screen_xs - expect(page).to have_selector(file_actions_selector, visible: true) - end - end - - context 'Markdown file' do - context 'visiting directly' do + context 'with refactor_blob_viewer feature flag enabled' do + context 'Ruby file' do before do - visit_blob('files/markdown/ruby-style-guide.md') + visit_blob('files/ruby/popen.rb') wait_for_requests end - it 'displays the blob using the rich viewer' do + it 'displays the blob' do aggregate_failures do - # hides the simple viewer - expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false) - expect(page).to have_selector('.blob-viewer[data-type="rich"]') - - # shows rendered Markdown - expect(page).to have_link("PEP-8") + # shows highlighted Ruby code + expect(page).to have_css(".js-syntax-highlight") + expect(page).to have_content("require 'fileutils'") - # shows a viewer switcher - expect(page).to have_selector('.js-blob-viewer-switcher') + # does not show a viewer switcher + expect(page).not_to have_selector('.js-blob-viewer-switcher') - # shows a disabled copy button - expect(page).to have_selector('.js-copy-blob-source-btn.disabled') + # shows an enabled copy button + expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') # shows a raw button expect(page).to have_link('Open raw') end end - context 'switching to the simple viewer' do + it 'displays file actions on all screen sizes' do + file_actions_selector = '.file-actions' + + resize_screen_sm + expect(page).to have_selector(file_actions_selector, visible: true) + + resize_screen_xs + expect(page).to have_selector(file_actions_selector, visible: true) + end + end + + context 'Markdown file' do + context 'visiting directly' do before do - find('.js-blob-viewer-switch-btn[data-viewer=simple]').click + visit_blob('files/markdown/ruby-style-guide.md') wait_for_requests end - it 'displays the blob using the simple viewer' do + it 'displays the blob using the rich viewer' do aggregate_failures do - # hides the rich viewer - expect(page).to have_selector('.blob-viewer[data-type="simple"]') - expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false) + # hides the simple viewer + expect(page).not_to have_selector('.blob-viewer[data-type="simple"]') + expect(page).to have_selector('.blob-viewer[data-type="rich"]') - # shows highlighted Markdown code - expect(page).to have_css(".js-syntax-highlight") - expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)") + # shows rendered Markdown + expect(page).to have_link("PEP-8") - # shows an enabled copy button - expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') + # shows a viewer switcher + expect(page).to have_selector('.js-blob-viewer-switcher') + + # shows a disabled copy button + expect(page).to have_selector('.js-copy-blob-source-btn.disabled') + + # shows a raw button + expect(page).to have_link('Open raw') end end - context 'switching to the rich viewer again' do + context 'switching to the simple viewer' do before do - find('.js-blob-viewer-switch-btn[data-viewer=rich]').click + find('.js-blob-viewer-switch-btn[data-viewer=simple]').click wait_for_requests end - it 'displays the blob using the rich viewer' do + it 'displays the blob using the simple viewer' do aggregate_failures do - # hides the simple viewer - expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false) - expect(page).to have_selector('.blob-viewer[data-type="rich"]') + # hides the rich viewer + expect(page).to have_selector('.blob-viewer[data-type="simple"]') + expect(page).not_to have_selector('.blob-viewer[data-type="rich"]') + + # shows highlighted Markdown code + expect(page).to have_css(".js-syntax-highlight") + expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)") # shows an enabled copy button expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') end end - end - end - end - context 'when ref switch' do - def switch_ref_to(ref_name) - first('.qa-branches-select').click # rubocop:disable QA/SelectorUsage - - page.within '.project-refs-form' do - click_link ref_name - wait_for_requests - end - end + context 'switching to the rich viewer again' do + before do + find('.js-blob-viewer-switch-btn[data-viewer=rich]').click - it 'displays single highlighted line number of different ref' do - visit_blob('files/js/application.js', anchor: 'L1') + wait_for_requests + end - switch_ref_to('feature') + it 'displays the blob using the rich viewer' do + aggregate_failures do + # hides the simple viewer + expect(page).not_to have_selector('.blob-viewer[data-type="simple"]') + expect(page).to have_selector('.blob-viewer[data-type="rich"]') - page.within '.blob-content' do - expect(find_by_id('LC1')[:class]).to include("hll") + # shows a disabled copy button + expect(page).to have_selector('.js-copy-blob-source-btn.disabled') + end + end + end end end - it 'displays multiple highlighted line numbers of different ref' do - visit_blob('files/js/application.js', anchor: 'L1-3') + context 'when ref switch' do + def switch_ref_to(ref_name) + first('.qa-branches-select').click # rubocop:disable QA/SelectorUsage - switch_ref_to('feature') - - page.within '.blob-content' do - expect(find_by_id('LC1')[:class]).to include("hll") - expect(find_by_id('LC2')[:class]).to include("hll") - expect(find_by_id('LC3')[:class]).to include("hll") + page.within '.project-refs-form' do + click_link ref_name + wait_for_requests + end end - end - it 'displays no highlighted number of different ref' do - Files::UpdateService.new( - project, - project.owner, - commit_message: 'Update', - start_branch: 'feature', - branch_name: 'feature', - file_path: 'files/js/application.js', - file_content: 'new content' - ).execute + it 'displays no highlighted number of different ref' do + Files::UpdateService.new( + project, + project.first_owner, + commit_message: 'Update', + start_branch: 'feature', + branch_name: 'feature', + file_path: 'files/js/application.js', + file_content: 'new content' + ).execute - project.commit('feature').diffs.diff_files.first + project.commit('feature').diffs.diff_files.first - visit_blob('files/js/application.js', anchor: 'L3') - switch_ref_to('feature') + visit_blob('files/js/application.js', anchor: 'L3') + switch_ref_to('feature') - page.within '.blob-content' do - expect(page).not_to have_css('.hll') + page.within '.blob-content' do + expect(page).not_to have_css('.hll') + end end - end - context 'successfully change ref of similar name' do - before do - project.repository.create_branch('dev') - project.repository.create_branch('development') - end + context 'successfully change ref of similar name' do + before do + project.repository.create_branch('dev') + project.repository.create_branch('development') + end - it 'switch ref from longer to shorter ref name' do - visit_blob('files/js/application.js', ref: 'development') - switch_ref_to('dev') + it 'switch ref from longer to shorter ref name' do + visit_blob('files/js/application.js', ref: 'development') + switch_ref_to('dev') - aggregate_failures do - expect(page.find('.file-title-name').text).to eq('application.js') - expect(page).not_to have_css('flash-container') + aggregate_failures do + expect(page.find('.file-title-name').text).to eq('application.js') + expect(page).not_to have_css('flash-container') + end end - end - it 'switch ref from shorter to longer ref name' do - visit_blob('files/js/application.js', ref: 'dev') - switch_ref_to('development') + it 'switch ref from shorter to longer ref name' do + visit_blob('files/js/application.js', ref: 'dev') + switch_ref_to('development') - aggregate_failures do - expect(page.find('.file-title-name').text).to eq('application.js') - expect(page).not_to have_css('flash-container') + aggregate_failures do + expect(page.find('.file-title-name').text).to eq('application.js') + expect(page).not_to have_css('flash-container') + end end end - end - it 'successfully changes ref when the ref name matches the project name' do - project.repository.create_branch(project.name) + it 'successfully changes ref when the ref name matches the project name' do + project.repository.create_branch(project.name) - visit_blob('files/js/application.js', ref: project.name) - switch_ref_to('master') + visit_blob('files/js/application.js', ref: project.name) + switch_ref_to('master') - aggregate_failures do - expect(page.find('.file-title-name').text).to eq('application.js') - expect(page).not_to have_css('flash-container') + aggregate_failures do + expect(page.find('.file-title-name').text).to eq('application.js') + expect(page).not_to have_css('flash-container') + end end end end - context 'visiting with a line number anchor' do + context 'Markdown rendering' do before do - visit_blob('files/markdown/ruby-style-guide.md', anchor: 'L1') - end + project.add_maintainer(project.creator) - it 'displays the blob using the simple viewer' do - aggregate_failures do - # hides the rich viewer - expect(page).to have_selector('.blob-viewer[data-type="simple"]') - expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false) + Files::CreateService.new( + project, + project.creator, + start_branch: 'master', + branch_name: 'master', + commit_message: "Add RedCarpet and CommonMark Markdown ", + file_path: 'files/commonmark/file.md', + file_content: "1. one\n - sublist\n" + ).execute + end - # highlights the line in question - expect(page).to have_selector('#LC1.hll') + context 'when rendering default markdown' do + before do + visit_blob('files/commonmark/file.md') - # shows highlighted Markdown code - expect(page).to have_css(".js-syntax-highlight") - expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)") + wait_for_requests + end - # shows an enabled copy button - expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') + it 'renders using CommonMark' do + aggregate_failures do + expect(page).to have_content("sublist") + expect(page).not_to have_xpath("//ol//li//ul") + end end end end - end - - context 'Markdown rendering' do - before do - project.add_maintainer(project.creator) - - Files::CreateService.new( - project, - project.creator, - start_branch: 'master', - branch_name: 'master', - commit_message: "Add RedCarpet and CommonMark Markdown ", - file_path: 'files/commonmark/file.md', - file_content: "1. one\n - sublist\n" - ).execute - end - context 'when rendering default markdown' do + context 'Markdown file (stored in LFS)' do before do - visit_blob('files/commonmark/file.md') - - wait_for_requests - end + project.add_maintainer(project.creator) - it 'renders using CommonMark' do - aggregate_failures do - expect(page).to have_content("sublist") - expect(page).not_to have_xpath("//ol//li//ul") - end + Files::CreateService.new( + project, + project.creator, + start_branch: 'master', + branch_name: 'master', + commit_message: "Add Markdown in LFS", + file_path: 'files/lfs/file.md', + file_content: project.repository.blob_at('master', 'files/lfs/lfs_object.iso').data + ).execute end - end - end - context 'Markdown file (stored in LFS)' do - before do - project.add_maintainer(project.creator) - - Files::CreateService.new( - project, - project.creator, - start_branch: 'master', - branch_name: 'master', - commit_message: "Add Markdown in LFS", - file_path: 'files/lfs/file.md', - file_content: project.repository.blob_at('master', 'files/lfs/lfs_object.iso').data - ).execute - end - - context 'when LFS is enabled on the project' do - before do - allow(Gitlab.config.lfs).to receive(:enabled).and_return(true) - project.update_attribute(:lfs_enabled, true) + context 'when LFS is enabled on the project' do + before do + allow(Gitlab.config.lfs).to receive(:enabled).and_return(true) + project.update_attribute(:lfs_enabled, true) - visit_blob('files/lfs/file.md') + visit_blob('files/lfs/file.md') - wait_for_requests - end + wait_for_requests + end - it 'displays an error' do - aggregate_failures do - # hides the simple viewer - expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false) - expect(page).to have_selector('.blob-viewer[data-type="rich"]') + it 'displays an error' do + aggregate_failures do + # hides the simple viewer + expect(page).not_to have_selector('.blob-viewer[data-type="simple"]') + expect(page).not_to have_selector('.blob-viewer[data-type="rich"]') - # shows an error message - expect(page).to have_content('The rendered file could not be displayed because it is stored in LFS. You can download it instead.') + # shows an error message + expect(page).to have_content('This content could not be displayed because it is stored in LFS. You can download it instead.') - # shows a viewer switcher - expect(page).to have_selector('.js-blob-viewer-switcher') + # does not show a viewer switcher + expect(page).not_to have_selector('.js-blob-viewer-switcher') - # does not show a copy button - expect(page).not_to have_selector('.js-copy-blob-source-btn') + # does not show a copy button + expect(page).not_to have_selector('.js-copy-blob-source-btn') - # shows a download button - expect(page).to have_link('Download') + # shows a download button + expect(page).to have_link('Download') + end end end - context 'switching to the simple viewer' do + context 'when LFS is disabled on the project' do before do - find('.js-blob-viewer-switcher .js-blob-viewer-switch-btn[data-viewer=simple]').click + visit_blob('files/lfs/file.md') wait_for_requests end - it 'displays an error' do + it 'displays the blob' do aggregate_failures do - # hides the rich viewer - expect(page).to have_selector('.blob-viewer[data-type="simple"]') - expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false) + # shows text + expect(page).to have_content('size 1575078') - # shows an error message - expect(page).to have_content('The source could not be displayed because it is stored in LFS. You can download it instead.') + # does not show a viewer switcher + expect(page).not_to have_selector('.js-blob-viewer-switcher') - # does not show a copy button - expect(page).not_to have_selector('.js-copy-blob-source-btn') + # shows an enabled copy button + expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') + + # shows a raw button + expect(page).to have_link('Open raw') end end end end - context 'when LFS is disabled on the project' do + context 'PDF file' do before do - visit_blob('files/lfs/file.md') + project.add_maintainer(project.creator) + + Files::CreateService.new( + project, + project.creator, + start_branch: 'master', + branch_name: 'master', + commit_message: "Add PDF", + file_path: 'files/test.pdf', + file_content: project.repository.blob_at('add-pdf-file', 'files/pdf/test.pdf').data + ).execute + + visit_blob('files/test.pdf') wait_for_requests end it 'displays the blob' do aggregate_failures do - # shows text - expect(page).to have_content('size 1575078') + # shows rendered PDF + expect(page).to have_selector('.js-pdf-viewer') # does not show a viewer switcher expect(page).not_to have_selector('.js-blob-viewer-switcher') - # shows an enabled copy button - expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') + # does not show a copy button + expect(page).not_to have_selector('.js-copy-blob-source-btn') - # shows a raw button - expect(page).to have_link('Open raw') + # shows a download button + expect(page).to have_link('Download') end end end - end - context 'PDF file' do - before do - project.add_maintainer(project.creator) + context 'Jupiter Notebook file' do + before do + project.add_maintainer(project.creator) - Files::CreateService.new( - project, - project.creator, - start_branch: 'master', - branch_name: 'master', - commit_message: "Add PDF", - file_path: 'files/test.pdf', - file_content: project.repository.blob_at('add-pdf-file', 'files/pdf/test.pdf').data - ).execute + Files::CreateService.new( + project, + project.creator, + start_branch: 'master', + branch_name: 'master', + commit_message: "Add Jupiter Notebook", + file_path: 'files/basic.ipynb', + file_content: project.repository.blob_at('add-ipython-files', 'files/ipython/basic.ipynb').data + ).execute - visit_blob('files/test.pdf') + visit_blob('files/basic.ipynb') - wait_for_requests - end + wait_for_requests + end - it 'displays the blob' do - aggregate_failures do - # shows rendered PDF - expect(page).to have_selector('.js-pdf-viewer') + it 'displays the blob' do + aggregate_failures do + # shows rendered notebook + expect(page).to have_selector('.js-notebook-viewer-mounted') + + # does show a viewer switcher + expect(page).to have_selector('.js-blob-viewer-switcher') + + # show a disabled copy button + expect(page).to have_selector('.js-copy-blob-source-btn.disabled') - # does not show a viewer switcher - expect(page).not_to have_selector('.js-blob-viewer-switcher') + # shows a raw button + expect(page).to have_link('Open raw') - # does not show a copy button - expect(page).not_to have_selector('.js-copy-blob-source-btn') + # shows a download button + expect(page).to have_link('Download') - # shows a download button - expect(page).to have_link('Download') + # shows the rendered notebook + expect(page).to have_content('test') + end end end - end - context 'Jupiter Notebook file' do - before do - project.add_maintainer(project.creator) + context 'ISO file (stored in LFS)' do + context 'when LFS is enabled on the project' do + before do + allow(Gitlab.config.lfs).to receive(:enabled).and_return(true) + project.update_attribute(:lfs_enabled, true) - Files::CreateService.new( - project, - project.creator, - start_branch: 'master', - branch_name: 'master', - commit_message: "Add Jupiter Notebook", - file_path: 'files/basic.ipynb', - file_content: project.repository.blob_at('add-ipython-files', 'files/ipython/basic.ipynb').data - ).execute + visit_blob('files/lfs/lfs_object.iso') - visit_blob('files/basic.ipynb') + wait_for_requests + end - wait_for_requests - end + it 'displays the blob' do + aggregate_failures do + # shows a download link + expect(page).to have_link('Download (1.50 MiB)') + + # does not show a viewer switcher + expect(page).not_to have_selector('.js-blob-viewer-switcher') + + # does not show a copy button + expect(page).not_to have_selector('.js-copy-blob-source-btn') + + # shows a download button + expect(page).to have_link('Download') + end + end + end - it 'displays the blob' do - aggregate_failures do - # shows rendered notebook - expect(page).to have_selector('.js-notebook-viewer-mounted') + context 'when LFS is disabled on the project' do + before do + visit_blob('files/lfs/lfs_object.iso') - # does show a viewer switcher - expect(page).to have_selector('.js-blob-viewer-switcher') + wait_for_requests + end - # show a disabled copy button - expect(page).to have_selector('.js-copy-blob-source-btn.disabled') + it 'displays the blob' do + aggregate_failures do + # shows text + expect(page).to have_content('size 1575078') - # shows a raw button - expect(page).to have_link('Open raw') + # does not show a viewer switcher + expect(page).not_to have_selector('.js-blob-viewer-switcher') - # shows a download button - expect(page).to have_link('Download') + # shows an enabled copy button + expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') - # shows the rendered notebook - expect(page).to have_content('test') + # shows a raw button + expect(page).to have_link('Open raw') + end + end end end - end - context 'ISO file (stored in LFS)' do - context 'when LFS is enabled on the project' do + context 'ZIP file' do before do - allow(Gitlab.config.lfs).to receive(:enabled).and_return(true) - project.update_attribute(:lfs_enabled, true) - - visit_blob('files/lfs/lfs_object.iso') + visit_blob('Gemfile.zip') wait_for_requests end @@ -473,7 +451,7 @@ RSpec.describe 'File blob', :js do it 'displays the blob' do aggregate_failures do # shows a download link - expect(page).to have_link('Download (1.5 MB)') + expect(page).to have_link('Download (2.11 KiB)') # does not show a viewer switcher expect(page).not_to have_selector('.js-blob-viewer-switcher') @@ -487,578 +465,703 @@ RSpec.describe 'File blob', :js do end end - context 'when LFS is disabled on the project' do + context 'empty file' do before do - visit_blob('files/lfs/lfs_object.iso') + project.add_maintainer(project.creator) + + Files::CreateService.new( + project, + project.creator, + start_branch: 'master', + branch_name: 'master', + commit_message: "Add empty file", + file_path: 'files/empty.md', + file_content: '' + ).execute + + visit_blob('files/empty.md') wait_for_requests end - it 'displays the blob' do + it 'displays an error' do aggregate_failures do - # shows text - expect(page).to have_content('size 1575078') + # shows an error message + expect(page).to have_content('Empty file') # does not show a viewer switcher expect(page).not_to have_selector('.js-blob-viewer-switcher') - # shows an enabled copy button - expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') + # does not show a copy button + expect(page).not_to have_selector('.js-copy-blob-source-btn') - # shows a raw button - expect(page).to have_link('Open raw') + # does not show a download or raw button + expect(page).not_to have_link('Download') + expect(page).not_to have_link('Open raw') end end end - end - - context 'ZIP file' do - before do - visit_blob('Gemfile.zip') - wait_for_requests - end + context 'files with auxiliary viewers' do + describe '.gitlab-ci.yml' do + before do + project.add_maintainer(project.creator) - it 'displays the blob' do - aggregate_failures do - # shows a download link - expect(page).to have_link('Download (2.11 KB)') + Files::CreateService.new( + project, + project.creator, + start_branch: 'master', + branch_name: 'master', + commit_message: "Add .gitlab-ci.yml", + file_path: '.gitlab-ci.yml', + file_content: File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) + ).execute - # does not show a viewer switcher - expect(page).not_to have_selector('.js-blob-viewer-switcher') + visit_blob('.gitlab-ci.yml') + end - # does not show a copy button - expect(page).not_to have_selector('.js-copy-blob-source-btn') + it 'displays an auxiliary viewer' do + aggregate_failures do + # shows that configuration is valid + expect(page).to have_content('This GitLab CI configuration is valid.') - # shows a download button - expect(page).to have_link('Download') + # shows a learn more link + expect(page).to have_link('Learn more') + end + end end - end - end - context 'empty file' do - before do - project.add_maintainer(project.creator) + describe '.gitlab/route-map.yml' do + before do + project.add_maintainer(project.creator) + + Files::CreateService.new( + project, + project.creator, + start_branch: 'master', + branch_name: 'master', + commit_message: "Add .gitlab/route-map.yml", + file_path: '.gitlab/route-map.yml', + file_content: <<-MAP.strip_heredoc + # Team data + - source: 'data/team.yml' + public: 'team/' + MAP + ).execute - Files::CreateService.new( - project, - project.creator, - start_branch: 'master', - branch_name: 'master', - commit_message: "Add empty file", - file_path: 'files/empty.md', - file_content: '' - ).execute + visit_blob('.gitlab/route-map.yml') + end - visit_blob('files/empty.md') + it 'displays an auxiliary viewer' do + aggregate_failures do + # shows that map is valid + expect(page).to have_content('This Route Map is valid.') - wait_for_requests - end + # shows a learn more link + expect(page).to have_link('Learn more') + end + end + end - it 'displays an error' do - aggregate_failures do - # shows an error message - expect(page).to have_content('Empty file') + describe '.gitlab/dashboards/custom-dashboard.yml' do + before do + project.add_maintainer(project.creator) - # does not show a viewer switcher - expect(page).not_to have_selector('.js-blob-viewer-switcher') + Files::CreateService.new( + project, + project.creator, + start_branch: 'master', + branch_name: 'master', + commit_message: "Add .gitlab/dashboards/custom-dashboard.yml", + file_path: '.gitlab/dashboards/custom-dashboard.yml', + file_content: file_content + ).execute + end - # does not show a copy button - expect(page).not_to have_selector('.js-copy-blob-source-btn') + context 'with metrics_dashboard_exhaustive_validations feature flag off' do + before do + stub_feature_flags(metrics_dashboard_exhaustive_validations: false) + visit_blob('.gitlab/dashboards/custom-dashboard.yml') + end - # does not show a download or raw button - expect(page).not_to have_link('Download') - expect(page).not_to have_link('Open raw') - end - end - end + context 'valid dashboard file' do + let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) } - context 'binary file that appears to be text in the first 1024 bytes' do - before do - visit_blob('encoding/binary-1.bin', ref: 'binary-encoding') - end + it 'displays an auxiliary viewer' do + aggregate_failures do + # shows that dashboard yaml is valid + expect(page).to have_content('Metrics Dashboard YAML definition is valid.') - it 'displays the blob' do - aggregate_failures do - # shows a download link - expect(page).to have_link('Download (23.8 KB)') + # shows a learn more link + expect(page).to have_link('Learn more') + end + end + end - # does not show a viewer switcher - expect(page).not_to have_selector('.js-blob-viewer-switcher') + context 'invalid dashboard file' do + let(:file_content) { "dashboard: 'invalid'" } - # The specs below verify an arguably incorrect result, but since we only - # learn that the file is not actually text once the text viewer content - # is loaded asynchronously, there is no straightforward way to get these - # synchronously loaded elements to display correctly. - # - # Clicking the copy button will result in nothing being copied. - # Clicking the raw button will result in the binary file being downloaded, - # as expected. + it 'displays an auxiliary viewer' do + aggregate_failures do + # shows that dashboard yaml is invalid + expect(page).to have_content('Metrics Dashboard YAML definition is invalid:') + expect(page).to have_content("panel_groups: should be an array of panel_groups objects") - # shows an enabled copy button, incorrectly - expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') + # shows a learn more link + expect(page).to have_link('Learn more') + end + end + end + end - # shows a raw button, incorrectly - expect(page).to have_link('Open raw') - end - end - end + context 'with metrics_dashboard_exhaustive_validations feature flag on' do + before do + stub_feature_flags(metrics_dashboard_exhaustive_validations: true) + visit_blob('.gitlab/dashboards/custom-dashboard.yml') + end - context 'files with auxiliary viewers' do - before do - stub_feature_flags(refactor_blob_viewer: true) - end + context 'valid dashboard file' do + let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) } - describe '.gitlab-ci.yml' do - before do - project.add_maintainer(project.creator) + it 'displays an auxiliary viewer' do + aggregate_failures do + # shows that dashboard yaml is valid + expect(page).to have_content('Metrics Dashboard YAML definition is valid.') - Files::CreateService.new( - project, - project.creator, - start_branch: 'master', - branch_name: 'master', - commit_message: "Add .gitlab-ci.yml", - file_path: '.gitlab-ci.yml', - file_content: File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) - ).execute + # shows a learn more link + expect(page).to have_link('Learn more') + end + end + end - visit_blob('.gitlab-ci.yml') - end + context 'invalid dashboard file' do + let(:file_content) { "dashboard: 'invalid'" } - it 'displays an auxiliary viewer' do - aggregate_failures do - # shows that configuration is valid - expect(page).to have_content('This GitLab CI configuration is valid.') + it 'displays an auxiliary viewer' do + aggregate_failures do + # shows that dashboard yaml is invalid + expect(page).to have_content('Metrics Dashboard YAML definition is invalid:') + expect(page).to have_content("root is missing required keys: panel_groups") - # shows a learn more link - expect(page).to have_link('Learn more') + # shows a learn more link + expect(page).to have_link('Learn more') + end + end + end end end - end - describe '.gitlab/route-map.yml' do - before do - project.add_maintainer(project.creator) + context 'LICENSE' do + before do + visit_blob('LICENSE') + end - Files::CreateService.new( - project, - project.creator, - start_branch: 'master', - branch_name: 'master', - commit_message: "Add .gitlab/route-map.yml", - file_path: '.gitlab/route-map.yml', - file_content: <<-MAP.strip_heredoc - # Team data - - source: 'data/team.yml' - public: 'team/' - MAP - ).execute + it 'displays an auxiliary viewer' do + aggregate_failures do + # shows license + expect(page).to have_content('This project is licensed under the MIT License.') - visit_blob('.gitlab/route-map.yml') + # shows a learn more link + expect(page).to have_link('Learn more', href: 'http://choosealicense.com/licenses/mit/') + end + end end - it 'displays an auxiliary viewer' do - aggregate_failures do - # shows that map is valid - expect(page).to have_content('This Route Map is valid.') + context '*.gemspec' do + before do + project.add_maintainer(project.creator) - # shows a learn more link - expect(page).to have_link('Learn more') + Files::CreateService.new( + project, + project.creator, + start_branch: 'master', + branch_name: 'master', + commit_message: "Add activerecord.gemspec", + file_path: 'activerecord.gemspec', + file_content: <<-SPEC.strip_heredoc + Gem::Specification.new do |s| + s.platform = Gem::Platform::RUBY + s.name = "activerecord" + end + SPEC + ).execute + + visit_blob('activerecord.gemspec') end - end - end - describe '.gitlab/dashboards/custom-dashboard.yml' do - before do - project.add_maintainer(project.creator) + it 'displays an auxiliary viewer' do + aggregate_failures do + # shows names of dependency manager and package + expect(page).to have_content('This project manages its dependencies using RubyGems.') - Files::CreateService.new( - project, - project.creator, - start_branch: 'master', - branch_name: 'master', - commit_message: "Add .gitlab/dashboards/custom-dashboard.yml", - file_path: '.gitlab/dashboards/custom-dashboard.yml', - file_content: file_content - ).execute + # shows a learn more link + expect(page).to have_link('Learn more', href: 'https://rubygems.org/') + end + end end - context 'with metrics_dashboard_exhaustive_validations feature flag off' do + context 'CONTRIBUTING.md' do before do - stub_feature_flags(metrics_dashboard_exhaustive_validations: false) - visit_blob('.gitlab/dashboards/custom-dashboard.yml') + file_name = 'CONTRIBUTING.md' + + create_file(file_name, '## Contribution guidelines') + visit_blob(file_name) end - context 'valid dashboard file' do - let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) } + it 'displays an auxiliary viewer' do + aggregate_failures do + expect(page).to have_content("After you've reviewed these contribution guidelines, you'll be all set to contribute to this project.") + end + end + end - it 'displays an auxiliary viewer' do - aggregate_failures do - # shows that dashboard yaml is valid - expect(page).to have_content('Metrics Dashboard YAML definition is valid.') + context 'CHANGELOG.md' do + before do + file_name = 'CHANGELOG.md' - # shows a learn more link - expect(page).to have_link('Learn more') - end + create_file(file_name, '## Changelog for v1.0.0') + visit_blob(file_name) + end + + it 'displays an auxiliary viewer' do + aggregate_failures do + expect(page).to have_content("To find the state of this project's repository at the time of any of these versions, check out the tags.") end end + end - context 'invalid dashboard file' do - let(:file_content) { "dashboard: 'invalid'" } + context 'Cargo.toml' do + before do + file_name = 'Cargo.toml' - it 'displays an auxiliary viewer' do - aggregate_failures do - # shows that dashboard yaml is invalid - expect(page).to have_content('Metrics Dashboard YAML definition is invalid:') - expect(page).to have_content("panel_groups: should be an array of panel_groups objects") + create_file(file_name, ' + [package] + name = "hello_world" # the name of the package + version = "0.1.0" # the current version, obeying semver + authors = ["Alice <a@example.com>", "Bob <b@example.com>"] + ') + visit_blob(file_name) + end - # shows a learn more link - expect(page).to have_link('Learn more') - end + it 'displays an auxiliary viewer' do + aggregate_failures do + expect(page).to have_content("This project manages its dependencies using Cargo.") end end end - context 'with metrics_dashboard_exhaustive_validations feature flag on' do + context 'Cartfile' do before do - stub_feature_flags(metrics_dashboard_exhaustive_validations: true) - visit_blob('.gitlab/dashboards/custom-dashboard.yml') + file_name = 'Cartfile' + + create_file(file_name, ' + gitlab "Alamofire/Alamofire" == 4.9.0 + gitlab "Alamofire/AlamofireImage" ~> 3.4 + ') + visit_blob(file_name) + end + + it 'displays an auxiliary viewer' do + aggregate_failures do + expect(page).to have_content("This project manages its dependencies using Carthage.") + end end + end - context 'valid dashboard file' do - let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) } + context 'composer.json' do + before do + file_name = 'composer.json' - it 'displays an auxiliary viewer' do - aggregate_failures do - # shows that dashboard yaml is valid - expect(page).to have_content('Metrics Dashboard YAML definition is valid.') + create_file(file_name, ' + { + "license": "MIT" + } + ') + visit_blob(file_name) + end - # shows a learn more link - expect(page).to have_link('Learn more') - end + it 'displays an auxiliary viewer' do + aggregate_failures do + expect(page).to have_content("This project manages its dependencies using Composer.") end end + end - context 'invalid dashboard file' do - let(:file_content) { "dashboard: 'invalid'" } + context 'Gemfile' do + before do + file_name = 'Gemfile' - it 'displays an auxiliary viewer' do - aggregate_failures do - # shows that dashboard yaml is invalid - expect(page).to have_content('Metrics Dashboard YAML definition is invalid:') - expect(page).to have_content("root is missing required keys: panel_groups") + create_file(file_name, ' + source "https://rubygems.org" - # shows a learn more link - expect(page).to have_link('Learn more') - end + # Gems here + ') + visit_blob(file_name) + end + + it 'displays an auxiliary viewer' do + aggregate_failures do + expect(page).to have_content("This project manages its dependencies using Bundler.") end end end - end - context 'LICENSE' do - before do - visit_blob('LICENSE') - end + context 'Godeps.json' do + before do + file_name = 'Godeps.json' - it 'displays an auxiliary viewer' do - aggregate_failures do - # shows license - expect(page).to have_content('This project is licensed under the MIT License.') + create_file(file_name, ' + { + "GoVersion": "go1.6" + } + ') + visit_blob(file_name) + end - # shows a learn more link - expect(page).to have_link('Learn more', href: 'http://choosealicense.com/licenses/mit/') + it 'displays an auxiliary viewer' do + aggregate_failures do + expect(page).to have_content("This project manages its dependencies using godep.") + end end end - end - context '*.gemspec' do - before do - project.add_maintainer(project.creator) + context 'go.mod' do + before do + file_name = 'go.mod' - Files::CreateService.new( - project, - project.creator, - start_branch: 'master', - branch_name: 'master', - commit_message: "Add activerecord.gemspec", - file_path: 'activerecord.gemspec', - file_content: <<-SPEC.strip_heredoc - Gem::Specification.new do |s| - s.platform = Gem::Platform::RUBY - s.name = "activerecord" - end - SPEC - ).execute + create_file(file_name, ' + module example.com/mymodule + + go 1.14 + ') + visit_blob(file_name) + end - visit_blob('activerecord.gemspec') + it 'displays an auxiliary viewer' do + aggregate_failures do + expect(page).to have_content("This project manages its dependencies using Go Modules.") + end + end end - it 'displays an auxiliary viewer' do - aggregate_failures do - # shows names of dependency manager and package - expect(page).to have_content('This project manages its dependencies using RubyGems.') + context 'package.json' do + before do + file_name = 'package.json' - # shows a learn more link - expect(page).to have_link('Learn more', href: 'https://rubygems.org/') + create_file(file_name, ' + { + "name": "my-awesome-package", + "version": "1.0.0" + } + ') + visit_blob(file_name) + end + + it 'displays an auxiliary viewer' do + aggregate_failures do + expect(page).to have_content("This project manages its dependencies using npm.") + end end end - end - context 'CONTRIBUTING.md' do - before do - file_name = 'CONTRIBUTING.md' + context 'podfile' do + before do + file_name = 'podfile' - create_file(file_name, '## Contribution guidelines') - visit_blob(file_name) - end + create_file(file_name, 'platform :ios, "8.0"') + visit_blob(file_name) + end - it 'displays an auxiliary viewer' do - aggregate_failures do - expect(page).to have_content("After you've reviewed these contribution guidelines, you'll be all set to contribute to this project.") + it 'displays an auxiliary viewer' do + aggregate_failures do + expect(page).to have_content("This project manages its dependencies using CocoaPods.") + end end end - end - context 'CHANGELOG.md' do - before do - file_name = 'CHANGELOG.md' + context 'test.podspec' do + before do + file_name = 'test.podspec' - create_file(file_name, '## Changelog for v1.0.0') - visit_blob(file_name) - end + create_file(file_name, ' + Pod::Spec.new do |s| + s.name = "TensorFlowLiteC" + ') + visit_blob(file_name) + end - it 'displays an auxiliary viewer' do - aggregate_failures do - expect(page).to have_content("To find the state of this project's repository at the time of any of these versions, check out the tags.") + it 'displays an auxiliary viewer' do + aggregate_failures do + expect(page).to have_content("This project manages its dependencies using CocoaPods.") + end end end - end - context 'Cargo.toml' do - before do - file_name = 'Cargo.toml' + context 'JSON.podspec.json' do + before do + file_name = 'JSON.podspec.json' - create_file(file_name, ' - [package] - name = "hello_world" # the name of the package - version = "0.1.0" # the current version, obeying semver - authors = ["Alice <a@example.com>", "Bob <b@example.com>"] - ') - visit_blob(file_name) - end + create_file(file_name, ' + { + "name": "JSON" + } + ') + visit_blob(file_name) + end - it 'displays an auxiliary viewer' do - aggregate_failures do - expect(page).to have_content("This project manages its dependencies using Cargo.") + it 'displays an auxiliary viewer' do + aggregate_failures do + expect(page).to have_content("This project manages its dependencies using CocoaPods.") + end end end - end - context 'Cartfile' do - before do - file_name = 'Cartfile' + context 'requirements.txt' do + before do + file_name = 'requirements.txt' - create_file(file_name, ' - gitlab "Alamofire/Alamofire" == 4.9.0 - gitlab "Alamofire/AlamofireImage" ~> 3.4 - ') - visit_blob(file_name) + create_file(file_name, 'Project requirements') + visit_blob(file_name) + end + + it 'displays an auxiliary viewer' do + aggregate_failures do + expect(page).to have_content("This project manages its dependencies using pip.") + end + end end - it 'displays an auxiliary viewer' do - aggregate_failures do - expect(page).to have_content("This project manages its dependencies using Carthage.") + context 'yarn.lock' do + before do + file_name = 'yarn.lock' + + create_file(file_name, ' + # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. + # yarn lockfile v1 + ') + visit_blob(file_name) + end + + it 'displays an auxiliary viewer' do + aggregate_failures do + expect(page).to have_content("This project manages its dependencies using Yarn.") + end end end end - context 'composer.json' do + context 'realtime pipelines' do before do - file_name = 'composer.json' + Files::CreateService.new( + project, + project.creator, + start_branch: 'feature', + branch_name: 'feature', + commit_message: "Add ruby file", + file_path: 'files/ruby/test.rb', + file_content: "# Awesome content" + ).execute - create_file(file_name, ' - { - "license": "MIT" - } - ') - visit_blob(file_name) + create(:ci_pipeline, status: 'running', project: project, ref: 'feature', sha: project.commit('feature').sha) + visit_blob('files/ruby/test.rb', ref: 'feature') end - it 'displays an auxiliary viewer' do - aggregate_failures do - expect(page).to have_content("This project manages its dependencies using Composer.") + it 'shows the realtime pipeline status' do + page.within('.commit-actions') do + expect(page).to have_css('.ci-status-icon') + expect(page).to have_css('.ci-status-icon-running') + expect(page).to have_css('.js-ci-status-icon-running') end end end - context 'Gemfile' do - before do - file_name = 'Gemfile' + context 'for subgroups' do + let(:group) { create(:group) } + let(:subgroup) { create(:group, parent: group) } + let(:project) { create(:project, :public, :repository, group: subgroup) } - create_file(file_name, ' - source "https://rubygems.org" + it 'renders tree table without errors' do + visit_blob('README.md') - # Gems here - ') - visit_blob(file_name) + expect(page).to have_selector('.file-content') + expect(page).not_to have_selector('[data-testid="alert-danger"]') end - it 'displays an auxiliary viewer' do - aggregate_failures do - expect(page).to have_content("This project manages its dependencies using Bundler.") - end + it 'displays a GPG badge' do + visit_blob('CONTRIBUTING.md', ref: '33f3729a45c02fc67d00adb1b8bca394b0e761d9') + + expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge' + expect(page).to have_selector '.gpg-status-box.invalid' end end - context 'Godeps.json' do - before do - file_name = 'Godeps.json' + context 'on signed merge commit' do + it 'displays a GPG badge' do + visit_blob('conflicting-file.md', ref: '6101e87e575de14b38b4e1ce180519a813671e10') - create_file(file_name, ' - { - "GoVersion": "go1.6" - } - ') - visit_blob(file_name) - end - - it 'displays an auxiliary viewer' do - aggregate_failures do - expect(page).to have_content("This project manages its dependencies using godep.") - end + expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge' + expect(page).to have_selector '.gpg-status-box.invalid' end end - context 'go.mod' do + context 'when static objects external storage is enabled' do before do - file_name = 'go.mod' + stub_application_setting(static_objects_external_storage_url: 'https://cdn.gitlab.com') + end - create_file(file_name, ' - module example.com/mymodule + context 'public project' do + before do + visit_blob('README.md') + end - go 1.14 - ') - visit_blob(file_name) - end + it 'shows open raw and download buttons with external storage URL prepended to their href' do + path = project_raw_path(project, 'master/README.md') + raw_uri = "https://cdn.gitlab.com#{path}" + download_uri = "https://cdn.gitlab.com#{path}?inline=false" - it 'displays an auxiliary viewer' do - aggregate_failures do - expect(page).to have_content("This project manages its dependencies using Go Modules.") + aggregate_failures do + expect(page).to have_link 'Open raw', href: raw_uri + expect(page).to have_link 'Download', href: download_uri + end end end end + end - context 'package.json' do - before do - file_name = 'package.json' + context 'with refactor_blob_viewer feature flag disabled' do + before do + stub_feature_flags(refactor_blob_viewer: false) + end - create_file(file_name, ' - { - "name": "my-awesome-package", - "version": "1.0.0" - } - ') - visit_blob(file_name) - end + context 'when ref switch' do + # We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled + # This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351558 - it 'displays an auxiliary viewer' do - aggregate_failures do - expect(page).to have_content("This project manages its dependencies using npm.") + def switch_ref_to(ref_name) + first('.qa-branches-select').click # rubocop:disable QA/SelectorUsage + + page.within '.project-refs-form' do + click_link ref_name + wait_for_requests end end - end - context 'podfile' do - before do - file_name = 'podfile' + context 'when highlighting lines' do + it 'displays single highlighted line number of different ref' do + visit_blob('files/js/application.js', anchor: 'L1') - create_file(file_name, 'platform :ios, "8.0"') - visit_blob(file_name) - end + switch_ref_to('feature') - it 'displays an auxiliary viewer' do - aggregate_failures do - expect(page).to have_content("This project manages its dependencies using CocoaPods.") + page.within '.blob-content' do + expect(find_by_id('LC1')[:class]).to include("hll") + end end - end - end - context 'test.podspec' do - before do - file_name = 'test.podspec' + it 'displays multiple highlighted line numbers of different ref' do + visit_blob('files/js/application.js', anchor: 'L1-3') - create_file(file_name, ' - Pod::Spec.new do |s| - s.name = "TensorFlowLiteC" - ') - visit_blob(file_name) - end + switch_ref_to('feature') - it 'displays an auxiliary viewer' do - aggregate_failures do - expect(page).to have_content("This project manages its dependencies using CocoaPods.") + page.within '.blob-content' do + expect(find_by_id('LC1')[:class]).to include("hll") + expect(find_by_id('LC2')[:class]).to include("hll") + expect(find_by_id('LC3')[:class]).to include("hll") + end end end end - context 'JSON.podspec.json' do - before do - file_name = 'JSON.podspec.json' + context 'visiting with a line number anchor' do + # We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled + # This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351558 - create_file(file_name, ' - { - "name": "JSON" - } - ') - visit_blob(file_name) + before do + visit_blob('files/markdown/ruby-style-guide.md', anchor: 'L1') end - it 'displays an auxiliary viewer' do + it 'displays the blob using the simple viewer' do aggregate_failures do - expect(page).to have_content("This project manages its dependencies using CocoaPods.") + # hides the rich viewer + expect(page).to have_selector('.blob-viewer[data-type="simple"]') + expect(page).not_to have_selector('.blob-viewer[data-type="rich"]') + + # highlights the line in question + expect(page).to have_selector('#LC1.hll') + + # shows highlighted Markdown code + expect(page).to have_css(".js-syntax-highlight") + expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)") + + # shows an enabled copy button + expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') end end end - context 'requirements.txt' do - before do - file_name = 'requirements.txt' + context 'binary file that appears to be text in the first 1024 bytes' do + # We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled + # This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351559 - create_file(file_name, 'Project requirements') - visit_blob(file_name) + before do + visit_blob('encoding/binary-1.bin', ref: 'binary-encoding') end - - it 'displays an auxiliary viewer' do + it 'displays the blob' do aggregate_failures do - expect(page).to have_content("This project manages its dependencies using pip.") + # shows a download link + expect(page).to have_link('Download (23.8 KB)') + # does not show a viewer switcher + expect(page).not_to have_selector('.js-blob-viewer-switcher') + # The specs below verify an arguably incorrect result, but since we only + # learn that the file is not actually text once the text viewer content + # is loaded asynchronously, there is no straightforward way to get these + # synchronously loaded elements to display correctly. + # + # Clicking the copy button will result in nothing being copied. + # Clicking the raw button will result in the binary file being downloaded, + # as expected. + # shows an enabled copy button, incorrectly + expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') + # shows a raw button, incorrectly + expect(page).to have_link('Open raw') end end end - context 'yarn.lock' do - before do - file_name = 'yarn.lock' + context 'when static objects external storage is enabled' do + # We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled + # This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351555 - create_file(file_name, ' - # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. - # yarn lockfile v1 - ') - visit_blob(file_name) + before do + stub_application_setting(static_objects_external_storage_url: 'https://cdn.gitlab.com') end - it 'displays an auxiliary viewer' do - aggregate_failures do - expect(page).to have_content("This project manages its dependencies using Yarn.") + context 'private project' do + let_it_be(:project) { create(:project, :repository, :private) } + let_it_be(:user) { create(:user) } + + before do + project.add_developer(user) + + sign_in(user) + visit_blob('README.md') + end + + it 'shows open raw and download buttons with external storage URL prepended and user token appended to their href' do + path = project_raw_path(project, 'master/README.md') + raw_uri = "https://cdn.gitlab.com#{path}?token=#{user.static_object_token}" + download_uri = "https://cdn.gitlab.com#{path}?inline=false&token=#{user.static_object_token}" + + aggregate_failures do + expect(page).to have_link 'Open raw', href: raw_uri + expect(page).to have_link 'Download', href: download_uri + end end end end - context 'when refactor_blob_viewer is disabled' do - before do - stub_feature_flags(refactor_blob_viewer: false) - end + context 'files with auxiliary viewers' do + # This context is the same as the other 'files with auxiliary viewers' in this file, we just ensure that the auxiliary viewers still work this the refactor_blob_viewer disabled + # It should be safe to remove once we rollout the refactored blob viewer describe '.gitlab-ci.yml' do before do @@ -1554,104 +1657,4 @@ RSpec.describe 'File blob', :js do end end end - - context 'realtime pipelines' do - before do - Files::CreateService.new( - project, - project.creator, - start_branch: 'feature', - branch_name: 'feature', - commit_message: "Add ruby file", - file_path: 'files/ruby/test.rb', - file_content: "# Awesome content" - ).execute - - create(:ci_pipeline, status: 'running', project: project, ref: 'feature', sha: project.commit('feature').sha) - visit_blob('files/ruby/test.rb', ref: 'feature') - end - - it 'shows the realtime pipeline status' do - page.within('.commit-actions') do - expect(page).to have_css('.ci-status-icon') - expect(page).to have_css('.ci-status-icon-running') - expect(page).to have_css('.js-ci-status-icon-running') - end - end - end - - context 'for subgroups' do - let(:group) { create(:group) } - let(:subgroup) { create(:group, parent: group) } - let(:project) { create(:project, :public, :repository, group: subgroup) } - - it 'renders tree table without errors' do - visit_blob('README.md') - - expect(page).to have_selector('.file-content') - expect(page).not_to have_selector('.flash-alert') - end - - it 'displays a GPG badge' do - visit_blob('CONTRIBUTING.md', ref: '33f3729a45c02fc67d00adb1b8bca394b0e761d9') - - expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge' - expect(page).to have_selector '.gpg-status-box.invalid' - end - end - - context 'on signed merge commit' do - it 'displays a GPG badge' do - visit_blob('conflicting-file.md', ref: '6101e87e575de14b38b4e1ce180519a813671e10') - - expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge' - expect(page).to have_selector '.gpg-status-box.invalid' - end - end - - context 'when static objects external storage is enabled' do - before do - stub_application_setting(static_objects_external_storage_url: 'https://cdn.gitlab.com') - end - - context 'private project' do - let_it_be(:project) { create(:project, :repository, :private) } - let_it_be(:user) { create(:user) } - - before do - project.add_developer(user) - - sign_in(user) - visit_blob('README.md') - end - - it 'shows open raw and download buttons with external storage URL prepended and user token appended to their href' do - path = project_raw_path(project, 'master/README.md') - raw_uri = "https://cdn.gitlab.com#{path}?token=#{user.static_object_token}" - download_uri = "https://cdn.gitlab.com#{path}?inline=false&token=#{user.static_object_token}" - - aggregate_failures do - expect(page).to have_link 'Open raw', href: raw_uri - expect(page).to have_link 'Download', href: download_uri - end - end - end - - context 'public project' do - before do - visit_blob('README.md') - end - - it 'shows open raw and download buttons with external storage URL prepended to their href' do - path = project_raw_path(project, 'master/README.md') - raw_uri = "https://cdn.gitlab.com#{path}" - download_uri = "https://cdn.gitlab.com#{path}?inline=false" - - aggregate_failures do - expect(page).to have_link 'Open raw', href: raw_uri - expect(page).to have_link 'Download', href: download_uri - end - end - end - end end diff --git a/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb b/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb index 1c79b2ddc38..a2db5e11c7c 100644 --- a/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb +++ b/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'User follows pipeline suggest nudge spec when feature is enabled include CookieHelper let(:project) { create(:project, :empty_repo) } - let(:user) { project.owner } + let(:user) { project.first_owner } describe 'viewing the new blob page' do before do diff --git a/spec/features/projects/branches/user_views_branches_spec.rb b/spec/features/projects/branches/user_views_branches_spec.rb index d0c0a0860d9..b6b6dcb5cf1 100644 --- a/spec/features/projects/branches/user_views_branches_spec.rb +++ b/spec/features/projects/branches/user_views_branches_spec.rb @@ -4,7 +4,7 @@ require "spec_helper" RSpec.describe "User views branches", :js do let_it_be(:project) { create(:project, :repository) } - let_it_be(:user) { project.owner } + let_it_be(:user) { project.first_owner } before do sign_in(user) diff --git a/spec/features/projects/ci/editor_spec.rb b/spec/features/projects/ci/editor_spec.rb index 16cfa9f5f84..daf5ac61d73 100644 --- a/spec/features/projects/ci/editor_spec.rb +++ b/spec/features/projects/ci/editor_spec.rb @@ -26,7 +26,7 @@ RSpec.describe 'Pipeline Editor', :js do expect(page).to have_content('Pipeline Editor') end - context 'branch switcher' do + describe 'Branch switcher' do def switch_to_branch(branch) find('[data-testid="branch-selector"]').click @@ -64,7 +64,64 @@ RSpec.describe 'Pipeline Editor', :js do end end - context 'Editor content' do + describe 'Editor navigation' do + context 'when no change is made' do + it 'user can navigate away without a browser alert' do + expect(page).to have_content('Pipeline Editor') + + click_link 'Pipelines' + + expect(page).not_to have_content('Pipeline Editor') + end + end + + context 'when a change is made' do + before do + click_button 'Collapse' + + page.within('#source-editor-') do + find('textarea').send_keys '123' + # It takes some time after sending keys for the vue + # component to update + sleep 1 + end + end + + it 'user who tries to navigate away can cancel the action and keep their changes' do + click_link 'Pipelines' + + page.driver.browser.switch_to.alert.dismiss + + expect(page).to have_content('Pipeline Editor') + + page.within('#source-editor-') do + expect(page).to have_content('Default Content123') + end + end + + it 'user who tries to navigate away can confirm the action and discard their change' do + click_link 'Pipelines' + + page.driver.browser.switch_to.alert.accept + + expect(page).not_to have_content('Pipeline Editor') + end + + it 'user who creates a MR is taken to the merge request page without warnings' do + expect(page).not_to have_content('New merge request') + + find_field('Target Branch').set 'new_branch' + find_field('Start a new merge request with these changes').click + + click_button 'Commit changes' + + expect(page).not_to have_content('Pipeline Editor') + expect(page).to have_content('New merge request') + end + end + end + + describe 'Editor content' do it 'user can reset their CI configuration' do click_button 'Collapse' diff --git a/spec/features/projects/cluster_agents_spec.rb b/spec/features/projects/cluster_agents_spec.rb index 4018ef2abc9..d2b07bbc1de 100644 --- a/spec/features/projects/cluster_agents_spec.rb +++ b/spec/features/projects/cluster_agents_spec.rb @@ -10,6 +10,11 @@ RSpec.describe 'ClusterAgents', :js do let(:user) { project.creator } before do + allow(Gitlab::Kas).to receive(:enabled?).and_return(true) + allow_next_instance_of(Gitlab::Kas::Client) do |client| + allow(client).to receive(:get_connected_agents).and_return([]) + end + gitlab_sign_in(user) end @@ -22,7 +27,7 @@ RSpec.describe 'ClusterAgents', :js do end it 'displays empty state', :aggregate_failures do - expect(page).to have_content('Install a new agent') + expect(page).to have_content('Install new Agent') expect(page).to have_selector('.empty-state') end end diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb index 6e45529c659..b0406e1f3c4 100644 --- a/spec/features/projects/clusters_spec.rb +++ b/spec/features/projects/clusters_spec.rb @@ -99,7 +99,8 @@ RSpec.describe 'Clusters', :js do allow_any_instance_of(GoogleApi::CloudPlatform::Client) .to receive(:projects_zones_clusters_create) do - OpenStruct.new( + double( + 'cluster_control', self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123', status: 'RUNNING' ) diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb index d88ff5c1aa5..bfd54b9c6da 100644 --- a/spec/features/projects/environments/environment_spec.rb +++ b/spec/features/projects/environments/environment_spec.rb @@ -132,6 +132,29 @@ RSpec.describe 'Environment' do end end + context 'with upcoming deployments' do + let(:pipeline) { create(:ci_pipeline, project: project) } + let(:build) { create(:ci_build, pipeline: pipeline) } + + let!(:runnind_deployment_1) { create(:deployment, environment: environment, deployable: build, status: :running) } + let!(:runnind_deployment_2) { create(:deployment, environment: environment, deployable: build, status: :running) } + # Success deployments must have present `finished_at`. We'll backfill in the future. + # See https://gitlab.com/gitlab-org/gitlab/-/issues/350618 for more information. + let!(:success_without_finished_at) { create(:deployment, environment: environment, deployable: build, status: :success, finished_at: nil) } + + before do + visit_environment(environment) + end + + # This ordering is unexpected and to be fixed. + # See https://gitlab.com/gitlab-org/gitlab/-/issues/350618 for more information. + it 'shows upcoming deployments in unordered way' do + displayed_ids = find_all('[data-testid="deployment-id"]').map { |e| e.text } + internal_ids = [runnind_deployment_1, runnind_deployment_2, success_without_finished_at].map { |d| "##{d.iid}" } + expect(displayed_ids).to match_array(internal_ids) + end + end + context 'with related deployable present' do let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, pipeline: pipeline) } diff --git a/spec/features/projects/environments_pod_logs_spec.rb b/spec/features/projects/environments_pod_logs_spec.rb index 7d31de2b418..531eae1d638 100644 --- a/spec/features/projects/environments_pod_logs_spec.rb +++ b/spec/features/projects/environments_pod_logs_spec.rb @@ -21,7 +21,7 @@ RSpec.describe 'Environment > Pod Logs', :js, :kubeclient do stub_kubeclient_ingresses(environment.deployment_namespace) stub_kubeclient_nodes_and_nodes_metrics(cluster.platform.api_url) - sign_in(project.owner) + sign_in(project.first_owner) end it "shows environments in dropdown" do diff --git a/spec/features/projects/files/dockerfile_dropdown_spec.rb b/spec/features/projects/files/dockerfile_dropdown_spec.rb index 11663158b33..3a0cc61d9c6 100644 --- a/spec/features/projects/files/dockerfile_dropdown_spec.rb +++ b/spec/features/projects/files/dockerfile_dropdown_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'Projects > Files > User wants to add a Dockerfile file', :js do before do project = create(:project, :repository) - sign_in project.owner + sign_in project.first_owner visit project_new_blob_path(project, 'master', file_name: 'Dockerfile') end diff --git a/spec/features/projects/files/edit_file_soft_wrap_spec.rb b/spec/features/projects/files/edit_file_soft_wrap_spec.rb index fda024e893d..e08c53a67dd 100644 --- a/spec/features/projects/files/edit_file_soft_wrap_spec.rb +++ b/spec/features/projects/files/edit_file_soft_wrap_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe 'Projects > Files > User uses soft wrap while editing file', :js do before do project = create(:project, :repository) - user = project.owner + user = project.first_owner sign_in user visit project_new_blob_path(project, 'master', file_name: 'test_file-name') diff --git a/spec/features/projects/files/editing_a_file_spec.rb b/spec/features/projects/files/editing_a_file_spec.rb index 819864b3def..e256bec2a1c 100644 --- a/spec/features/projects/files/editing_a_file_spec.rb +++ b/spec/features/projects/files/editing_a_file_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe 'Projects > Files > User wants to edit a file' do let(:project) { create(:project, :repository) } - let(:user) { project.owner } + let(:user) { project.first_owner } let(:commit_params) do { start_branch: project.default_branch, diff --git a/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb b/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb index 94190889ace..a283f7d128c 100644 --- a/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb +++ b/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe 'Projects > Files > User views files page' do let(:project) { create(:forked_project_with_submodules) } - let(:user) { project.owner } + let(:user) { project.first_owner } before do sign_in user diff --git a/spec/features/projects/files/find_file_keyboard_spec.rb b/spec/features/projects/files/find_file_keyboard_spec.rb index 4293183fd9a..9ae3be4993b 100644 --- a/spec/features/projects/files/find_file_keyboard_spec.rb +++ b/spec/features/projects/files/find_file_keyboard_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe 'Projects > Files > Find file keyboard shortcuts', :js do let(:project) { create(:project, :repository) } - let(:user) { project.owner } + let(:user) { project.first_owner } before do sign_in user diff --git a/spec/features/projects/files/gitignore_dropdown_spec.rb b/spec/features/projects/files/gitignore_dropdown_spec.rb index d47eaee2e79..4a92216f46c 100644 --- a/spec/features/projects/files/gitignore_dropdown_spec.rb +++ b/spec/features/projects/files/gitignore_dropdown_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitignore file', :js do before do project = create(:project, :repository) - sign_in project.owner + sign_in project.first_owner visit project_new_blob_path(project, 'master', file_name: '.gitignore') end diff --git a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb index fc199f66490..cdf6c219ea5 100644 --- a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb +++ b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb @@ -11,7 +11,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js let_it_be(:project) { create(:project, :repository) } before do - sign_in project.owner + sign_in project.first_owner visit project_new_blob_path(project, 'master', file_name: filename, **params) end diff --git a/spec/features/projects/files/project_owner_creates_license_file_spec.rb b/spec/features/projects/files/project_owner_creates_license_file_spec.rb index ab62e8aabc0..4a0b1f4c548 100644 --- a/spec/features/projects/files/project_owner_creates_license_file_spec.rb +++ b/spec/features/projects/files/project_owner_creates_license_file_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe 'Projects > Files > Project owner creates a license file', :js do let(:project) { create(:project, :repository) } - let(:project_maintainer) { project.owner } + let(:project_maintainer) { project.first_owner } before do project.repository.delete_file(project_maintainer, 'LICENSE', diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb index 37583870cfd..ca384291c12 100644 --- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb +++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'Projects > Files > Project owner sees a link to create a license include WebIdeSpecHelpers let(:project) { create(:project_empty_repo) } - let(:project_maintainer) { project.owner } + let(:project_maintainer) { project.first_owner } before do sign_in(project_maintainer) diff --git a/spec/features/projects/files/template_type_dropdown_spec.rb b/spec/features/projects/files/template_type_dropdown_spec.rb index ca9ce841a92..9cdb5eeb076 100644 --- a/spec/features/projects/files/template_type_dropdown_spec.rb +++ b/spec/features/projects/files/template_type_dropdown_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe 'Projects > Files > Template type dropdown selector', :js do let(:project) { create(:project, :repository) } - let(:user) { project.owner } + let(:user) { project.first_owner } before do sign_in user diff --git a/spec/features/projects/files/undo_template_spec.rb b/spec/features/projects/files/undo_template_spec.rb index 560cb53ead2..0b2daf12063 100644 --- a/spec/features/projects/files/undo_template_spec.rb +++ b/spec/features/projects/files/undo_template_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe 'Projects > Files > Template Undo Button', :js do let(:project) { create(:project, :repository) } - let(:user) { project.owner } + let(:user) { project.first_owner } before do sign_in user diff --git a/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb b/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb index 4d9da783f98..220572c6a6d 100644 --- a/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb +++ b/spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' # This is a regression test for https://gitlab.com/gitlab-org/gitlab-foss/issues/37569 RSpec.describe 'Projects > Files > User browses a tree with a folder containing only a folder', :js do let(:project) { create(:project, :empty_repo) } - let(:user) { project.owner } + let(:user) { project.first_owner } before do project.repository.create_dir(user, 'foo/bar', branch_name: 'master', message: 'Add the foo/bar folder') diff --git a/spec/features/projects/files/user_browses_files_spec.rb b/spec/features/projects/files/user_browses_files_spec.rb index 508dec70db6..9b4d1502bc8 100644 --- a/spec/features/projects/files/user_browses_files_spec.rb +++ b/spec/features/projects/files/user_browses_files_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" -RSpec.describe "User browses files" do +RSpec.describe "User browses files", :js do include RepoHelpers let(:fork_message) do @@ -13,7 +13,7 @@ RSpec.describe "User browses files" do let(:project) { create(:project, :repository, name: "Shop") } let(:project2) { create(:project, :repository, name: "Another Project", path: "another-project") } let(:tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } - let(:user) { project.owner } + let(:user) { project.first_owner } before do sign_in(user) @@ -340,32 +340,37 @@ RSpec.describe "User browses files" do let(:newrev) { project.repository.commit('master').sha } before do - stub_feature_flags(refactor_blob_viewer: false) # This stub will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/350456 create_file_in_repo(project, 'master', 'master', filename, 'Test file') path = File.join('master', filename) visit(project_blob_path(project, path)) + wait_for_requests end - it "shows a raw file content" do - click_link("Open raw") + it "shows raw file content in a new tab" do + new_tab = window_opened_by {click_link 'Open raw'} - expect(source).to eq("") # Body is filled in by gitlab-workhorse + within_window new_tab do + expect(page).to have_content("Test file") + end end end context "when browsing a raw file" do before do - stub_feature_flags(refactor_blob_viewer: false) # This stub will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/350456 - path = File.join(RepoHelpers.sample_commit.id, RepoHelpers.sample_blob.path) + visit(tree_path_root_ref) + wait_for_requests - visit(project_blob_path(project, path)) + click_link(".gitignore") + wait_for_requests end - it "shows a raw file content" do - click_link("Open raw") + it "shows raw file content in a new tab" do + new_tab = window_opened_by {click_link 'Open raw'} - expect(source).to eq("") # Body is filled in by gitlab-workhorse + within_window new_tab do + expect(page).to have_content("*.rbc") + end end end end diff --git a/spec/features/projects/files/user_browses_lfs_files_spec.rb b/spec/features/projects/files/user_browses_lfs_files_spec.rb index 17699847704..3976df849fa 100644 --- a/spec/features/projects/files/user_browses_lfs_files_spec.rb +++ b/spec/features/projects/files/user_browses_lfs_files_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe 'Projects > Files > User browses LFS files' do let(:project) { create(:project, :repository) } - let(:user) { project.owner } + let(:user) { project.first_owner } before do sign_in(user) diff --git a/spec/features/projects/files/user_searches_for_files_spec.rb b/spec/features/projects/files/user_searches_for_files_spec.rb index 7fd7dfff279..cce73d06f94 100644 --- a/spec/features/projects/files/user_searches_for_files_spec.rb +++ b/spec/features/projects/files/user_searches_for_files_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe 'Projects > Files > User searches for files' do - let(:user) { project.owner } + let(:user) { project.first_owner } before do sign_in(user) diff --git a/spec/features/projects/gfm_autocomplete_load_spec.rb b/spec/features/projects/gfm_autocomplete_load_spec.rb index f4cd65bcba1..a7d68b07dd3 100644 --- a/spec/features/projects/gfm_autocomplete_load_spec.rb +++ b/spec/features/projects/gfm_autocomplete_load_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'GFM autocomplete loading', :js do let(:project) { create(:project) } before do - sign_in(project.owner) + sign_in(project.first_owner) visit project_path(project) end diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index 2fbec4e22f4..1e5c5d33ad9 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -41,7 +41,7 @@ RSpec.describe 'Import/Export - project import integration test', :js do project = Project.last expect(project).not_to be_nil - expect(page).to have_content("Project 'test-project-path' is being imported") + expect(page).to have_content("Project 'Test Project Name' is being imported") end it 'invalid project' do diff --git a/spec/features/projects/services/disable_triggers_spec.rb b/spec/features/projects/integrations/disable_triggers_spec.rb index c6413685f38..b039d610ecb 100644 --- a/spec/features/projects/services/disable_triggers_spec.rb +++ b/spec/features/projects/integrations/disable_triggers_spec.rb @@ -3,16 +3,16 @@ require 'spec_helper' RSpec.describe 'Disable individual triggers', :js do - include_context 'project service activation' + include_context 'project integration activation' let(:checkbox_selector) { 'input[name$="_events]"]' } before do - visit_project_integration(service_name) + visit_project_integration(integration_name) end - context 'service has multiple supported events' do - let(:service_name) { 'Jenkins' } + context 'integration has multiple supported events' do + let(:integration_name) { 'Jenkins' } it 'shows trigger checkboxes' do event_count = Integrations::Jenkins.supported_events.count @@ -22,8 +22,8 @@ RSpec.describe 'Disable individual triggers', :js do end end - context 'services only has one supported event' do - let(:service_name) { 'Asana' } + context 'integrations only has one supported event' do + let(:integration_name) { 'Asana' } it "doesn't show unnecessary Trigger checkboxes" do expect(page).not_to have_content "Trigger" diff --git a/spec/features/projects/integrations/project_integrations_spec.rb b/spec/features/projects/integrations/project_integrations_spec.rb new file mode 100644 index 00000000000..708a5bca8c1 --- /dev/null +++ b/spec/features/projects/integrations/project_integrations_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Project integrations', :js do + include_context 'project integration activation' + + it_behaves_like 'integration settings form' do + let(:integrations) { project.find_or_initialize_integrations } + + def navigate_to_integration(integration) + visit_project_integration(integration.title) + end + end +end diff --git a/spec/features/projects/services/prometheus_external_alerts_spec.rb b/spec/features/projects/integrations/prometheus_external_alerts_spec.rb index c2ae72ddb5e..7e56ca13e23 100644 --- a/spec/features/projects/services/prometheus_external_alerts_spec.rb +++ b/spec/features/projects/integrations/prometheus_external_alerts_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe 'Prometheus external alerts', :js do - include_context 'project service activation' + include_context 'project integration activation' let(:alerts_section_selector) { '.js-prometheus-alerts' } let(:alerts_section) { page.find(alerts_section_selector) } diff --git a/spec/features/projects/integrations/user_activates_asana_spec.rb b/spec/features/projects/integrations/user_activates_asana_spec.rb index cf2290383e8..9ec9f00529a 100644 --- a/spec/features/projects/integrations/user_activates_asana_spec.rb +++ b/spec/features/projects/integrations/user_activates_asana_spec.rb @@ -3,9 +3,9 @@ require 'spec_helper' RSpec.describe 'User activates Asana' do - include_context 'project service activation' + include_context 'project integration activation' - it 'activates service', :js do + it 'activates integration', :js do visit_project_integration('Asana') fill_in('API key', with: 'verySecret') fill_in('Restrict to branch', with: 'verySecret') diff --git a/spec/features/projects/integrations/user_activates_assembla_spec.rb b/spec/features/projects/integrations/user_activates_assembla_spec.rb index 63cc424a641..be9034ec5ba 100644 --- a/spec/features/projects/integrations/user_activates_assembla_spec.rb +++ b/spec/features/projects/integrations/user_activates_assembla_spec.rb @@ -3,13 +3,13 @@ require 'spec_helper' RSpec.describe 'User activates Assembla' do - include_context 'project service activation' + include_context 'project integration activation' before do stub_request(:post, /.*atlas.assembla.com.*/) end - it 'activates service', :js do + it 'activates integration', :js do visit_project_integration('Assembla') fill_in('Token', with: 'verySecret') diff --git a/spec/features/projects/integrations/user_activates_atlassian_bamboo_ci_spec.rb b/spec/features/projects/integrations/user_activates_atlassian_bamboo_ci_spec.rb index 91db375be3a..49f62a34bd2 100644 --- a/spec/features/projects/integrations/user_activates_atlassian_bamboo_ci_spec.rb +++ b/spec/features/projects/integrations/user_activates_atlassian_bamboo_ci_spec.rb @@ -3,13 +3,13 @@ require 'spec_helper' RSpec.describe 'User activates Atlassian Bamboo CI' do - include_context 'project service activation' + include_context 'project integration activation' before do stub_request(:get, /.*bamboo.example.com.*/) end - it 'activates service', :js do + it 'activates integration', :js do visit_project_integration('Atlassian Bamboo') fill_in('Bamboo URL', with: 'http://bamboo.example.com') fill_in('Build key', with: 'KEY') diff --git a/spec/features/projects/services/user_activates_emails_on_push_spec.rb b/spec/features/projects/integrations/user_activates_emails_on_push_spec.rb index 5a075fc61e8..168779aad07 100644 --- a/spec/features/projects/services/user_activates_emails_on_push_spec.rb +++ b/spec/features/projects/integrations/user_activates_emails_on_push_spec.rb @@ -3,9 +3,9 @@ require 'spec_helper' RSpec.describe 'User activates Emails on push' do - include_context 'project service activation' + include_context 'project integration activation' - it 'activates service', :js do + it 'activates integration', :js do visit_project_integration('Emails on push') fill_in('Recipients', with: 'qa@company.name') diff --git a/spec/features/projects/integrations/user_activates_flowdock_spec.rb b/spec/features/projects/integrations/user_activates_flowdock_spec.rb index 4a4d7bbecfd..df1a4feddfb 100644 --- a/spec/features/projects/integrations/user_activates_flowdock_spec.rb +++ b/spec/features/projects/integrations/user_activates_flowdock_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe 'User activates Flowdock' do - include_context 'project service activation' do + include_context 'project integration activation' do let(:project) { create(:project, :repository) } end @@ -11,7 +11,7 @@ RSpec.describe 'User activates Flowdock' do stub_request(:post, /.*api.flowdock.com.*/) end - it 'activates service', :js do + it 'activates integration', :js do visit_project_integration('Flowdock') fill_in('Token', with: 'verySecret') diff --git a/spec/features/projects/services/user_activates_irker_spec.rb b/spec/features/projects/integrations/user_activates_irker_spec.rb index 004aa116bb3..23b5f2a5c47 100644 --- a/spec/features/projects/services/user_activates_irker_spec.rb +++ b/spec/features/projects/integrations/user_activates_irker_spec.rb @@ -3,9 +3,9 @@ require 'spec_helper' RSpec.describe 'User activates irker (IRC gateway)' do - include_context 'project service activation' + include_context 'project integration activation' - it 'activates service', :js do + it 'activates integration', :js do visit_project_integration('irker (IRC gateway)') check('Colorize messages') fill_in('Recipients', with: 'irc://chat.freenode.net/#commits') diff --git a/spec/features/projects/services/user_activates_issue_tracker_spec.rb b/spec/features/projects/integrations/user_activates_issue_tracker_spec.rb index 27c23e7beb5..b9c2c539899 100644 --- a/spec/features/projects/services/user_activates_issue_tracker_spec.rb +++ b/spec/features/projects/integrations/user_activates_issue_tracker_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe 'User activates issue tracker', :js do - include_context 'project service activation' + include_context 'project integration activation' let(:url) { 'http://tracker.example.com' } @@ -17,7 +17,7 @@ RSpec.describe 'User activates issue tracker', :js do end shared_examples 'external issue tracker activation' do |tracker:, skip_new_issue_url: false, skip_test: false| - describe 'user sets and activates the Service' do + describe 'user sets and activates the integration' do context 'when the connection test succeeds' do before do stub_request(:head, url).to_return(headers: { 'Content-Type' => 'application/json' }) @@ -32,7 +32,7 @@ RSpec.describe 'User activates issue tracker', :js do end end - it 'activates the service' do + it 'activates the integration' do expect(page).to have_content("#{tracker} settings saved and active.") expect(current_path).to eq(edit_project_integration_path(project, tracker.parameterize(separator: '_'))) end @@ -45,7 +45,7 @@ RSpec.describe 'User activates issue tracker', :js do end context 'when the connection test fails' do - it 'activates the service' do + it 'activates the integration' do stub_request(:head, url).to_raise(Gitlab::HTTP::Error) visit_project_integration(tracker) @@ -63,7 +63,7 @@ RSpec.describe 'User activates issue tracker', :js do end end - describe 'user disables the service' do + describe 'user disables the integration' do before do visit_project_integration(tracker) fill_form(disable: true, skip_new_issue_url: skip_new_issue_url) @@ -71,7 +71,7 @@ RSpec.describe 'User activates issue tracker', :js do click_button('Save changes') end - it 'saves but does not activate the service' do + it 'saves but does not activate the integration' do expect(page).to have_content("#{tracker} settings saved, but not active.") expect(current_path).to eq(edit_project_integration_path(project, tracker.parameterize(separator: '_'))) end diff --git a/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb b/spec/features/projects/integrations/user_activates_jetbrains_teamcity_ci_spec.rb index 17bfe8fc1e2..e6f2e462b8c 100644 --- a/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb +++ b/spec/features/projects/integrations/user_activates_jetbrains_teamcity_ci_spec.rb @@ -3,13 +3,13 @@ require 'spec_helper' RSpec.describe 'User activates JetBrains TeamCity CI' do - include_context 'project service activation' + include_context 'project integration activation' before do stub_request(:post, /.*teamcity.example.com.*/) end - it 'activates service', :js do + it 'activates integration', :js do visit_project_integration('JetBrains TeamCity') check('Push') check('Merge Request') diff --git a/spec/features/projects/integrations/user_activates_jira_spec.rb b/spec/features/projects/integrations/user_activates_jira_spec.rb index 50010950f0e..7562dc00092 100644 --- a/spec/features/projects/integrations/user_activates_jira_spec.rb +++ b/spec/features/projects/integrations/user_activates_jira_spec.rb @@ -3,14 +3,14 @@ require 'spec_helper' RSpec.describe 'User activates Jira', :js do - include_context 'project service activation' - include_context 'project service Jira context' + include_context 'project integration activation' + include_context 'project integration Jira context' before do stub_request(:get, test_url).to_return(body: { key: 'value' }.to_json) end - describe 'user tests Jira Service' do + describe 'user tests Jira integration' do context 'when Jira connection test succeeds' do before do visit_project_integration('Jira') @@ -18,7 +18,7 @@ RSpec.describe 'User activates Jira', :js do click_test_then_save_integration(expect_test_to_fail: false) end - it 'activates the Jira service' do + it 'activates the Jira integration' do expect(page).to have_content('Jira settings saved and active.') expect(current_path).to eq(edit_project_integration_path(project, :jira)) end @@ -46,7 +46,7 @@ RSpec.describe 'User activates Jira', :js do end end - it 'activates the Jira service' do + it 'activates the Jira integration' do stub_request(:get, test_url).with(basic_auth: %w(username password)) .to_raise(JIRA::HTTPError.new(double(message: 'message'))) @@ -60,7 +60,7 @@ RSpec.describe 'User activates Jira', :js do end end - describe 'user disables the Jira Service' do + describe 'user disables the Jira integration' do include JiraServiceHelper before do @@ -70,7 +70,7 @@ RSpec.describe 'User activates Jira', :js do click_save_integration end - it 'saves but does not activate the Jira service' do + it 'saves but does not activate the Jira integration' do expect(page).to have_content('Jira settings saved, but not active.') expect(current_path).to eq(edit_project_integration_path(project, :jira)) end diff --git a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb b/spec/features/projects/integrations/user_activates_mattermost_slash_command_spec.rb index 74919a99f04..ed0877ab0e9 100644 --- a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb +++ b/spec/features/projects/integrations/user_activates_mattermost_slash_command_spec.rb @@ -4,14 +4,14 @@ require 'spec_helper' RSpec.describe 'Set up Mattermost slash commands', :js do describe 'user visits the mattermost slash command config page' do - include_context 'project service activation' + include_context 'project integration activation' before do stub_mattermost_setting(enabled: mattermost_enabled) visit_project_integration('Mattermost slash commands') end - context 'mattermost service is enabled' do + context 'mattermost integration is enabled' do let(:mattermost_enabled) { true } describe 'activation' do @@ -84,7 +84,9 @@ RSpec.describe 'Set up Mattermost slash commands', :js do end it 'shows an error alert with the error message if there is an error requesting teams' do - allow_any_instance_of(Integrations::MattermostSlashCommands).to receive(:list_teams) { [[], 'test mattermost error message'] } + allow_next_instance_of(Integrations::MattermostSlashCommands) do |integration| + allow(integration).to receive(:list_teams).and_return([[], 'test mattermost error message']) + end click_link 'Add to Mattermost' @@ -113,7 +115,9 @@ RSpec.describe 'Set up Mattermost slash commands', :js do def stub_teams(count: 0) teams = create_teams(count) - allow_any_instance_of(Integrations::MattermostSlashCommands).to receive(:list_teams) { [teams, nil] } + allow_next_instance_of(Integrations::MattermostSlashCommands) do |integration| + allow(integration).to receive(:list_teams).and_return([teams, nil]) + end teams end @@ -129,7 +133,7 @@ RSpec.describe 'Set up Mattermost slash commands', :js do end end - context 'mattermost service is not enabled' do + context 'mattermost integration is not enabled' do let(:mattermost_enabled) { false } it 'shows the correct trigger url' do diff --git a/spec/features/projects/services/user_activates_packagist_spec.rb b/spec/features/projects/integrations/user_activates_packagist_spec.rb index 87303cf8fb4..0892843e840 100644 --- a/spec/features/projects/services/user_activates_packagist_spec.rb +++ b/spec/features/projects/integrations/user_activates_packagist_spec.rb @@ -3,13 +3,13 @@ require 'spec_helper' RSpec.describe 'User activates Packagist' do - include_context 'project service activation' + include_context 'project integration activation' before do stub_request(:post, /.*packagist.org.*/) end - it 'activates service', :js do + it 'activates integration', :js do visit_project_integration('Packagist') fill_in('Username', with: 'theUser') fill_in('Token', with: 'verySecret') diff --git a/spec/features/projects/integrations/user_activates_pivotaltracker_spec.rb b/spec/features/projects/integrations/user_activates_pivotaltracker_spec.rb index ea34a766719..fe6ed786ace 100644 --- a/spec/features/projects/integrations/user_activates_pivotaltracker_spec.rb +++ b/spec/features/projects/integrations/user_activates_pivotaltracker_spec.rb @@ -3,13 +3,13 @@ require 'spec_helper' RSpec.describe 'User activates PivotalTracker' do - include_context 'project service activation' + include_context 'project integration activation' before do stub_request(:post, /.*www.pivotaltracker.com.*/) end - it 'activates service', :js do + it 'activates integration', :js do visit_project_integration('Pivotal Tracker') fill_in('Token', with: 'verySecret') diff --git a/spec/features/projects/services/user_activates_prometheus_spec.rb b/spec/features/projects/integrations/user_activates_prometheus_spec.rb index 73ad8088be2..80629af6fce 100644 --- a/spec/features/projects/services/user_activates_prometheus_spec.rb +++ b/spec/features/projects/integrations/user_activates_prometheus_spec.rb @@ -3,13 +3,13 @@ require 'spec_helper' RSpec.describe 'User activates Prometheus' do - include_context 'project service activation' + include_context 'project integration activation' before do stub_request(:get, /.*prometheus.example.com.*/) end - it 'does not activate service and informs about deprecation', :js do + it 'does not activate integration and informs about deprecation', :js do visit_project_integration('Prometheus') check('Active') fill_in('API URL', with: 'http://prometheus.example.com') diff --git a/spec/features/projects/services/user_activates_pushover_spec.rb b/spec/features/projects/integrations/user_activates_pushover_spec.rb index d92f69e700a..616efdc836f 100644 --- a/spec/features/projects/services/user_activates_pushover_spec.rb +++ b/spec/features/projects/integrations/user_activates_pushover_spec.rb @@ -3,13 +3,13 @@ require 'spec_helper' RSpec.describe 'User activates Pushover' do - include_context 'project service activation' + include_context 'project integration activation' before do stub_request(:post, /.*api.pushover.net.*/) end - it 'activates service', :js do + it 'activates integration', :js do visit_project_integration('Pushover') fill_in('API key', with: 'verySecret') fill_in('User key', with: 'verySecret') diff --git a/spec/features/projects/services/user_activates_slack_notifications_spec.rb b/spec/features/projects/integrations/user_activates_slack_notifications_spec.rb index 38b6ad84c77..616469c5df8 100644 --- a/spec/features/projects/services/user_activates_slack_notifications_spec.rb +++ b/spec/features/projects/integrations/user_activates_slack_notifications_spec.rb @@ -3,14 +3,14 @@ require 'spec_helper' RSpec.describe 'User activates Slack notifications', :js do - include_context 'project service activation' + include_context 'project integration activation' - context 'when service is not configured yet' do + context 'when integration is not configured yet' do before do visit_project_integration('Slack notifications') end - it 'activates service' do + it 'activates integration' do fill_in('Webhook', with: 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685') click_test_then_save_integration @@ -19,7 +19,7 @@ RSpec.describe 'User activates Slack notifications', :js do end end - context 'when service is already configured' do + context 'when integration is already configured' do let(:integration) { Integrations::Slack.new } let(:project) { create(:project, slack_integration: integration) } diff --git a/spec/features/projects/services/user_activates_slack_slash_command_spec.rb b/spec/features/projects/integrations/user_activates_slack_slash_command_spec.rb index d46d1f739b7..7ec469070ea 100644 --- a/spec/features/projects/services/user_activates_slack_slash_command_spec.rb +++ b/spec/features/projects/integrations/user_activates_slack_slash_command_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe 'Slack slash commands', :js do - include_context 'project service activation' + include_context 'project integration activation' before do visit_project_integration('Slack slash commands') diff --git a/spec/features/projects/integrations/user_uses_inherited_settings_spec.rb b/spec/features/projects/integrations/user_uses_inherited_settings_spec.rb index d2c4418f0d6..fcb04c338a9 100644 --- a/spec/features/projects/integrations/user_uses_inherited_settings_spec.rb +++ b/spec/features/projects/integrations/user_uses_inherited_settings_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe 'User uses inherited settings', :js do include JiraServiceHelper - include_context 'project service activation' + include_context 'project integration activation' before do stub_jira_integration_test diff --git a/spec/features/projects/services/user_views_services_spec.rb b/spec/features/projects/integrations/user_views_services_spec.rb index 201a58ba379..559461f911f 100644 --- a/spec/features/projects/services/user_views_services_spec.rb +++ b/spec/features/projects/integrations/user_views_services_spec.rb @@ -2,10 +2,10 @@ require 'spec_helper' -RSpec.describe 'User views services', :js do - include_context 'project service activation' +RSpec.describe 'User views integrations', :js do + include_context 'project integration activation' - it 'shows the list of available services' do + it 'shows the list of available integrations' do visit_project_integrations expect(page).to have_content('Integrations') diff --git a/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb b/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb index 211576a93f3..762f9c33510 100644 --- a/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb +++ b/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'User uploads new design', :js do include DesignManagementTestHelpers let(:project) { create(:project_empty_repo, :public) } - let(:user) { project.owner } + let(:user) { project.first_owner } let(:issue) { create(:issue, project: project) } before do diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index 7ccd5c51493..a65d2d15c12 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -615,7 +615,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do end context 'when the user is not able to view the cluster' do - let(:user_access_level) { :developer } + let(:user_access_level) { :reporter } it 'includes only the name of the cluster without a link' do expect(page).to have_content 'using cluster the-cluster' diff --git a/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb b/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb index c8a9f959188..c9fee9bee7a 100644 --- a/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb +++ b/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb @@ -21,6 +21,6 @@ RSpec.describe 'Projects > Members > Group member cannot leave group project' do it 'renders a flash message if attempting to leave by url', :js do visit project_path(project, leave: 1) - expect(find('.flash-alert')).to have_content 'You do not have permission to leave this project' + expect(find('[data-testid="alert-danger"]')).to have_content 'You do not have permission to leave this project' end end diff --git a/spec/features/projects/members/invite_group_spec.rb b/spec/features/projects/members/invite_group_spec.rb index b674cad0312..066e0b0d20f 100644 --- a/spec/features/projects/members/invite_group_spec.rb +++ b/spec/features/projects/members/invite_group_spec.rb @@ -8,7 +8,7 @@ RSpec.describe 'Project > Members > Invite group', :js do include Spec::Support::Helpers::Features::MembersHelpers include Spec::Support::Helpers::Features::InviteMembersModalHelper - let(:maintainer) { create(:user) } + let_it_be(:maintainer) { create(:user) } using RSpec::Parameterized::TableSyntax @@ -190,17 +190,26 @@ RSpec.describe 'Project > Members > Invite group', :js do end describe 'the groups dropdown' do - context 'with multiple groups to choose from' do - let(:project) { create(:project) } + let_it_be(:parent_group) { create(:group, :public) } + let_it_be(:project_group) { create(:group, :public, parent: parent_group) } + let_it_be(:public_sub_subgroup) { create(:group, :public, parent: project_group) } + let_it_be(:public_sibbling_group) { create(:group, :public, parent: parent_group) } + let_it_be(:private_sibbling_group) { create(:group, :private, parent: parent_group) } + let_it_be(:private_membership_group) { create(:group, :private) } + let_it_be(:public_membership_group) { create(:group, :public) } + let_it_be(:project) { create(:project, group: project_group) } - it 'includes multiple groups' do - project.add_maintainer(maintainer) - sign_in(maintainer) + before do + private_membership_group.add_guest(maintainer) + public_membership_group.add_maintainer(maintainer) + + sign_in(maintainer) + end - group1 = create(:group) - group1.add_owner(maintainer) - group2 = create(:group) - group2.add_owner(maintainer) + context 'for a project in a nested group' do + it 'does not show the groups inherited from projects' do + project.add_maintainer(maintainer) + public_sibbling_group.add_maintainer(maintainer) visit project_project_members_path(project) @@ -208,37 +217,90 @@ RSpec.describe 'Project > Members > Invite group', :js do click_on 'Select a group' wait_for_requests - expect(page).to have_button(group1.name) - expect(page).to have_button(group2.name) - end - end - - context 'for a project in a nested group' do - let(:group) { create(:group) } - let!(:nested_group) { create(:group, parent: group) } - let!(:group_to_share_with) { create(:group) } - let!(:project) { create(:project, namespace: nested_group) } + page.within('[data-testid="group-select-dropdown"]') do + expect_to_have_group(public_membership_group) + expect_to_have_group(public_sibbling_group) + expect_to_have_group(private_membership_group) - before do - project.add_maintainer(maintainer) - sign_in(maintainer) - group.add_maintainer(maintainer) - group_to_share_with.add_maintainer(maintainer) + expect_not_to_have_group(public_sub_subgroup) + expect_not_to_have_group(private_sibbling_group) + expect_not_to_have_group(parent_group) + expect_not_to_have_group(project_group) + end end - # This behavior should be changed to exclude the ancestor and project - # group from the options once issue is fixed for the modal: - # https://gitlab.com/gitlab-org/gitlab/-/issues/329835 - it 'the groups dropdown does show ancestors and the project group' do + it 'does not show the ancestors or project group', :aggregate_failures do + parent_group.add_maintainer(maintainer) + visit project_project_members_path(project) click_on 'Invite a group' click_on 'Select a group' wait_for_requests - expect(page).to have_button(group_to_share_with.name) - expect(page).to have_button(group.name) - expect(page).to have_button(nested_group.name) + page.within('[data-testid="group-select-dropdown"]') do + expect_to_have_group(public_membership_group) + expect_to_have_group(public_sibbling_group) + expect_to_have_group(private_membership_group) + expect_to_have_group(public_sub_subgroup) + expect_to_have_group(private_sibbling_group) + + expect_not_to_have_group(parent_group) + expect_not_to_have_group(project_group) + end + end + + context 'when invite_members_group_modal feature disabled' do + let(:group_invite_dropdown) { find('#select2-results-2') } + + before do + stub_feature_flags(invite_members_group_modal: false) + end + + it 'does not show the groups inherited from projects', :aggregate_failures do + project.add_maintainer(maintainer) + public_sibbling_group.add_maintainer(maintainer) + + visit project_project_members_path(project) + + click_on 'Invite group' + click_on 'Search for a group' + wait_for_requests + + expect(group_invite_dropdown).to have_text(public_membership_group.full_path) + expect(group_invite_dropdown).to have_text(public_sibbling_group.full_path) + expect(group_invite_dropdown).to have_text(private_membership_group.full_path) + expect(group_invite_dropdown).not_to have_text(public_sub_subgroup.full_path) + expect(group_invite_dropdown).not_to have_text(private_sibbling_group.full_path) + expect(group_invite_dropdown).not_to have_text(parent_group.full_path, exact: true) + expect(group_invite_dropdown).not_to have_text(project_group.full_path, exact: true) + end + + it 'does not show the ancestors or project group', :aggregate_failures do + parent_group.add_maintainer(maintainer) + + visit project_project_members_path(project) + + click_on 'Invite group' + click_on 'Search for a group' + wait_for_requests + + expect(group_invite_dropdown).to have_text(public_membership_group.full_path) + expect(group_invite_dropdown).to have_text(public_sub_subgroup.full_path) + expect(group_invite_dropdown).to have_text(public_sibbling_group.full_path) + expect(group_invite_dropdown).to have_text(private_sibbling_group.full_path) + expect(group_invite_dropdown).to have_text(private_membership_group.full_path) + expect(group_invite_dropdown).not_to have_text(parent_group.full_path, exact: true) + expect(group_invite_dropdown).not_to have_text(project_group.full_path, exact: true) + end + end + + def expect_to_have_group(group) + expect(page).to have_selector("[entity-id='#{group.id}']") + end + + def expect_not_to_have_group(group) + expect(page).not_to have_selector("[entity-id='#{group.id}']") end end end diff --git a/spec/features/projects/members/member_leaves_project_spec.rb b/spec/features/projects/members/member_leaves_project_spec.rb index 4881a7bdf1a..c38292f81bf 100644 --- a/spec/features/projects/members/member_leaves_project_spec.rb +++ b/spec/features/projects/members/member_leaves_project_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe 'Projects > Members > Member leaves project' do + include Spec::Support::Helpers::Features::MembersHelpers + let(:user) { create(:user) } let(:project) { create(:project, :repository) } @@ -21,13 +23,18 @@ RSpec.describe 'Projects > Members > Member leaves project' do expect(project.users.exists?(user.id)).to be_falsey end - it 'user leaves project by url param', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/35925' do + it 'user leaves project by url param', :js do visit project_path(project, leave: 1) page.accept_confirm + wait_for_all_requests - expect(find('.flash-notice')).to have_content "You left the \"#{project.full_name}\" project" expect(current_path).to eq(dashboard_projects_path) - expect(project.users.exists?(user.id)).to be_falsey + + sign_in(project.first_owner) + + visit project_project_members_path(project) + + expect(members_table).not_to have_content(user.name) end end diff --git a/spec/features/projects/members/owner_cannot_leave_project_spec.rb b/spec/features/projects/members/owner_cannot_leave_project_spec.rb index fbe8583b236..45a8f979b87 100644 --- a/spec/features/projects/members/owner_cannot_leave_project_spec.rb +++ b/spec/features/projects/members/owner_cannot_leave_project_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'Projects > Members > Owner cannot leave project' do let(:project) { create(:project) } before do - sign_in(project.owner) + sign_in(project.first_owner) visit project_path(project) end diff --git a/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb b/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb index 5e6e3d4d7f2..fad5d831c19 100644 --- a/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb +++ b/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'Projects > Members > Owner cannot request access to their own pr let(:project) { create(:project) } before do - sign_in(project.owner) + sign_in(project.first_owner) visit project_path(project) end diff --git a/spec/features/projects/members/user_requests_access_spec.rb b/spec/features/projects/members/user_requests_access_spec.rb index dcaef5f4ef0..0b00656f87b 100644 --- a/spec/features/projects/members/user_requests_access_spec.rb +++ b/spec/features/projects/members/user_requests_access_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'Projects > Members > User requests access', :js do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, :public, :repository) } - let(:maintainer) { project.owner } + let(:maintainer) { project.first_owner } before do sign_in(user) diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb index f61eaccf5b9..91e643ff258 100644 --- a/spec/features/projects/navbar_spec.rb +++ b/spec/features/projects/navbar_spec.rb @@ -10,7 +10,7 @@ RSpec.describe 'Project navbar' do let_it_be(:project) { create(:project, :repository) } - let(:user) { project.owner } + let(:user) { project.first_owner } before do sign_in(user) diff --git a/spec/features/projects/network_graph_spec.rb b/spec/features/projects/network_graph_spec.rb index 4ae809399b6..1ee0ea51e53 100644 --- a/spec/features/projects/network_graph_spec.rb +++ b/spec/features/projects/network_graph_spec.rb @@ -96,7 +96,7 @@ RSpec.describe 'Project Network Graph', :js do find('button').click end - expect(page).to have_selector '.flash-alert', text: "Git revision ';' does not exist." + expect(page).to have_selector '[data-testid="alert-danger"]', text: "Git revision ';' does not exist." end end diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb index f1786c1be40..b3fbf5d356e 100644 --- a/spec/features/projects/new_project_spec.rb +++ b/spec/features/projects/new_project_spec.rb @@ -306,10 +306,24 @@ RSpec.describe 'New project', :js do expect(page).to have_text('There is not a valid Git repository at this URL') end + it 'reports error if repo URL is not a valid Git repository and submit button is clicked immediately' do + stub_request(:get, "http://foo/bar/info/refs?service=git-upload-pack").to_return(status: 200, body: "not-a-git-repo") + + fill_in 'project_import_url', with: 'http://foo/bar' + click_on 'Create project' + + wait_for_requests + + expect(page).to have_text('There is not a valid Git repository at this URL') + end + it 'keeps "Import project" tab open after form validation error' do collision_project = create(:project, name: 'test-name-collision', namespace: user.namespace) + stub_request(:get, "http://foo/bar/info/refs?service=git-upload-pack").to_return({ status: 200, + body: '001e# service=git-upload-pack', + headers: { 'Content-Type': 'application/x-git-upload-pack-advertisement' } }) - fill_in 'project_import_url', with: collision_project.http_url_to_repo + fill_in 'project_import_url', with: 'http://foo/bar' fill_in 'project_name', with: collision_project.name click_on 'Create project' @@ -319,6 +333,38 @@ RSpec.describe 'New project', :js do end end + context 'when import is initiated from project page' do + before do + project_without_repo = create(:project, name: 'project-without-repo', namespace: user.namespace) + visit project_path(project_without_repo) + click_on 'Import repository' + end + + it 'reports error when invalid url is provided' do + stub_request(:get, "http://foo/bar/info/refs?service=git-upload-pack").to_return(status: 200, body: "not-a-git-repo") + + fill_in 'project_import_url', with: 'http://foo/bar' + + click_on 'Start import' + wait_for_requests + + expect(page).to have_text('There is not a valid Git repository at this URL') + end + + it 'initiates import when valid repo url is provided' do + stub_request(:get, "http://foo/bar/info/refs?service=git-upload-pack").to_return({ status: 200, + body: '001e# service=git-upload-pack', + headers: { 'Content-Type': 'application/x-git-upload-pack-advertisement' } }) + + fill_in 'project_import_url', with: 'http://foo/bar' + + click_on 'Start import' + wait_for_requests + + expect(page).to have_text('Import in progress') + end + end + context 'from GitHub' do before do first('.js-import-github').click @@ -358,4 +404,47 @@ RSpec.describe 'New project', :js do end end end + + context 'from Bitbucket', :js do + shared_examples 'has a link to bitbucket cloud' do + context 'when bitbucket is not configured' do + before do + allow(Gitlab::Auth::OAuth::Provider).to receive(:enabled?).and_call_original + allow(Gitlab::Auth::OAuth::Provider) + .to receive(:enabled?).with(:bitbucket) + .and_return(false) + + visit new_project_path + click_link 'Import project' + click_link 'Bitbucket Cloud' + end + + it 'shows import instructions' do + expect(find('.modal-body')).to have_content(bitbucket_link_content) + end + end + end + + context 'as a user' do + let(:user) { create(:user) } + let(:bitbucket_link_content) { 'To enable importing projects from Bitbucket, ask your GitLab administrator to configure OAuth integration' } + + before do + sign_in(user) + end + + it_behaves_like 'has a link to bitbucket cloud' + end + + context 'as an admin' do + let(:user) { create(:admin) } + let(:bitbucket_link_content) { 'To enable importing projects from Bitbucket, as administrator you need to configure OAuth integration' } + + before do + sign_in(user) + end + + it_behaves_like 'has a link to bitbucket cloud' + end + end end diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index 5176a7ec5a1..01c942aec4c 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -715,7 +715,7 @@ RSpec.describe 'Pipeline', :js do let(:schedule) do create(:ci_pipeline_schedule, project: project, - owner: project.owner, + owner: project.first_owner, description: 'blocked user schedule' ).tap do |schedule| schedule.update_column(:next_run_at, 1.minute.ago) diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index fb45db213d0..d5b470194a2 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe 'Pipelines', :js do include ProjectForksHelper + include Spec::Support::Helpers::ModalHelpers let(:project) { create(:project) } @@ -159,7 +160,7 @@ RSpec.describe 'Pipelines', :js do end end - context 'when pipeline is detached merge request pipeline' do + context 'when pipeline is detached merge request pipeline, with rearrange_pipelines_table feature flag turned off' do let(:merge_request) do create(:merge_request, :with_detached_merge_request_pipeline, @@ -172,6 +173,8 @@ RSpec.describe 'Pipelines', :js do let(:target_project) { project } before do + stub_feature_flags(rearrange_pipelines_table: false) + visit project_pipelines_path(source_project) end @@ -201,7 +204,47 @@ RSpec.describe 'Pipelines', :js do end end - context 'when pipeline is merge request pipeline' do + context 'when pipeline is detached merge request pipeline, with rearrange_pipelines_table feature flag turned on' do + let(:merge_request) do + create(:merge_request, + :with_detached_merge_request_pipeline, + source_project: source_project, + target_project: target_project) + end + + let!(:pipeline) { merge_request.all_pipelines.first } + let(:source_project) { project } + let(:target_project) { project } + + before do + stub_feature_flags(rearrange_pipelines_table: true) + + visit project_pipelines_path(source_project) + end + + shared_examples_for 'detached merge request pipeline' do + it 'shows pipeline information without pipeline ref', :sidekiq_might_not_need_inline do + within '.pipeline-tags' do + expect(page).to have_content('detached') + + expect(page).to have_link(merge_request.iid, + href: project_merge_request_path(project, merge_request)) + + expect(page).not_to have_link(pipeline.ref) + end + end + end + + it_behaves_like 'detached merge request pipeline' + + context 'when source project is a forked project' do + let(:source_project) { fork_project(project, user, repository: true) } + + it_behaves_like 'detached merge request pipeline' + end + end + + context 'when pipeline is merge request pipeline, with rearrange_pipelines_table feature flag turned off' do let(:merge_request) do create(:merge_request, :with_merge_request_pipeline, @@ -215,6 +258,8 @@ RSpec.describe 'Pipelines', :js do let(:target_project) { project } before do + stub_feature_flags(rearrange_pipelines_table: false) + visit project_pipelines_path(source_project) end @@ -244,6 +289,47 @@ RSpec.describe 'Pipelines', :js do end end + context 'when pipeline is merge request pipeline, with rearrange_pipelines_table feature flag turned on' do + let(:merge_request) do + create(:merge_request, + :with_merge_request_pipeline, + source_project: source_project, + target_project: target_project, + merge_sha: target_project.commit.sha) + end + + let!(:pipeline) { merge_request.all_pipelines.first } + let(:source_project) { project } + let(:target_project) { project } + + before do + stub_feature_flags(rearrange_pipelines_table: true) + + visit project_pipelines_path(source_project) + end + + shared_examples_for 'Correct merge request pipeline information' do + it 'does not show detached tag for the pipeline, and shows the link of the merge request, and does not show the ref of the pipeline', :sidekiq_might_not_need_inline do + within '.pipeline-tags' do + expect(page).not_to have_content('detached') + + expect(page).to have_link(merge_request.iid, + href: project_merge_request_path(project, merge_request)) + + expect(page).not_to have_link(pipeline.ref) + end + end + end + + it_behaves_like 'Correct merge request pipeline information' + + context 'when source project is a forked project' do + let(:source_project) { fork_project(project, user, repository: true) } + + it_behaves_like 'Correct merge request pipeline information' + end + end + context 'when pipeline has configuration errors' do let(:pipeline) do create(:ci_pipeline, :invalid, project: project) @@ -351,7 +437,9 @@ RSpec.describe 'Pipelines', :js do context 'when user played a delayed job immediately' do before do find('[data-testid="pipelines-manual-actions-dropdown"]').click - page.accept_confirm { click_button('delayed job 1') } + accept_gl_confirm do + click_button 'delayed job 1' + end wait_for_requests end @@ -587,6 +675,7 @@ RSpec.describe 'Pipelines', :js do context 'with pipeline key selection' do before do + stub_feature_flags(rearrange_pipelines_table: false) visit project_pipelines_path(project) wait_for_requests end @@ -604,6 +693,27 @@ RSpec.describe 'Pipelines', :js do expect(page.find('[data-testid="pipeline-url-link"]')).to have_content "##{pipeline.iid}" end end + + context 'with pipeline key selection and rearrange_pipelines_table ff on' do + before do + stub_feature_flags(rearrange_pipelines_table: true) + visit project_pipelines_path(project) + wait_for_requests + end + + it 'changes the Pipeline ID column for Pipeline IID' do + page.find('[data-testid="pipeline-key-dropdown"]').click + + within '.gl-new-dropdown-contents' do + dropdown_options = page.find_all '.gl-new-dropdown-item' + + dropdown_options[1].click + end + + expect(page.find('[data-testid="pipeline-th"]')).to have_content 'Pipeline' + expect(page.find('[data-testid="pipeline-identifier"]')).to have_content "##{pipeline.iid}" + end + end end describe 'GET /:project/-/pipelines/show' do @@ -750,7 +860,7 @@ RSpec.describe 'Pipelines', :js do it 'increments jobs_cache_index' do click_button 'Clear runner caches' wait_for_requests - expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.' + expect(page.find('[data-testid="alert-info"]')).to have_content 'Project cache successfully reset.' end end @@ -758,7 +868,7 @@ RSpec.describe 'Pipelines', :js do it 'sets jobs_cache_index to 1' do click_button 'Clear runner caches' wait_for_requests - expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.' + expect(page.find('[data-testid="alert-info"]')).to have_content 'Project cache successfully reset.' end end end diff --git a/spec/features/projects/settings/monitor_settings_spec.rb b/spec/features/projects/settings/monitor_settings_spec.rb index 3f6c4646f00..871391fbe9c 100644 --- a/spec/features/projects/settings/monitor_settings_spec.rb +++ b/spec/features/projects/settings/monitor_settings_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe 'Projects > Settings > For a forked project', :js do let_it_be(:project) { create(:project, :repository, create_templates: :issue) } - let(:user) { project.owner } + let(:user) { project.first_owner } before do sign_in(user) diff --git a/spec/features/projects/settings/packages_settings_spec.rb b/spec/features/projects/settings/packages_settings_spec.rb index e70839e9720..057e6b635fe 100644 --- a/spec/features/projects/settings/packages_settings_spec.rb +++ b/spec/features/projects/settings/packages_settings_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe 'Projects > Settings > Packages', :js do let_it_be(:project) { create(:project) } - let(:user) { project.owner } + let(:user) { project.first_owner } before do sign_in(user) diff --git a/spec/features/projects/settings/project_settings_spec.rb b/spec/features/projects/settings/project_settings_spec.rb index b67caa5a5f9..a0d44b579a8 100644 --- a/spec/features/projects/settings/project_settings_spec.rb +++ b/spec/features/projects/settings/project_settings_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe 'Projects settings' do let_it_be(:project) { create(:project) } - let(:user) { project.owner } + let(:user) { project.first_owner } let(:panel) { find('.general-settings', match: :first) } let(:button) { panel.find('.btn.gl-button.js-settings-toggle') } let(:title) { panel.find('.settings-title') } diff --git a/spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb b/spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb index 91a7753fe6d..d16295aedbe 100644 --- a/spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb +++ b/spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb @@ -4,7 +4,7 @@ require "spec_helper" RSpec.describe "User interacts with deploy keys", :js do let(:project) { create(:project, :repository) } - let(:user) { project.owner } + let(:user) { project.first_owner } before do sign_in(user) diff --git a/spec/features/projects/show/redirects_spec.rb b/spec/features/projects/show/redirects_spec.rb index 659edda5672..3ac82244ded 100644 --- a/spec/features/projects/show/redirects_spec.rb +++ b/spec/features/projects/show/redirects_spec.rb @@ -47,7 +47,7 @@ RSpec.describe 'Projects > Show > Redirects' do it 'redirects to private project page after sign in' do visit project_path(private_project) - owner = private_project.owner + owner = private_project.first_owner fill_in 'user_login', with: owner.email fill_in 'user_password', with: owner.password click_button 'Sign in' diff --git a/spec/features/projects/show/user_manages_notifications_spec.rb b/spec/features/projects/show/user_manages_notifications_spec.rb index 80dae4ec386..1df37eef6a9 100644 --- a/spec/features/projects/show/user_manages_notifications_spec.rb +++ b/spec/features/projects/show/user_manages_notifications_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'Projects > Show > User manages notifications', :js do let(:project) { create(:project, :public, :repository) } before do - sign_in(project.owner) + sign_in(project.first_owner) end def click_notifications_button diff --git a/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb b/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb index b7af0c29b33..47e010dcf89 100644 --- a/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb +++ b/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'Projects > Show > User sees a deletion failure message' do let(:project) { create(:project, :empty_repo, pending_delete: true) } before do - sign_in(project.owner) + sign_in(project.first_owner) end it 'shows error message if deletion for project fails' do diff --git a/spec/features/projects/show/user_sees_git_instructions_spec.rb b/spec/features/projects/show/user_sees_git_instructions_spec.rb index e6157887c12..5270939f681 100644 --- a/spec/features/projects/show/user_sees_git_instructions_spec.rb +++ b/spec/features/projects/show/user_sees_git_instructions_spec.rb @@ -61,7 +61,7 @@ RSpec.describe 'Projects > Show > User sees Git instructions' do let_it_be(:project) { create(:project, :public) } before do - sign_in(project.owner) + sign_in(project.first_owner) visit project_path(project) end @@ -77,7 +77,7 @@ RSpec.describe 'Projects > Show > User sees Git instructions' do .at_least(:once) .and_return('example_branch') - sign_in(project.owner) + sign_in(project.first_owner) visit project_path(project) end diff --git a/spec/features/projects/tree/tree_show_spec.rb b/spec/features/projects/tree/tree_show_spec.rb index f8bbaa9535b..cd94e6da018 100644 --- a/spec/features/projects/tree/tree_show_spec.rb +++ b/spec/features/projects/tree/tree_show_spec.rb @@ -25,7 +25,7 @@ RSpec.describe 'Projects tree', :js do expect(page).to have_selector('.tree-item') expect(page).to have_content('add tests for .gitattributes custom highlighting') - expect(page).not_to have_selector('.flash-alert') + expect(page).not_to have_selector('[data-testid="alert-danger"]') expect(page).not_to have_selector('[data-qa-selector="label-lfs"]', text: 'LFS') # rubocop:disable QA/SelectorUsage end @@ -36,7 +36,7 @@ RSpec.describe 'Projects tree', :js do expect(page).to have_selector('.tree-item') expect(page).to have_content('add spaces in whitespace file') expect(page).not_to have_selector('[data-qa-selector="label-lfs"]', text: 'LFS') # rubocop:disable QA/SelectorUsage - expect(page).not_to have_selector('.flash-alert') + expect(page).not_to have_selector('[data-testid="alert-danger"]') end it 'renders tree table with non-ASCII filenames without errors' do @@ -46,7 +46,7 @@ RSpec.describe 'Projects tree', :js do expect(page).to have_selector('.tree-item') expect(page).to have_content('Files, encoding and much more') expect(page).to have_content('ใในใ.txt') - expect(page).not_to have_selector('.flash-alert') + expect(page).not_to have_selector('[data-testid="alert-danger"]') end context "with a tree that contains pathspec characters" do @@ -139,7 +139,7 @@ RSpec.describe 'Projects tree', :js do wait_for_requests expect(page).to have_selector('.tree-item') - expect(page).not_to have_selector('.flash-alert') + expect(page).not_to have_selector('[data-testid="alert-danger"]') end context 'for signed commit' do diff --git a/spec/features/projects/user_changes_project_visibility_spec.rb b/spec/features/projects/user_changes_project_visibility_spec.rb index 68fed9b8a74..d2a7596aec0 100644 --- a/spec/features/projects/user_changes_project_visibility_spec.rb +++ b/spec/features/projects/user_changes_project_visibility_spec.rb @@ -43,9 +43,9 @@ RSpec.describe 'User changes public project visibility', :js do context 'when the project has forks' do before do - fork_project(project, project.owner) + fork_project(project, project.first_owner) - sign_in(project.owner) + sign_in(project.first_owner) visit edit_project_path(project) end @@ -84,7 +84,7 @@ RSpec.describe 'User changes public project visibility', :js do let(:project) { create(:project, :empty_repo, :public) } before do - sign_in(project.owner) + sign_in(project.first_owner) visit edit_project_path(project) end @@ -98,9 +98,9 @@ RSpec.describe 'User changes public project visibility', :js do before do stub_feature_flags(unlink_fork_network_upon_visibility_decrease: false) - fork_project(project, project.owner) + fork_project(project, project.first_owner) - sign_in(project.owner) + sign_in(project.first_owner) visit edit_project_path(project) end diff --git a/spec/features/projects/user_uses_shortcuts_spec.rb b/spec/features/projects/user_uses_shortcuts_spec.rb index 7bb15451538..cd6f09ce275 100644 --- a/spec/features/projects/user_uses_shortcuts_spec.rb +++ b/spec/features/projects/user_uses_shortcuts_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe 'User uses shortcuts', :js do let_it_be(:project) { create(:project, :repository) } - let(:user) { project.owner } + let(:user) { project.first_owner } before do sign_in(user) diff --git a/spec/features/projects/view_on_env_spec.rb b/spec/features/projects/view_on_env_spec.rb index 94085b075aa..5dd30f59e3d 100644 --- a/spec/features/projects/view_on_env_spec.rb +++ b/spec/features/projects/view_on_env_spec.rb @@ -9,7 +9,6 @@ RSpec.describe 'View on environment', :js do let(:user) { project.creator } before do - stub_feature_flags(refactor_blob_viewer: false) # This stub will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/350457 project.add_maintainer(user) end diff --git a/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb b/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb index 63ee89bd11f..fbb5c24f6e1 100644 --- a/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb +++ b/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe 'Projects > Wiki > User views wiki in project page' do before do - sign_in(project.owner) + sign_in(project.first_owner) end context 'when repository is disabled for project' do |