summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-05-05 12:10:33 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-05-05 12:10:33 +0000
commit023e050d82ed11d9060ce5bdaec99c3871b98164 (patch)
treeee89e2c83c2771c635a0c1daaa88fcce25f18612 /spec
parent1c568d834d0cbe1bbbf558ac9a45940f6dbda37a (diff)
downloadgitlab-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.rb141
-rw-r--r--spec/features/issues/issue_sidebar_spec.rb53
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb6
-rw-r--r--spec/features/projects/navbar_spec.rb2
-rw-r--r--spec/fixtures/api/schemas/issue.json1
-rw-r--r--spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js17
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/skip_spec.rb24
-rw-r--r--spec/lib/sidebars/projects/menus/analytics_menu_spec.rb120
-rw-r--r--spec/services/ci/create_web_ide_terminal_service_spec.rb17
-rw-r--r--spec/tooling/danger/project_helper_spec.rb2
-rw-r--r--spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb88
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: '&lt;script&gt;alert("xss");&lt;&#x2F;script&gt;') }
- 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: '&lt;script&gt;alert("xss");&lt;&#x2F;script&gt;') }
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