diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-04-27 15:08:19 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-04-27 15:08:19 +0300 |
commit | 863ba7d77355b305b06112b0c6c3cab3c09898b0 (patch) | |
tree | 6b657c3bfc0cff804fad6094ba61d42c6925c4d4 /spec | |
parent | 359bc6940b1205035e14f028b75d0c9c80a1fd5e (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
34 files changed, 355 insertions, 162 deletions
diff --git a/spec/components/pajamas/alert_component_spec.rb b/spec/components/pajamas/alert_component_spec.rb index 628d715ff64..58c1cb2231a 100644 --- a/spec/components/pajamas/alert_component_spec.rb +++ b/spec/components/pajamas/alert_component_spec.rb @@ -25,47 +25,71 @@ RSpec.describe Pajamas::AlertComponent, :aggregate_failures, type: :component do it 'renders the default variant' do expect(rendered_component).to have_selector('.gl-alert-info') expect(rendered_component).to have_selector("[data-testid='information-o-icon']") + expect(rendered_component).not_to have_selector('.gl-alert-no-icon') end it 'renders a dismiss button' do expect(rendered_component).to have_selector('.gl-dismiss-btn.js-close') expect(rendered_component).to have_selector("[data-testid='close-icon']") + expect(rendered_component).not_to have_selector('.gl-alert-not-dismissible') end end context 'with custom options' do context 'with simple options' do - context 'without dismissible content' do - before do - render_inline described_class.new( - title: '_title_', - dismissible: false, - alert_class: '_alert_class_', - alert_data: { - feature_id: '_feature_id_', - dismiss_endpoint: '_dismiss_endpoint_' - } - ) - end + before do + render_inline described_class.new( + title: '_title_', + alert_class: '_alert_class_', + alert_data: { + feature_id: '_feature_id_', + dismiss_endpoint: '_dismiss_endpoint_' + } + ) + end - it 'sets the title' do - expect(rendered_component).to have_selector('.gl-alert-title') - expect(rendered_component).to have_content('_title_') - expect(rendered_component).not_to have_selector('.gl-alert-icon-no-title') - end + it 'sets the title' do + expect(rendered_component).to have_selector('.gl-alert-title') + expect(rendered_component).to have_content('_title_') + expect(rendered_component).not_to have_selector('.gl-alert-icon-no-title') + end - it 'sets to not be dismissible' do - expect(rendered_component).not_to have_selector('.gl-dismiss-btn.js-close') - expect(rendered_component).not_to have_selector("[data-testid='close-icon']") - end + it 'sets the alert_class' do + expect(rendered_component).to have_selector('._alert_class_') + end - it 'sets the alert_class' do - expect(rendered_component).to have_selector('._alert_class_') - end + it 'sets the alert_data' do + expect(rendered_component).to have_selector('[data-feature-id="_feature_id_"][data-dismiss-endpoint="_dismiss_endpoint_"]') + end + end - it 'sets the alert_data' do - expect(rendered_component).to have_selector('[data-feature-id="_feature_id_"][data-dismiss-endpoint="_dismiss_endpoint_"]') - end + context 'with dismissible disabled' do + before do + render_inline described_class.new(dismissible: false) + end + + it 'has the "not dismissible" class' do + expect(rendered_component).to have_selector('.gl-alert-not-dismissible') + end + + it 'does not render the dismiss button' do + expect(rendered_component).not_to have_selector('.gl-dismiss-btn.js-close') + expect(rendered_component).not_to have_selector("[data-testid='close-icon']") + end + end + + context 'with the icon hidden' do + before do + render_inline described_class.new(show_icon: false) + end + + it 'has the hidden icon class' do + expect(rendered_component).to have_selector('.gl-alert-no-icon') + end + + it 'does not render the icon' do + expect(rendered_component).not_to have_selector('.gl-alert-icon') + expect(rendered_component).not_to have_selector("[data-testid='information-o-icon']") end end @@ -79,6 +103,10 @@ RSpec.describe Pajamas::AlertComponent, :aggregate_failures, type: :component do ) end + it 'does not have "not dismissible" class' do + expect(rendered_component).not_to have_selector('.gl-alert-not-dismissible') + end + it 'renders a dismiss button and data' do expect(rendered_component).to have_selector('.gl-dismiss-btn.js-close._close_button_class_') expect(rendered_component).to have_selector("[data-testid='close-icon']") diff --git a/spec/controllers/uploads_controller_spec.rb b/spec/controllers/uploads_controller_spec.rb index ffcd759435c..c27e58634f6 100644 --- a/spec/controllers/uploads_controller_spec.rb +++ b/spec/controllers/uploads_controller_spec.rb @@ -703,13 +703,16 @@ RSpec.describe UploadsController do end context 'when viewing alert metric images' do - let!(:user) { create(:user) } - let!(:project) { create(:project) } - let(:alert) { create(:alert_management_alert, project: project) } - let(:metric_image) { create(:alert_metric_image, alert: alert) } + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project) } + let_it_be(:alert) { create(:alert_management_alert, project: project) } + let_it_be(:metric_image) { create(:alert_metric_image, alert: alert) } - before do + before_all do project.add_developer(user) + end + + before do sign_in(user) end diff --git a/spec/features/groups/empty_states_spec.rb b/spec/features/groups/empty_states_spec.rb index 0317f9162cc..71f38401fa1 100644 --- a/spec/features/groups/empty_states_spec.rb +++ b/spec/features/groups/empty_states_spec.rb @@ -7,6 +7,8 @@ RSpec.describe 'Group empty states' do let(:user) { create(:group_member, :developer, user: create(:user), group: group ).user } before do + stub_feature_flags(vue_issues_list: true) + sign_in(user) end @@ -100,21 +102,23 @@ RSpec.describe 'Group empty states' do end it "the new #{issuable_name} button opens a project dropdown" do - within '.empty-state' do - click_button 'Toggle project select' - end + click_button 'Toggle project select' - expect(page).to have_selector('.ajax-project-dropdown') + if issuable == :issue + expect(page).to have_button project.name + else + expect(page).to have_selector('.ajax-project-dropdown') + end end end end shared_examples "no projects" do - it 'displays an empty state' do + it 'displays an empty state', :js do expect(page).to have_selector('.empty-state') end - it "does not show a new #{issuable_name} button" do + it "does not show a new #{issuable_name} button", :js do within '.empty-state' do expect(page).not_to have_link("create #{issuable_name}") end @@ -143,7 +147,7 @@ RSpec.describe 'Group empty states' do visit path end - it 'displays an empty state' do + it 'displays an empty state', :js do expect(page).to have_selector('.empty-state') end end diff --git a/spec/features/issuables/issuable_list_spec.rb b/spec/features/issuables/issuable_list_spec.rb index a0786d36fdf..7edf5fdc5ff 100644 --- a/spec/features/issuables/issuable_list_spec.rb +++ b/spec/features/issuables/issuable_list_spec.rb @@ -9,6 +9,8 @@ RSpec.describe 'issuable list', :js do issuable_types = [:issue, :merge_request] before do + stub_feature_flags(vue_issues_list: true) + project.add_user(user, :developer) sign_in(user) issuable_types.each { |type| create_issuables(type) } @@ -34,16 +36,16 @@ RSpec.describe 'issuable list', :js do it 'sorts labels alphabetically' do label1 = create(:label, project: project, title: 'a') label2 = create(:label, project: project, title: 'z') - label3 = create(:label, project: project, title: 'X') - label4 = create(:label, project: project, title: 'B') + label3 = create(:label, project: project, title: 'x') + label4 = create(:label, project: project, title: 'b') issuable = create_issuable(issuable_type) issuable.labels << [label1, label2, label3, label4] visit_issuable_list(issuable_type) - expect(all('.gl-label-text')[0].text).to have_content('B') - expect(all('.gl-label-text')[1].text).to have_content('X') - expect(all('.gl-label-text')[2].text).to have_content('a') + expect(all('.gl-label-text')[0].text).to have_content('a') + expect(all('.gl-label-text')[1].text).to have_content('b') + expect(all('.gl-label-text')[2].text).to have_content('x') expect(all('.gl-label-text')[3].text).to have_content('z') end end diff --git a/spec/features/issue_rebalancing_spec.rb b/spec/features/issue_rebalancing_spec.rb index 978768270ec..8a05aeec7ec 100644 --- a/spec/features/issue_rebalancing_spec.rb +++ b/spec/features/issue_rebalancing_spec.rb @@ -15,6 +15,10 @@ RSpec.describe 'Issue rebalancing' do group.add_developer(user) end + before do + stub_feature_flags(vue_issues_list: true) + end + context 'when issue rebalancing is in progress' do before do sign_in(user) @@ -38,16 +42,16 @@ RSpec.describe 'Issue rebalancing' do expect(page).to have_selector('.gl-alert-info', text: alert_message_regex, count: 1) end - it 'shows an alert in project issues list with manual sort' do + it 'shows an alert in project issues list with manual sort', :js do visit project_issues_path(project, sort: 'relative_position') - expect(page).to have_selector('.gl-alert-info', text: alert_message_regex, count: 1) + expect(page).to have_selector('.flash-notice', text: alert_message_regex, count: 1) end - it 'shows an alert in group issues list with manual sort' do + it 'shows an alert in group issues list with manual sort', :js do visit issues_group_path(group, sort: 'relative_position') - expect(page).to have_selector('.gl-alert-info', text: alert_message_regex, count: 1) + expect(page).to have_selector('.flash-notice', text: alert_message_regex, count: 1) end it 'does not show an alert in project issues list with other sorts' do diff --git a/spec/features/issues/rss_spec.rb b/spec/features/issues/rss_spec.rb index b20502ecc25..bdc5f282875 100644 --- a/spec/features/issues/rss_spec.rb +++ b/spec/features/issues/rss_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Project Issues RSS' do +RSpec.describe 'Project Issues RSS', :js do let_it_be(:user) { create(:user) } let_it_be(:group) { create(:group) } let_it_be(:project) { create(:project, group: group, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } @@ -13,6 +13,10 @@ RSpec.describe 'Project Issues RSS' do group.add_developer(user) end + before do + stub_feature_flags(vue_issues_list: true) + end + context 'when signed in' do let_it_be(:user) { create(:user) } @@ -25,7 +29,10 @@ RSpec.describe 'Project Issues RSS' do visit path end - it_behaves_like "it has an RSS button with current_user's feed token" + it "shows the RSS button with current_user's feed token" do + expect(page).to have_link 'Subscribe to RSS feed', href: /feed_token=#{user.feed_token}/ + end + it_behaves_like "an autodiscoverable RSS feed with current_user's feed token" end @@ -34,7 +41,10 @@ RSpec.describe 'Project Issues RSS' do visit path end - it_behaves_like "it has an RSS button without a feed token" + it "shows the RSS button without a feed token" do + expect(page).not_to have_link 'Subscribe to RSS feed', href: /feed_token/ + end + it_behaves_like "an autodiscoverable RSS feed without a feed token" end diff --git a/spec/features/issues/user_bulk_edits_issues_labels_spec.rb b/spec/features/issues/user_bulk_edits_issues_labels_spec.rb index 71213fb661f..27377f6e1fd 100644 --- a/spec/features/issues/user_bulk_edits_issues_labels_spec.rb +++ b/spec/features/issues/user_bulk_edits_issues_labels_spec.rb @@ -12,8 +12,12 @@ RSpec.describe 'Issues > Labels bulk assignment' do let!(:issue1) { create(:issue, project: project, title: "Issue 1", labels: [frontend]) } let!(:issue2) { create(:issue, project: project, title: "Issue 2") } - let(:issue_1_selector) { "#issue_#{issue1.id}" } - let(:issue_2_selector) { "#issue_#{issue2.id}" } + let(:issue_1_selector) { "#issuable_#{issue1.id}" } + let(:issue_2_selector) { "#issuable_#{issue2.id}" } + + before do + stub_feature_flags(vue_issues_list: true) + end context 'as an allowed user', :js do before do diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb index 8a5e33ba18c..3bba041dab7 100644 --- a/spec/features/issues/user_creates_issue_spec.rb +++ b/spec/features/issues/user_creates_issue_spec.rb @@ -8,12 +8,16 @@ RSpec.describe "User creates issue" do let_it_be(:project) { create(:project_empty_repo, :public) } let_it_be(:user) { create(:user) } + before do + stub_feature_flags(vue_issues_list: true) + end + context "when unauthenticated" do before do sign_out(:user) end - it "redirects to signin then back to new issue after signin" do + it "redirects to signin then back to new issue after signin", :js do create(:issue, project: project) visit project_issues_path(project) diff --git a/spec/features/issues/user_filters_issues_spec.rb b/spec/features/issues/user_filters_issues_spec.rb index 5d05df6aaf0..42c2b5d32c1 100644 --- a/spec/features/issues/user_filters_issues_spec.rb +++ b/spec/features/issues/user_filters_issues_spec.rb @@ -7,6 +7,8 @@ RSpec.describe 'User filters issues', :js do let_it_be(:project) { create(:project_empty_repo, :public) } before do + stub_feature_flags(vue_issues_list: true) + %w[foobar barbaz].each do |title| create(:issue, author: user, @@ -24,7 +26,7 @@ RSpec.describe 'User filters issues', :js do let(:issue) { @issue } it 'allows filtering by issues with no specified assignee' do - visit project_issues_path(project, assignee_id: IssuableFinder::Params::FILTER_NONE) + visit project_issues_path(project, assignee_id: IssuableFinder::Params::FILTER_NONE.capitalize) expect(page).to have_content 'foobar' expect(page).not_to have_content 'barbaz' diff --git a/spec/features/issues/user_sees_breadcrumb_links_spec.rb b/spec/features/issues/user_sees_breadcrumb_links_spec.rb index 669c7c45411..44fa062480a 100644 --- a/spec/features/issues/user_sees_breadcrumb_links_spec.rb +++ b/spec/features/issues/user_sees_breadcrumb_links_spec.rb @@ -8,6 +8,8 @@ RSpec.describe 'New issue breadcrumb' do let(:user) { project.creator } before do + stub_feature_flags(vue_issues_list: true) + sign_in(user) visit(new_project_issue_path(project)) end @@ -27,7 +29,7 @@ RSpec.describe 'New issue breadcrumb' do expect(find('.breadcrumbs-sub-title a')[:href]).to end_with(issue_path(issue)) end - it 'excludes award_emoji from comment count' do + it 'excludes award_emoji from comment count', :js do issue = create(:issue, author: user, assignees: [user], project: project, title: 'foobar') create(:award_emoji, awardable: issue) diff --git a/spec/features/issues/user_sorts_issues_spec.rb b/spec/features/issues/user_sorts_issues_spec.rb index 86bdaf5d706..4af313576ed 100644 --- a/spec/features/issues/user_sorts_issues_spec.rb +++ b/spec/features/issues/user_sorts_issues_spec.rb @@ -16,6 +16,8 @@ RSpec.describe "User sorts issues" do let_it_be(:later_due_milestone) { create(:milestone, project: project, due_date: '2013-12-12') } before do + stub_feature_flags(vue_issues_list: true) + create_list(:award_emoji, 2, :upvote, awardable: issue1) create_list(:award_emoji, 2, :downvote, awardable: issue2) create(:award_emoji, :downvote, awardable: issue1) @@ -24,26 +26,23 @@ RSpec.describe "User sorts issues" do sign_in(user) end - it 'keeps the sort option' do + it 'keeps the sort option', :js do visit(project_issues_path(project)) - find('.filter-dropdown-container .dropdown').click - - page.within('ul.dropdown-menu.dropdown-menu-right li') do - click_link('Milestone') - end + click_button 'Created date' + click_button 'Milestone' visit(issues_dashboard_path(assignee_username: user.username)) - expect(find('.issues-filters a.is-active')).to have_content('Milestone') + expect(page).to have_button 'Milestone' visit(project_issues_path(project)) - expect(find('.issues-filters a.is-active')).to have_content('Milestone') + expect(page).to have_button 'Milestone' visit(issues_group_path(group)) - expect(find('.issues-filters a.is-active')).to have_content('Milestone') + expect(page).to have_button 'Milestone' end it 'sorts by popularity', :js do diff --git a/spec/features/merge_requests/user_sorts_merge_requests_spec.rb b/spec/features/merge_requests/user_sorts_merge_requests_spec.rb index 99473f3b1ea..fba7facaa1f 100644 --- a/spec/features/merge_requests/user_sorts_merge_requests_spec.rb +++ b/spec/features/merge_requests/user_sorts_merge_requests_spec.rb @@ -16,6 +16,8 @@ RSpec.describe 'User sorts merge requests' do let_it_be(:project) { create(:project, :public, group: group) } before do + stub_feature_flags(vue_issues_list: true) + sign_in(user) visit(project_merge_requests_path(project)) @@ -49,7 +51,7 @@ RSpec.describe 'User sorts merge requests' do expect(find('.issues-filters a.is-active')).to have_content('Milestone') end - it 'separates remember sorting with issues' do + it 'separates remember sorting with issues', :js do create(:issue, project: project) find('.filter-dropdown-container .dropdown').click diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb index 3b70d177fce..07b7a54974a 100644 --- a/spec/features/projects/jobs/user_browses_jobs_spec.rb +++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb @@ -19,7 +19,7 @@ RSpec.describe 'User browses jobs' do stub_feature_flags(jobs_table_vue: false) project.add_maintainer(user) project.enable_ci - project.update_attribute(:build_coverage_regex, /Coverage (\d+)%/) + build.update!(coverage_regex: '/Coverage (\d+)%/') sign_in(user) diff --git a/spec/features/projects/settings/pipelines_settings_spec.rb b/spec/features/projects/settings/pipelines_settings_spec.rb index 39c4315bf0f..a64f81430d1 100644 --- a/spec/features/projects/settings/pipelines_settings_spec.rb +++ b/spec/features/projects/settings/pipelines_settings_spec.rb @@ -25,24 +25,6 @@ RSpec.describe "Projects > Settings > Pipelines settings" do context 'for maintainer' do let(:role) { :maintainer } - it 'be allowed to change' do - visit project_settings_ci_cd_path(project) - - fill_in('Test coverage parsing', with: 'coverage_regex') - - page.within '#js-general-pipeline-settings' do - click_on 'Save changes' - end - - expect(page.status_code).to eq(200) - - page.within '#js-general-pipeline-settings' do - expect(page).to have_button('Save changes', disabled: false) - end - - expect(page).to have_field('Test coverage parsing', with: 'coverage_regex') - end - it 'updates auto_cancel_pending_pipelines' do visit project_settings_ci_cd_path(project) diff --git a/spec/features/user_sorts_things_spec.rb b/spec/features/user_sorts_things_spec.rb index fa37d692225..9cff08c7f29 100644 --- a/spec/features/user_sorts_things_spec.rb +++ b/spec/features/user_sorts_things_spec.rb @@ -16,21 +16,24 @@ RSpec.describe "User sorts things" do let_it_be(:merge_request) { create(:merge_request, target_project: project, source_project: project, author: current_user) } before do + stub_feature_flags(vue_issues_list: true) + project.add_developer(current_user) sign_in(current_user) end - it "issues -> project home page -> issues" do + it "issues -> project home page -> issues", :js do sort_option = 'Updated date' visit(project_issues_path(project)) - sort_by(sort_option) + click_button 'Created date' + click_button sort_option visit(project_path(project)) visit(project_issues_path(project)) - expect(find(".issues-filters")).to have_content(sort_option) + expect(page).to have_button(sort_option) end it "merge requests -> dashboard merge requests" do diff --git a/spec/fixtures/lib/gitlab/import_export/designs/project.json b/spec/fixtures/lib/gitlab/import_export/designs/project.json index 16dd805c132..6720139adeb 100644 --- a/spec/fixtures/lib/gitlab/import_export/designs/project.json +++ b/spec/fixtures/lib/gitlab/import_export/designs/project.json @@ -9,7 +9,6 @@ "merge_requests_ff_only_enabled":false, "issues_template":null, "shared_runners_enabled":true, - "build_coverage_regex":null, "build_allow_git_fetch":true, "build_timeout":3600, "pending_delete":false, diff --git a/spec/fixtures/lib/gitlab/import_export/multi_pipeline_ref_one_external_pr/project.json b/spec/fixtures/lib/gitlab/import_export/multi_pipeline_ref_one_external_pr/project.json index 5ca803cc11f..d25371e10dd 100644 --- a/spec/fixtures/lib/gitlab/import_export/multi_pipeline_ref_one_external_pr/project.json +++ b/spec/fixtures/lib/gitlab/import_export/multi_pipeline_ref_one_external_pr/project.json @@ -5,7 +5,6 @@ "autoclose_referenced_issues": true, "boards": [], "build_allow_git_fetch": true, - "build_coverage_regex": null, "build_timeout": 3600, "ci_cd_settings": { "group_runners_enabled": true diff --git a/spec/fixtures/lib/gitlab/import_export/multi_pipeline_ref_one_external_pr/tree/project.json b/spec/fixtures/lib/gitlab/import_export/multi_pipeline_ref_one_external_pr/tree/project.json index 5f7cf8128bc..4e08ae31f36 100644 --- a/spec/fixtures/lib/gitlab/import_export/multi_pipeline_ref_one_external_pr/tree/project.json +++ b/spec/fixtures/lib/gitlab/import_export/multi_pipeline_ref_one_external_pr/tree/project.json @@ -1 +1 @@ -{"id":5,"approvals_before_merge":0,"archived":false,"auto_cancel_pending_pipelines":"enabled","autoclose_referenced_issues":true,"build_allow_git_fetch":true,"build_coverage_regex":null,"build_timeout":3600,"ci_config_path":null,"delete_error":null,"description":"Vim, Tmux and others","disable_overriding_approvers_per_merge_request":null,"external_authorization_classification_label":"","external_webhook_token":"D3mVYFzZkgZ5kMfcW_wx","public_builds":true,"shared_runners_enabled":true,"visibility_level":20} +{"id":5,"approvals_before_merge":0,"archived":false,"auto_cancel_pending_pipelines":"enabled","autoclose_referenced_issues":true,"build_allow_git_fetch":true,"build_timeout":3600,"ci_config_path":null,"delete_error":null,"description":"Vim, Tmux and others","disable_overriding_approvers_per_merge_request":null,"external_authorization_classification_label":"","external_webhook_token":"D3mVYFzZkgZ5kMfcW_wx","public_builds":true,"shared_runners_enabled":true,"visibility_level":20} diff --git a/spec/frontend/boards/components/board_list_header_spec.js b/spec/frontend/boards/components/board_list_header_spec.js index 14870ec76a2..2f9677680eb 100644 --- a/spec/frontend/boards/components/board_list_header_spec.js +++ b/spec/frontend/boards/components/board_list_header_spec.js @@ -132,7 +132,7 @@ describe('Board List Header Component', () => { const icon = findCaret(); - expect(icon.props('icon')).toBe('chevron-right'); + expect(icon.props('icon')).toBe('chevron-down'); }); it('should display expand icon when column is collapsed', async () => { @@ -140,7 +140,7 @@ describe('Board List Header Component', () => { const icon = findCaret(); - expect(icon.props('icon')).toBe('chevron-down'); + expect(icon.props('icon')).toBe('chevron-right'); }); it('should dispatch toggleListCollapse when clicking the collapse icon', async () => { diff --git a/spec/frontend/diffs/utils/diff_file_spec.js b/spec/frontend/diffs/utils/diff_file_spec.js index 3a6a537f924..778897be3ba 100644 --- a/spec/frontend/diffs/utils/diff_file_spec.js +++ b/spec/frontend/diffs/utils/diff_file_spec.js @@ -3,6 +3,7 @@ import { getShortShaFromFile, stats, isNotDiffable, + match, } from '~/diffs/utils/diff_file'; import { diffViewerModes } from '~/ide/constants'; import mockDiffFile from '../mock_data/diff_file'; @@ -262,4 +263,42 @@ describe('diff_file utilities', () => { expect(isNotDiffable(file)).toBe(false); }); }); + + describe('match', () => { + const authorityFileId = '68296a4f-f1c7-445a-bd0e-6e3b02c4eec0'; + const fih = 'file_identifier_hash'; + const fihs = 'file identifier hashes'; + let authorityFile; + + beforeAll(() => { + const files = getDiffFiles(); + + authorityFile = prepareRawDiffFile({ + file: files[0], + allFiles: files, + }); + + Object.freeze(authorityFile); + }); + + describe.each` + mode | comparisonFiles | keyName + ${'universal'} | ${[{ [fih]: 'ABC1' }, { id: 'foo' }, { id: authorityFileId }]} | ${'ids'} + ${'mr'} | ${[{ id: authorityFileId }, { [fih]: 'ABC2' }, { [fih]: 'ABC1' }]} | ${fihs} + `('$mode mode', ({ mode, comparisonFiles, keyName }) => { + it(`fails to match if files or ${keyName} aren't present`, () => { + expect(match({ fileA: authorityFile, fileB: undefined, mode })).toBe(false); + expect(match({ fileA: authorityFile, fileB: null, mode })).toBe(false); + expect(match({ fileA: authorityFile, fileB: comparisonFiles[0], mode })).toBe(false); + }); + + it(`fails to match if the ${keyName} aren't the same`, () => { + expect(match({ fileA: authorityFile, fileB: comparisonFiles[1], mode })).toBe(false); + }); + + it(`matches if the ${keyName} are the same`, () => { + expect(match({ fileA: authorityFile, fileB: comparisonFiles[2], mode })).toBe(true); + }); + }); + }); }); diff --git a/spec/frontend/notes/mixins/discussion_navigation_spec.js b/spec/frontend/notes/mixins/discussion_navigation_spec.js index aba80789a01..35b3dec6298 100644 --- a/spec/frontend/notes/mixins/discussion_navigation_spec.js +++ b/spec/frontend/notes/mixins/discussion_navigation_spec.js @@ -59,6 +59,7 @@ describe('Discussion navigation mixin', () => { diffs: { namespaced: true, actions: { scrollToFile }, + state: { diffFiles: [] }, }, }, }); diff --git a/spec/frontend/notes/mock_data.js b/spec/frontend/notes/mock_data.js index a4aeeda48d8..c7a6ca5eae3 100644 --- a/spec/frontend/notes/mock_data.js +++ b/spec/frontend/notes/mock_data.js @@ -1171,7 +1171,7 @@ export const discussion1 = { resolved: false, active: true, diff_file: { - file_path: 'about.md', + file_identifier_hash: 'discfile1', }, position: { new_line: 50, @@ -1189,7 +1189,7 @@ export const resolvedDiscussion1 = { resolvable: true, resolved: true, diff_file: { - file_path: 'about.md', + file_identifier_hash: 'discfile1', }, position: { new_line: 50, @@ -1208,7 +1208,7 @@ export const discussion2 = { resolved: false, active: true, diff_file: { - file_path: 'README.md', + file_identifier_hash: 'discfile2', }, position: { new_line: null, @@ -1227,7 +1227,7 @@ export const discussion3 = { active: true, resolved: false, diff_file: { - file_path: 'README.md', + file_identifier_hash: 'discfile3', }, position: { new_line: 21, @@ -1240,6 +1240,12 @@ export const discussion3 = { ], }; +export const authoritativeDiscussionFile = { + id: 'abc', + file_identifier_hash: 'discfile1', + order: 0, +}; + export const unresolvableDiscussion = { resolvable: false, }; diff --git a/spec/frontend/notes/stores/getters_spec.js b/spec/frontend/notes/stores/getters_spec.js index 9a11fdba508..6d078dcefcf 100644 --- a/spec/frontend/notes/stores/getters_spec.js +++ b/spec/frontend/notes/stores/getters_spec.js @@ -12,6 +12,7 @@ import { discussion2, discussion3, resolvedDiscussion1, + authoritativeDiscussionFile, unresolvableDiscussion, draftComments, draftReply, @@ -26,6 +27,23 @@ const createDiscussionNeighborParams = (discussionId, diffOrder, step) => ({ }); const asDraftDiscussion = (x) => ({ ...x, individual_note: true }); +const createRootState = () => { + return { + diffs: { + diffFiles: [ + { ...authoritativeDiscussionFile }, + { + ...authoritativeDiscussionFile, + ...{ id: 'abc2', file_identifier_hash: 'discfile2', order: 1 }, + }, + { + ...authoritativeDiscussionFile, + ...{ id: 'abc3', file_identifier_hash: 'discfile3', order: 2 }, + }, + ], + }, + }; +}; describe('Getters Notes Store', () => { let state; @@ -226,20 +244,84 @@ describe('Getters Notes Store', () => { const localGetters = { allResolvableDiscussions: [discussion3, discussion1, discussion2], }; + const rootState = createRootState(); - expect(getters.unresolvedDiscussionsIdsByDiff(state, localGetters)).toEqual([ + expect(getters.unresolvedDiscussionsIdsByDiff(state, localGetters, rootState)).toEqual([ 'abc1', 'abc2', 'abc3', ]); }); + // This is the same test as above, but it exercises the sorting algorithm + // for a "strange" Diff File ordering. The intent is to ensure that even if lots + // of shuffling has to occur, everything still works + + it('should return all discussions IDs in unusual diff order', () => { + const localGetters = { + allResolvableDiscussions: [discussion3, discussion1, discussion2], + }; + const rootState = { + diffs: { + diffFiles: [ + // 2 is first, but should sort 2nd + { + ...authoritativeDiscussionFile, + ...{ id: 'abc2', file_identifier_hash: 'discfile2', order: 1 }, + }, + // 1 is second, but should sort 3rd + { ...authoritativeDiscussionFile, ...{ order: 2 } }, + // 3 is third, but should sort 1st + { + ...authoritativeDiscussionFile, + ...{ id: 'abc3', file_identifier_hash: 'discfile3', order: 0 }, + }, + ], + }, + }; + + expect(getters.unresolvedDiscussionsIdsByDiff(state, localGetters, rootState)).toEqual([ + 'abc3', + 'abc2', + 'abc1', + ]); + }); + + it("should use the discussions array order if the files don't have explicit order values", () => { + const localGetters = { + allResolvableDiscussions: [discussion3, discussion1, discussion2], // This order is used! + }; + const auth1 = { ...authoritativeDiscussionFile }; + const auth2 = { + ...authoritativeDiscussionFile, + ...{ id: 'abc2', file_identifier_hash: 'discfile2' }, + }; + const auth3 = { + ...authoritativeDiscussionFile, + ...{ id: 'abc3', file_identifier_hash: 'discfile3' }, + }; + const rootState = { + diffs: { diffFiles: [auth2, auth1, auth3] }, // This order is not used! + }; + + delete auth1.order; + delete auth2.order; + delete auth3.order; + + expect(getters.unresolvedDiscussionsIdsByDiff(state, localGetters, rootState)).toEqual([ + 'abc3', + 'abc1', + 'abc2', + ]); + }); + it('should return empty array if all discussions have been resolved', () => { const localGetters = { allResolvableDiscussions: [resolvedDiscussion1], }; + const rootState = createRootState(); - expect(getters.unresolvedDiscussionsIdsByDiff(state, localGetters)).toEqual([]); + expect(getters.unresolvedDiscussionsIdsByDiff(state, localGetters, rootState)).toEqual([]); }); }); diff --git a/spec/lib/bulk_imports/projects/pipelines/project_attributes_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/project_attributes_pipeline_spec.rb index df7ff5b8062..6e1fd252c25 100644 --- a/spec/lib/bulk_imports/projects/pipelines/project_attributes_pipeline_spec.rb +++ b/spec/lib/bulk_imports/projects/pipelines/project_attributes_pipeline_spec.rb @@ -23,7 +23,6 @@ RSpec.describe BulkImports::Projects::Pipelines::ProjectAttributesPipeline do 'merge_requests_ff_only_enabled' => true, 'issues_template' => 'test', 'shared_runners_enabled' => true, - 'build_coverage_regex' => 'build_coverage_regex', 'build_allow_git_fetch' => true, 'build_timeout' => 3600, 'pending_delete' => false, diff --git a/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb b/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb index 200898f8f03..5cff10cfccd 100644 --- a/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb +++ b/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb @@ -290,25 +290,6 @@ RSpec.describe Gitlab::GithubImport::ParallelScheduling do importer.parallel_import end end - - context 'when distribute_github_parallel_import feature flag is disabled' do - before do - stub_feature_flags(distribute_github_parallel_import: false) - end - - it 'imports data in parallel' do - expect(importer) - .to receive(:each_object_to_import) - .and_yield(object) - - expect(worker_class) - .to receive(:perform_async) - .with(project.id, { title: 'Foo' }, an_instance_of(String)) - - expect(importer.parallel_import) - .to be_an_instance_of(Gitlab::JobWaiter) - end - end end describe '#each_object_to_import' do diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index e06fcb0cd3f..06d19835304 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -521,7 +521,6 @@ Project: - star_count - ci_id - shared_runners_enabled -- build_coverage_regex - build_allow_git_fetchs - build_timeout - pending_delete diff --git a/spec/models/alert_management/metric_image_spec.rb b/spec/models/alert_management/metric_image_spec.rb index dedbd6e501e..ca910474423 100644 --- a/spec/models/alert_management/metric_image_spec.rb +++ b/spec/models/alert_management/metric_image_spec.rb @@ -15,12 +15,4 @@ RSpec.describe AlertManagement::MetricImage do it { is_expected.to validate_length_of(:url).is_at_most(255) } it { is_expected.to validate_length_of(:url_text).is_at_most(128) } end - - describe '.available_for?' do - subject { described_class.available_for?(issue.project) } - - let_it_be_with_refind(:issue) { create(:issue) } - - it { is_expected.to eq(true) } - end end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 3409b43347e..384d1078893 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -1101,36 +1101,6 @@ RSpec.describe Ci::Build do end end - describe '#coverage_regex' do - subject { build.coverage_regex } - - context 'when project has build_coverage_regex set' do - let(:project_regex) { '\(\d+\.\d+\) covered' } - - before do - project.update_column(:build_coverage_regex, project_regex) - end - - context 'and coverage_regex attribute is not set' do - it { is_expected.to eq(project_regex) } - end - - context 'but coverage_regex attribute is also set' do - let(:build_regex) { 'Code coverage: \d+\.\d+' } - - before do - build.coverage_regex = build_regex - end - - it { is_expected.to eq(build_regex) } - end - end - - context 'when neither project nor build has coverage regex set' do - it { is_expected.to be_nil } - end - end - describe '#update_coverage' do context "regarding coverage_regex's value," do before do diff --git a/spec/requests/api/import_bitbucket_server_spec.rb b/spec/requests/api/import_bitbucket_server_spec.rb index 970416c7444..8ab41f49549 100644 --- a/spec/requests/api/import_bitbucket_server_spec.rb +++ b/spec/requests/api/import_bitbucket_server_spec.rb @@ -9,7 +9,15 @@ RSpec.describe API::ImportBitbucketServer do let(:secret) { "sekrettt" } let(:project_key) { 'TES' } let(:repo_slug) { 'vim' } - let(:repo) { { name: 'vim' } } + let(:repo) do + double('repo', + name: repo_slug, + browse_url: "#{base_uri}/projects/#{project_key}/repos/#{repo_slug}/browse", + clone_url: "#{base_uri}/scm/#{project_key}/#{repo_slug}.git", + description: 'provider', + visibility_level: Gitlab::VisibilityLevel::PUBLIC + ) + end describe "POST /import/bitbucket_server" do context 'with no optional parameters' do @@ -20,7 +28,7 @@ RSpec.describe API::ImportBitbucketServer do before do Grape::Endpoint.before_each do |endpoint| allow(endpoint).to receive(:client).and_return(client.as_null_object) - allow(client).to receive(:repo).with(project_key, repo_slug).and_return(double(name: repo_slug)) + allow(client).to receive(:repo).with(project_key, repo_slug).and_return(repo) end end diff --git a/spec/requests/api/import_github_spec.rb b/spec/requests/api/import_github_spec.rb index f0c4fcc4f29..7de72de3940 100644 --- a/spec/requests/api/import_github_spec.rb +++ b/spec/requests/api/import_github_spec.rb @@ -16,7 +16,11 @@ RSpec.describe API::ImportGithub do double('provider', name: 'vim', full_name: "#{provider_username}/vim", - owner: double('provider', login: provider_username) + owner: double('provider', login: provider_username), + description: 'provider', + private: false, + clone_url: 'https://fake.url/vim.git', + has_wiki?: true ) end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 3af205bcd1d..5f623eda28a 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -1180,9 +1180,15 @@ RSpec.describe API::Projects do end it 'disallows creating a project with an import_url when git import source is disabled' do + url = 'http://example.com' stub_application_setting(import_sources: nil) - project_params = { import_url: 'http://example.com', path: 'path-project-Foo', name: 'Foo Project' } + endpoint_url = "#{url}/info/refs?service=git-upload-pack" + stub_full_request(endpoint_url, method: :get).to_return({ status: 200, + body: '001e# service=git-upload-pack', + headers: { 'Content-Type': 'application/x-git-upload-pack-advertisement' } }) + + project_params = { import_url: url, path: 'path-project-Foo', name: 'Foo Project' } expect { post api('/projects', user), params: project_params } .not_to change { Project.count } diff --git a/spec/services/import/bitbucket_server_service_spec.rb b/spec/services/import/bitbucket_server_service_spec.rb index 56d93625b91..0b9fe10e95a 100644 --- a/spec/services/import/bitbucket_server_service_spec.rb +++ b/spec/services/import/bitbucket_server_service_spec.rb @@ -48,6 +48,23 @@ RSpec.describe Import::BitbucketServerService do end end + context 'when import source is disabled' do + before do + stub_application_setting(import_sources: nil) + allow(subject).to receive(:authorized?).and_return(true) + allow(client).to receive(:repo).with(project_key, repo_slug).and_return(double(repo)) + end + + it 'returns forbidden' do + result = subject.execute(credentials) + + expect(result).to include( + status: :error, + http_status: :forbidden + ) + end + end + context 'when user is unauthorized' do before do allow(subject).to receive(:authorized?).and_return(false) diff --git a/spec/services/import/github_service_spec.rb b/spec/services/import/github_service_spec.rb index 58afae1e647..1c26677cfa5 100644 --- a/spec/services/import/github_service_spec.rb +++ b/spec/services/import/github_service_spec.rb @@ -111,6 +111,33 @@ RSpec.describe Import::GithubService do end end + context 'when import source is disabled' do + let(:repository_double) do + double({ + name: 'vim', + description: 'test', + full_name: 'test/vim', + clone_url: 'http://repo.com/repo/repo.git', + private: false, + has_wiki?: false + }) + end + + before do + stub_application_setting(import_sources: nil) + allow(client).to receive(:repository).and_return(repository_double) + end + + it 'returns forbidden' do + result = subject.execute(access_params, :github) + + expect(result).to include( + status: :error, + http_status: :forbidden + ) + end + end + context 'when a blocked/local URL is used as github_hostname' do let(:message) { 'Error while attempting to import from GitHub' } let(:error) { "Invalid URL: #{url}" } diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb index 26242ddaba0..364b0e163f7 100644 --- a/spec/services/projects/create_service_spec.rb +++ b/spec/services/projects/create_service_spec.rb @@ -768,6 +768,21 @@ RSpec.describe Projects::CreateService, '#execute' do create_project(user, opts) end + context 'when import source is disabled' do + before do + stub_application_setting(import_sources: []) + opts[:import_type] = 'git' + end + + it 'raises an error' do + project = create_project(user, opts) + + expect(project).to respond_to(:errors) + expect(project.errors).to have_key(:import_source_disabled) + expect(project.saved?).to be_falsey + end + end + context 'with external authorization enabled' do before do enable_external_authorization_service_check |