diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-05 12:10:33 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-05 12:10:33 +0000 |
commit | 023e050d82ed11d9060ce5bdaec99c3871b98164 (patch) | |
tree | ee89e2c83c2771c635a0c1daaa88fcce25f18612 /spec | |
parent | 1c568d834d0cbe1bbbf558ac9a45940f6dbda37a (diff) | |
download | gitlab-ce-023e050d82ed11d9060ce5bdaec99c3871b98164.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r-- | spec/config/inject_enterprise_edition_module_spec.rb | 141 | ||||
-rw-r--r-- | spec/features/issues/issue_sidebar_spec.rb | 53 | ||||
-rw-r--r-- | spec/features/issues/user_edits_issue_spec.rb | 6 | ||||
-rw-r--r-- | spec/features/projects/navbar_spec.rb | 2 | ||||
-rw-r--r-- | spec/fixtures/api/schemas/issue.json | 1 | ||||
-rw-r--r-- | spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js | 17 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/pipeline/chain/skip_spec.rb | 24 | ||||
-rw-r--r-- | spec/lib/sidebars/projects/menus/analytics_menu_spec.rb | 120 | ||||
-rw-r--r-- | spec/services/ci/create_web_ide_terminal_service_spec.rb | 17 | ||||
-rw-r--r-- | spec/tooling/danger/project_helper_spec.rb | 2 | ||||
-rw-r--r-- | spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb | 88 |
11 files changed, 427 insertions, 44 deletions
diff --git a/spec/config/inject_enterprise_edition_module_spec.rb b/spec/config/inject_enterprise_edition_module_spec.rb new file mode 100644 index 00000000000..c65d909cc6b --- /dev/null +++ b/spec/config/inject_enterprise_edition_module_spec.rb @@ -0,0 +1,141 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' + +RSpec.describe InjectEnterpriseEditionModule do + let(:extension_name) { 'FF' } + let(:extension_namespace) { Module.new } + let(:fish_name) { 'Fish' } + let(:fish_class) { Class.new } + let(:fish_extension) { Module.new } + + before do + # Make sure we're not relying on which mode we're running under + allow(Gitlab).to receive(:extensions).and_return([extension_name.downcase]) + + # Test on an imagined extension and imagined class + stub_const(fish_name, fish_class) # Fish + allow(fish_class).to receive(:name).and_return(fish_name) + end + + shared_examples 'expand the extension with' do |method| + context 'when extension namespace is set at top-level' do + before do + stub_const(extension_name, extension_namespace) # FF + extension_namespace.const_set(fish_name, fish_extension) # FF::Fish + end + + it "calls #{method} with the extension module" do + expect(fish_class).to receive(method).with(fish_extension) + + fish_class.__send__("#{method}_if_ee", fish_name) + end + + it "ignores EE prefix and calls #{method} with the extension module" do + expect(fish_class).to receive(method).with(fish_extension) + + fish_class.__send__("#{method}_if_ee", "EE::#{fish_name}") + end + + it "ignores ::EE prefix and calls #{method} with the extension module" do + expect(fish_class).to receive(method).with(fish_extension) + + fish_class.__send__("#{method}_if_ee", "::EE::#{fish_name}") + end + end + + context 'when extension namespace is set at another namespace' do + let(:another_namespace) { Module.new } # QA + + before do + another_namespace.const_set(extension_name, extension_namespace) # QA::FF + extension_namespace.const_set(fish_name, fish_extension) # QA::FF::Fish + end + + it "calls #{method} with the extension module from the additional namespace" do + expect(fish_class).to receive(method).with(fish_extension) + + fish_class.__send__("#{method}_if_ee", fish_name, namespace: another_namespace) + end + end + + context 'when extension namespace exists but not the extension' do + before do + stub_const(extension_name, extension_namespace) # FF + end + + it "does not call #{method}" do + expect(fish_class).not_to receive(method).with(fish_extension) + + fish_class.__send__("#{method}_if_ee", fish_name) + end + end + + context 'when extension namespace does not exist' do + it "does not call #{method}" do + expect(fish_class).not_to receive(method).with(fish_extension) + + fish_class.__send__("#{method}_if_ee", fish_name) + end + end + end + + shared_examples 'expand the assumed extension with' do |method| + context 'when extension namespace is set at top-level' do + before do + stub_const(extension_name, extension_namespace) # FF + extension_namespace.const_set(fish_name, fish_extension) # FF::Fish + end + + it "calls #{method} with the extension module" do + expect(fish_class).to receive(method).with(fish_extension) + + fish_class.__send__("#{method}_mod") + end + end + + context 'when extension namespace exists but not the extension' do + before do + stub_const(extension_name, extension_namespace) # FF + end + + it "does not call #{method}" do + expect(fish_class).not_to receive(method).with(fish_extension) + + fish_class.__send__("#{method}_mod") + end + end + + context 'when extension namespace does not exist' do + it "does not call #{method}" do + expect(fish_class).not_to receive(method).with(fish_extension) + + fish_class.__send__("#{method}_mod") + end + end + end + + describe '#prepend_if_ee' do + it_behaves_like 'expand the extension with', :prepend + end + + describe '#extend_if_ee' do + it_behaves_like 'expand the extension with', :extend + end + + describe '#include_if_ee' do + it_behaves_like 'expand the extension with', :include + end + + describe '#prepend_mod' do + it_behaves_like 'expand the assumed extension with', :prepend + end + + describe '#extend_mod' do + it_behaves_like 'expand the assumed extension with', :extend + end + + describe '#include_mod' do + it_behaves_like 'expand the assumed extension with', :include + end +end diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb index da9def60ff9..d147476f1ab 100644 --- a/spec/features/issues/issue_sidebar_spec.rb +++ b/spec/features/issues/issue_sidebar_spec.rb @@ -5,17 +5,14 @@ require 'spec_helper' RSpec.describe 'Issue Sidebar' do include MobileHelpers - let(:group) { create(:group, :nested) } - let(:project) { create(:project, :public, namespace: group) } - let!(:user) { create(:user) } - let!(:label) { create(:label, project: project, title: 'bug') } - let(:issue) { create(:labeled_issue, project: project, labels: [label]) } - let!(:xss_label) { create(:label, project: project, title: '<script>alert("xss");</script>') } - let!(:milestone_expired) { create(:milestone, project: project, due_date: 5.days.ago) } - let!(:milestone_no_duedate) { create(:milestone, project: project, title: 'Foo - No due date') } - let!(:milestone1) { create(:milestone, project: project, title: 'Milestone-1', due_date: 20.days.from_now) } - let!(:milestone2) { create(:milestone, project: project, title: 'Milestone-2', due_date: 15.days.from_now) } - let!(:milestone3) { create(:milestone, project: project, title: 'Milestone-3', due_date: 10.days.from_now) } + let_it_be(:group) { create(:group, :nested) } + let_it_be(:project) { create(:project, :public, namespace: group) } + let_it_be(:user) { create(:user) } + let_it_be(:label) { create(:label, project: project, title: 'bug') } + let_it_be(:issue) { create(:labeled_issue, project: project, labels: [label]) } + let_it_be(:mock_date) { Date.today.at_beginning_of_month + 2.days } + let_it_be(:issue_with_due_date) { create(:issue, project: project, due_date: mock_date) } + let_it_be(:xss_label) { create(:label, project: project, title: '<script>alert("xss");</script>') } before do stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab") @@ -204,7 +201,31 @@ RSpec.describe 'Issue Sidebar' do end end - context 'as a allowed user' do + context 'due date widget', :js do + let(:due_date_value) { find('[data-testid="due-date"] [data-testid="sidebar-date-value"]') } + + context 'when no due date exists' do + before do + visit_issue(project, issue) + end + + it "displays 'None'" do + expect(due_date_value.text).to have_content 'None' + end + end + + context 'when due date exists' do + before do + visit_issue(project, issue_with_due_date) + end + + it "displays the due date" do + expect(due_date_value.text).to have_content mock_date.strftime('%b %-d, %Y') + end + end + end + + context 'as an allowed user' do before do project.add_developer(user) visit_issue(project, issue) @@ -238,6 +259,12 @@ RSpec.describe 'Issue Sidebar' do end context 'editing issue milestone', :js do + let_it_be(:milestone_expired) { create(:milestone, project: project, due_date: 5.days.ago) } + let_it_be(:milestone_no_duedate) { create(:milestone, project: project, title: 'Foo - No due date') } + let_it_be(:milestone1) { create(:milestone, project: project, title: 'Milestone-1', due_date: 20.days.from_now) } + let_it_be(:milestone2) { create(:milestone, project: project, title: 'Milestone-2', due_date: 15.days.from_now) } + let_it_be(:milestone3) { create(:milestone, project: project, title: 'Milestone-3', due_date: 10.days.from_now) } + before do page.within('.block.milestone > .title') do click_on 'Edit' @@ -426,6 +453,8 @@ RSpec.describe 'Issue Sidebar' do def visit_issue(project, issue) visit project_issue_path(project, issue) + + wait_for_requests end def open_issue_sidebar diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb index be2955527be..cb4a5a32762 100644 --- a/spec/features/issues/user_edits_issue_spec.rb +++ b/spec/features/issues/user_edits_issue_spec.rb @@ -406,6 +406,12 @@ RSpec.describe "Issues > User edits issue", :js do end context 'update due date' do + before do + # Due date widget uses GraphQL and needs to wait for requests to come back + # The date picker won't be rendered before requests complete + wait_for_requests + end + it 'adds due date to issue' do date = Date.today.at_beginning_of_month + 2.days diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb index 9bb8f0b2f21..5ab75a6b914 100644 --- a/spec/features/projects/navbar_spec.rb +++ b/spec/features/projects/navbar_spec.rb @@ -34,7 +34,7 @@ RSpec.describe 'Project navbar' do it 'redirects to value stream when Analytics item is clicked' do page.within('.sidebar-top-level-items') do - find('[data-qa-selector=analytics_anchor]').click + find('.shortcuts-analytics').click end wait_for_requests diff --git a/spec/fixtures/api/schemas/issue.json b/spec/fixtures/api/schemas/issue.json index bb6e5c0de10..aefba89d9e2 100644 --- a/spec/fixtures/api/schemas/issue.json +++ b/spec/fixtures/api/schemas/issue.json @@ -14,6 +14,7 @@ "due_date": { "type": ["string", "null"] }, "relative_position": { "type": ["integer", "null"] }, "time_estimate": { "type": "integer" }, + "type": { "type": "string", "enum": ["ISSUE", "INCIDENT", "TEST_CASE", "REQUIREMENT"] }, "issue_sidebar_endpoint": { "type": "string" }, "toggle_subscription_endpoint": { "type": "string" }, "assignable_labels_endpoint": { "type": "string" }, diff --git a/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js b/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js index 273235fe197..91cbcc6cc27 100644 --- a/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js +++ b/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js @@ -80,6 +80,12 @@ describe('Sidebar date Widget', () => { expect(findPopoverIcon().exists()).toBe(false); }); + it('does not render GlDatePicker', () => { + createComponent(); + + expect(findDatePicker().exists()).toBe(false); + }); + describe('when issuable has no due date', () => { beforeEach(async () => { createComponent({ @@ -114,8 +120,15 @@ describe('Sidebar date Widget', () => { }); it('uses a correct prop to set the initial date for GlDatePicker', () => { - expect(findDatePicker().props('value')).toBe(null); - expect(findDatePicker().props('defaultDate')).toEqual(wrapper.vm.parsedDate); + expect(findDatePicker().props()).toMatchObject({ + value: null, + autocomplete: 'off', + defaultDate: expect.any(Object), + }); + }); + + it('renders GlDatePicker', async () => { + expect(findDatePicker().exists()).toBe(true); }); }); diff --git a/spec/lib/gitlab/ci/pipeline/chain/skip_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/skip_spec.rb index e4768f2ef0d..ae427eaf403 100644 --- a/spec/lib/gitlab/ci/pipeline/chain/skip_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/chain/skip_spec.rb @@ -21,17 +21,37 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Skip do before do allow(pipeline).to receive(:git_commit_message) .and_return('commit message [ci skip]') - - step.perform! end it 'breaks the chain' do + step.perform! + expect(step.break?).to be true end it 'skips the pipeline' do + step.perform! + expect(pipeline.reload).to be_skipped end + + it 'calls ensure_project_iid explicitly' do + expect(pipeline).to receive(:ensure_project_iid!) + + step.perform! + end + + context 'when the ci_pipeline_ensure_iid_on_save feature flag is off' do + before do + stub_feature_flags(ci_pipeline_ensure_iid_on_skip: false) + end + + it 'does not call ensure_project_iid explicitly' do + expect(pipeline).not_to receive(:ensure_project_iid!) + + step.perform! + end + end end context 'when pipeline has not been skipped' do diff --git a/spec/lib/sidebars/projects/menus/analytics_menu_spec.rb b/spec/lib/sidebars/projects/menus/analytics_menu_spec.rb new file mode 100644 index 00000000000..c109631fabe --- /dev/null +++ b/spec/lib/sidebars/projects/menus/analytics_menu_spec.rb @@ -0,0 +1,120 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::Projects::Menus::AnalyticsMenu do + let_it_be(:project) { create(:project, :repository) } + + let(:user) { project.owner } + let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, current_ref: project.repository.root_ref) } + + subject { described_class.new(context) } + + describe '#render?' do + context 'whe user cannot read analytics' do + let(:user) { nil } + + it 'returns false' do + expect(subject.render?).to be false + end + end + + context 'whe user can read analytics' do + it 'returns true' do + expect(subject.render?).to be true + end + + context 'when menu does not have any menu items' do + it 'returns false' do + allow(subject).to receive(:has_items?).and_return(false) + + expect(subject.render?).to be false + end + end + + context 'when menu has menu items' do + it 'returns true' do + expect(subject.render?).to be true + end + end + end + end + + describe '#link' do + it 'returns link to the value stream page' do + expect(subject.link).to include('/-/value_stream_analytics') + end + + context 'when Value Stream is not visible' do + it 'returns link to the the first visible menu item' do + allow(subject).to receive(:cycle_analytics_menu_item).and_return(nil) + + expect(subject.link).to eq subject.items.first.link + end + end + end + + describe 'Menu items' do + subject { described_class.new(context).items.index { |e| e.item_id == item_id } } + + describe 'CI/CD' do + let(:item_id) { :ci_cd_analytics } + + specify { is_expected.not_to be_nil } + + describe 'when the project repository is empty' do + before do + allow(project).to receive(:empty_repo?).and_return(true) + end + + specify { is_expected.to be_nil } + end + + describe 'when builds access level is DISABLED' do + before do + project.project_feature.update!(builds_access_level: Featurable::DISABLED) + end + + specify { is_expected.to be_nil } + end + + describe 'when the user does not have access' do + let(:user) { nil } + + specify { is_expected.to be_nil } + end + end + + describe 'Repository' do + let(:item_id) { :repository_analytics } + + specify { is_expected.not_to be_nil } + + describe 'when the project repository is empty' do + before do + allow(project).to receive(:empty_repo?).and_return(true) + end + + specify { is_expected.to be_nil } + end + + describe 'when the user does not have access' do + let(:user) { nil } + + specify { is_expected.to be_nil } + end + end + + describe 'Value Stream' do + let(:item_id) { :cycle_analytics } + + specify { is_expected.not_to be_nil } + + describe 'when the user does not have access' do + let(:user) { nil } + + specify { is_expected.to be_nil } + end + end + end +end diff --git a/spec/services/ci/create_web_ide_terminal_service_spec.rb b/spec/services/ci/create_web_ide_terminal_service_spec.rb index e8a549650a6..a0974247918 100644 --- a/spec/services/ci/create_web_ide_terminal_service_spec.rb +++ b/spec/services/ci/create_web_ide_terminal_service_spec.rb @@ -21,6 +21,23 @@ RSpec.describe Ci::CreateWebIdeTerminalService do expect(subject[:pipeline].stages.count).to eq(1) expect(subject[:pipeline].builds.count).to eq(1) end + + it 'calls ensure_project_iid explicitly' do + expect_next_instance_of(Ci::Pipeline) do |instance| + expect(instance).to receive(:ensure_project_iid!).twice + end + subject + end + + context 'when the ci_pipeline_ensure_iid_on_save feature flag is off' do + it 'does not call ensure_project_iid explicitly' do + stub_feature_flags(ci_pipeline_ensure_iid_on_save: false) + expect_next_instance_of(Ci::Pipeline) do |instance| + expect(instance).to receive(:ensure_project_iid!).once + end + subject + end + end end before do diff --git a/spec/tooling/danger/project_helper_spec.rb b/spec/tooling/danger/project_helper_spec.rb index 5d106f08402..6bec176b39b 100644 --- a/spec/tooling/danger/project_helper_spec.rb +++ b/spec/tooling/danger/project_helper_spec.rb @@ -220,7 +220,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do describe '.local_warning_message' do it 'returns an informational message with rules that can run' do - expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changelog, changes_size, commit_messages, database, datateam, documentation, duplicate_yarn_dependencies, eslint, karma, pajamas, pipeline, prettier, product_intelligence, utility_css') + expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changelog, commit_messages, database, datateam, documentation, duplicate_yarn_dependencies, eslint, karma, pajamas, pipeline, prettier, product_intelligence, utility_css') end end diff --git a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb index b86164a6639..d5320b2d044 100644 --- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb +++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb @@ -650,6 +650,68 @@ RSpec.describe 'layouts/nav/sidebar/_project' do end end + describe 'Analytics' do + it 'top level navigation link is visible points to the value stream page' do + render + + expect(rendered).to have_link('Analytics', href: project_cycle_analytics_path(project)) + end + + describe 'CI/CD' do + it 'has a link to the CI/CD analytics page' do + render + + expect(rendered).to have_link('CI/CD', href: charts_project_pipelines_path(project)) + end + + context 'when user does not have access' do + let(:user) { nil } + + it 'does not have a link to the CI/CD analytics page' do + render + + expect(rendered).not_to have_link('CI/CD', href: charts_project_pipelines_path(project)) + end + end + end + + describe 'Repository' do + it 'has a link to the repository analytics page' do + render + + expect(rendered).to have_link('Repository', href: charts_project_graph_path(project, 'master')) + end + + context 'when user does not have access' do + let(:user) { nil } + + it 'does not have a link to the repository analytics page' do + render + + expect(rendered).not_to have_link('Repository', href: charts_project_graph_path(project, 'master')) + end + end + end + + describe 'Value Stream' do + it 'has a link to the value stream page' do + render + + expect(rendered).to have_link('Value Stream', href: project_cycle_analytics_path(project)) + end + + context 'when user does not have access' do + let(:user) { nil } + + it 'does not have a link to the value stream page' do + render + + expect(rendered).not_to have_link('Value Stream', href: project_cycle_analytics_path(project)) + end + end + end + end + describe 'wiki entry tab' do let(:can_read_wiki) { true } @@ -736,32 +798,6 @@ RSpec.describe 'layouts/nav/sidebar/_project' do end end - describe 'value stream analytics entry' do - let(:read_cycle_analytics) { true } - - before do - allow(view).to receive(:can?).with(user, :read_cycle_analytics, project).and_return(read_cycle_analytics) - end - - describe 'when value stream analytics is enabled' do - it 'shows the value stream analytics entry' do - render - - expect(rendered).to have_link('Value Stream', href: project_cycle_analytics_path(project)) - end - end - - describe 'when value stream analytics is disabled' do - let(:read_cycle_analytics) { false } - - it 'does not show the value stream analytics entry' do - render - - expect(rendered).not_to have_link('Value Stream', href: project_cycle_analytics_path(project)) - end - end - end - describe 'operations settings tab' do describe 'archive projects' do before do |