Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-10-22 15:06:20 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2019-10-22 15:06:20 +0300
commitb1bcdba89bc241e2cede910f26cf3f5fff8d7901 (patch)
tree41b45ec9ff1ba56c93b29b00435495e7e5abf02b /spec
parent30dc5b50569db30fef06cc7ab66e7341161b3c70 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb4
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap37
-rw-r--r--spec/frontend/vue_shared/components/split_button_spec.js104
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/metrics_spec.rb46
-rw-r--r--spec/lib/prometheus/pid_provider_spec.rb12
-rw-r--r--spec/migrations/schedule_fix_gitlab_com_pages_access_level_spec.rb143
-rw-r--r--spec/models/merge_request_spec.rb2
-rw-r--r--spec/models/project_services/chat_message/pipeline_message_spec.rb39
-rw-r--r--spec/models/project_services/chat_message/push_message_spec.rb6
9 files changed, 369 insertions, 24 deletions
diff --git a/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb
index 4afbf30ece4..419f741d0ea 100644
--- a/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb
+++ b/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb
@@ -89,12 +89,12 @@ describe 'Merge request > User merges only if pipeline succeeds', :js do
context 'when CI skipped' do
let(:status) { :skipped }
- it 'allows MR to be merged' do
+ it 'does not allow MR to be merged' do
visit project_merge_request_path(project, merge_request)
wait_for_requests
- expect(page).to have_button 'Merge'
+ expect(page).not_to have_button 'Merge'
end
end
end
diff --git a/spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap
new file mode 100644
index 00000000000..95296de5a5d
--- /dev/null
+++ b/spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap
@@ -0,0 +1,37 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`SplitButton renders actionItems 1`] = `
+<gldropdown-stub
+ menu-class="dropdown-menu-selectable "
+ split="true"
+ text="professor"
+>
+ <gldropdownitem-stub
+ active="true"
+ active-class="is-active"
+ >
+ <strong>
+ professor
+ </strong>
+
+ <div>
+ very symphonic
+ </div>
+ </gldropdownitem-stub>
+
+ <gldropdowndivider-stub />
+ <gldropdownitem-stub
+ active-class="is-active"
+ >
+ <strong>
+ captain
+ </strong>
+
+ <div>
+ warp drive
+ </div>
+ </gldropdownitem-stub>
+
+ <!---->
+</gldropdown-stub>
+`;
diff --git a/spec/frontend/vue_shared/components/split_button_spec.js b/spec/frontend/vue_shared/components/split_button_spec.js
new file mode 100644
index 00000000000..520abb02cf7
--- /dev/null
+++ b/spec/frontend/vue_shared/components/split_button_spec.js
@@ -0,0 +1,104 @@
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+
+import SplitButton from '~/vue_shared/components/split_button.vue';
+
+const mockActionItems = [
+ {
+ eventName: 'concert',
+ title: 'professor',
+ description: 'very symphonic',
+ },
+ {
+ eventName: 'apocalypse',
+ title: 'captain',
+ description: 'warp drive',
+ },
+];
+
+describe('SplitButton', () => {
+ let wrapper;
+
+ const createComponent = propsData => {
+ wrapper = shallowMount(SplitButton, {
+ propsData,
+ sync: false,
+ });
+ };
+
+ const findDropdown = () => wrapper.find(GlDropdown);
+ const findDropdownItem = (index = 0) =>
+ findDropdown()
+ .findAll(GlDropdownItem)
+ .at(index);
+ const selectItem = index => {
+ findDropdownItem(index).vm.$emit('click');
+
+ return wrapper.vm.$nextTick();
+ };
+ const clickToggleButton = () => {
+ findDropdown().vm.$emit('click');
+
+ return wrapper.vm.$nextTick();
+ };
+
+ it('fails for empty actionItems', () => {
+ const actionItems = [];
+ expect(() => createComponent({ actionItems })).toThrow();
+ });
+
+ it('fails for single actionItems', () => {
+ const actionItems = [mockActionItems[0]];
+ expect(() => createComponent({ actionItems })).toThrow();
+ });
+
+ it('renders actionItems', () => {
+ createComponent({ actionItems: mockActionItems });
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ describe('toggle button text', () => {
+ beforeEach(() => {
+ createComponent({ actionItems: mockActionItems });
+ });
+
+ it('defaults to first actionItems title', () => {
+ expect(findDropdown().props().text).toBe(mockActionItems[0].title);
+ });
+
+ it('changes to selected actionItems title', () =>
+ selectItem(1).then(() => {
+ expect(findDropdown().props().text).toBe(mockActionItems[1].title);
+ }));
+ });
+
+ describe('emitted event', () => {
+ let eventHandler;
+
+ beforeEach(() => {
+ createComponent({ actionItems: mockActionItems });
+ });
+
+ const addEventHandler = ({ eventName }) => {
+ eventHandler = jest.fn();
+ wrapper.vm.$once(eventName, () => eventHandler());
+ };
+
+ it('defaults to first actionItems event', () => {
+ addEventHandler(mockActionItems[0]);
+
+ return clickToggleButton().then(() => {
+ expect(eventHandler).toHaveBeenCalled();
+ });
+ });
+
+ it('changes to selected actionItems event', () =>
+ selectItem(1)
+ .then(() => addEventHandler(mockActionItems[1]))
+ .then(clickToggleButton)
+ .then(() => {
+ expect(eventHandler).toHaveBeenCalled();
+ }));
+ });
+});
diff --git a/spec/lib/gitlab/sidekiq_middleware/metrics_spec.rb b/spec/lib/gitlab/sidekiq_middleware/metrics_spec.rb
index 806112fcb16..ec4c8560f22 100644
--- a/spec/lib/gitlab/sidekiq_middleware/metrics_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/metrics_spec.rb
@@ -3,25 +3,37 @@
require 'spec_helper'
describe Gitlab::SidekiqMiddleware::Metrics do
- describe '#call' do
- let(:middleware) { described_class.new }
- let(:worker) { double(:worker) }
-
- let(:completion_seconds_metric) { double('completion seconds metric') }
- let(:user_execution_seconds_metric) { double('user execution seconds metric') }
- let(:failed_total_metric) { double('failed total metric') }
- let(:retried_total_metric) { double('retried total metric') }
- let(:running_jobs_metric) { double('running jobs metric') }
+ let(:middleware) { described_class.new }
+
+ let(:concurrency_metric) { double('concurrency metric') }
+ let(:completion_seconds_metric) { double('completion seconds metric') }
+ let(:user_execution_seconds_metric) { double('user execution seconds metric') }
+ let(:failed_total_metric) { double('failed total metric') }
+ let(:retried_total_metric) { double('retried total metric') }
+ let(:running_jobs_metric) { double('running jobs metric') }
+
+ before do
+ allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_completion_seconds, anything, anything, anything).and_return(completion_seconds_metric)
+ allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_cpu_seconds, anything, anything, anything).and_return(user_execution_seconds_metric)
+ allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_jobs_failed_total, anything).and_return(failed_total_metric)
+ allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_jobs_retried_total, anything).and_return(retried_total_metric)
+ allow(Gitlab::Metrics).to receive(:gauge).with(:sidekiq_running_jobs, anything, {}, :all).and_return(running_jobs_metric)
+ allow(Gitlab::Metrics).to receive(:gauge).with(:sidekiq_concurrency, anything, {}, :all).and_return(concurrency_metric)
+
+ allow(running_jobs_metric).to receive(:increment)
+ allow(concurrency_metric).to receive(:set)
+ end
- before do
- allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_completion_seconds, anything, anything, anything).and_return(completion_seconds_metric)
- allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_cpu_seconds, anything, anything, anything).and_return(user_execution_seconds_metric)
- allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_jobs_failed_total, anything).and_return(failed_total_metric)
- allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_jobs_retried_total, anything).and_return(retried_total_metric)
- allow(Gitlab::Metrics).to receive(:gauge).with(:sidekiq_running_jobs, anything, {}, :livesum).and_return(running_jobs_metric)
+ describe '#initialize' do
+ it 'sets general metrics' do
+ expect(concurrency_metric).to receive(:set).with({}, Sidekiq.options[:concurrency].to_i)
- allow(running_jobs_metric).to receive(:increment)
+ middleware
end
+ end
+
+ describe '#call' do
+ let(:worker) { double(:worker) }
it 'yields block' do
allow(completion_seconds_metric).to receive(:observe)
@@ -30,7 +42,7 @@ describe Gitlab::SidekiqMiddleware::Metrics do
expect { |b| middleware.call(worker, {}, :test, &b) }.to yield_control.once
end
- it 'sets metrics' do
+ it 'sets queue specific metrics' do
labels = { queue: :test }
allow(middleware).to receive(:get_thread_cputime).and_return(1, 3)
diff --git a/spec/lib/prometheus/pid_provider_spec.rb b/spec/lib/prometheus/pid_provider_spec.rb
index ba843b27254..6fdc11b14c4 100644
--- a/spec/lib/prometheus/pid_provider_spec.rb
+++ b/spec/lib/prometheus/pid_provider_spec.rb
@@ -18,7 +18,17 @@ describe Prometheus::PidProvider do
expect(Sidekiq).to receive(:server?).and_return(true)
end
- it { is_expected.to eq 'sidekiq' }
+ context 'in a clustered setup' do
+ before do
+ stub_env('SIDEKIQ_WORKER_ID', '123')
+ end
+
+ it { is_expected.to eq 'sidekiq_123' }
+ end
+
+ context 'in a single process setup' do
+ it { is_expected.to eq 'sidekiq' }
+ end
end
context 'when running in Unicorn mode' do
diff --git a/spec/migrations/schedule_fix_gitlab_com_pages_access_level_spec.rb b/spec/migrations/schedule_fix_gitlab_com_pages_access_level_spec.rb
new file mode 100644
index 00000000000..db312242bea
--- /dev/null
+++ b/spec/migrations/schedule_fix_gitlab_com_pages_access_level_spec.rb
@@ -0,0 +1,143 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20191017045817_schedule_fix_gitlab_com_pages_access_level.rb')
+
+describe ScheduleFixGitlabComPagesAccessLevel, :migration, :sidekiq, schema: 2019_10_16_072826 do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:migration_name) { 'FixGitlabComPagesAccessLevel' }
+
+ ProjectClass = ::Gitlab::BackgroundMigration::FixGitlabComPagesAccessLevel::Project
+ FeatureClass = ::Gitlab::BackgroundMigration::FixGitlabComPagesAccessLevel::ProjectFeature
+
+ let(:namespaces_table) { table(:namespaces) }
+ let(:projects_table) { table(:projects) }
+ let(:features_table) { table(:project_features) }
+ let(:pages_metadata_table) { table(:project_pages_metadata) }
+
+ let(:subgroup) do
+ root_group = namespaces_table.create(path: "group", name: "group")
+ namespaces_table.create!(path: "subgroup", name: "group", parent_id: root_group.id)
+ end
+
+ before do
+ allow(::Gitlab).to receive(:com?).and_return true
+ end
+
+ describe 'scheduling migration' do
+ let!(:first_project) { create_project(ProjectClass::PRIVATE, FeatureClass::PRIVATE, false, false, 'first' ) }
+ let!(:last_project) { create_project(ProjectClass::PRIVATE, FeatureClass::PRIVATE, false, false, 'second' ) }
+
+ subject do
+ Sidekiq::Testing.fake! do
+ migrate!
+ end
+ end
+
+ it 'schedules background migrations' do
+ Timecop.freeze do
+ subject
+
+ expect(migration_name).to be_scheduled_delayed_migration(2.minutes, first_project.id, last_project.id)
+ expect(BackgroundMigrationWorker.jobs.size).to eq(1)
+ end
+ end
+
+ context 'not on gitlab.com' do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return false
+ end
+
+ it 'does not schedule background migrations' do
+ Timecop.freeze do
+ subject
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(0)
+ end
+ end
+ end
+ end
+
+ where(:visibility_level, :pages_access_level,
+ :pages_deployed, :ac_is_enabled_in_config,
+ :result_pages_access_level) do
+ # Does not change anything if pages are not deployed
+ ProjectClass::PRIVATE | FeatureClass::DISABLED | false | false | FeatureClass::DISABLED
+ ProjectClass::PRIVATE | FeatureClass::PRIVATE | false | false | FeatureClass::PRIVATE
+ ProjectClass::PRIVATE | FeatureClass::ENABLED | false | false | FeatureClass::ENABLED
+ ProjectClass::PRIVATE | FeatureClass::PUBLIC | false | false | FeatureClass::PUBLIC
+ ProjectClass::INTERNAL | FeatureClass::DISABLED | false | false | FeatureClass::DISABLED
+ ProjectClass::INTERNAL | FeatureClass::PRIVATE | false | false | FeatureClass::PRIVATE
+ ProjectClass::INTERNAL | FeatureClass::ENABLED | false | false | FeatureClass::ENABLED
+ ProjectClass::INTERNAL | FeatureClass::PUBLIC | false | false | FeatureClass::PUBLIC
+ ProjectClass::PUBLIC | FeatureClass::DISABLED | false | false | FeatureClass::DISABLED
+ ProjectClass::PUBLIC | FeatureClass::PRIVATE | false | false | FeatureClass::PRIVATE
+ ProjectClass::PUBLIC | FeatureClass::ENABLED | false | false | FeatureClass::ENABLED
+ ProjectClass::PUBLIC | FeatureClass::PUBLIC | false | false | FeatureClass::PUBLIC
+
+ # Does not change anything if pages are already private in config.json
+ # many of these cases are invalid and will not occur in production
+ ProjectClass::PRIVATE | FeatureClass::DISABLED | true | true | FeatureClass::DISABLED
+ ProjectClass::PRIVATE | FeatureClass::PRIVATE | true | true | FeatureClass::PRIVATE
+ ProjectClass::PRIVATE | FeatureClass::ENABLED | true | true | FeatureClass::ENABLED
+ ProjectClass::PRIVATE | FeatureClass::PUBLIC | true | true | FeatureClass::PUBLIC
+ ProjectClass::INTERNAL | FeatureClass::DISABLED | true | true | FeatureClass::DISABLED
+ ProjectClass::INTERNAL | FeatureClass::PRIVATE | true | true | FeatureClass::PRIVATE
+ ProjectClass::INTERNAL | FeatureClass::ENABLED | true | true | FeatureClass::ENABLED
+ ProjectClass::INTERNAL | FeatureClass::PUBLIC | true | true | FeatureClass::PUBLIC
+ ProjectClass::PUBLIC | FeatureClass::DISABLED | true | true | FeatureClass::DISABLED
+ ProjectClass::PUBLIC | FeatureClass::PRIVATE | true | true | FeatureClass::PRIVATE
+ ProjectClass::PUBLIC | FeatureClass::ENABLED | true | true | FeatureClass::ENABLED
+ ProjectClass::PUBLIC | FeatureClass::PUBLIC | true | true | FeatureClass::PUBLIC
+
+ # when pages are deployed and ac is disabled in config
+ ProjectClass::PRIVATE | FeatureClass::DISABLED | true | false | FeatureClass::DISABLED
+ ProjectClass::PRIVATE | FeatureClass::PRIVATE | true | false | FeatureClass::PUBLIC # need to update
+ ProjectClass::PRIVATE | FeatureClass::ENABLED | true | false | FeatureClass::PUBLIC # invalid state, need to update
+ ProjectClass::PRIVATE | FeatureClass::PUBLIC | true | false | FeatureClass::PUBLIC
+ ProjectClass::INTERNAL | FeatureClass::DISABLED | true | false | FeatureClass::DISABLED
+ ProjectClass::INTERNAL | FeatureClass::PRIVATE | true | false | FeatureClass::PUBLIC # need to update
+ ProjectClass::INTERNAL | FeatureClass::ENABLED | true | false | FeatureClass::PUBLIC # invalid state, need to update
+ ProjectClass::INTERNAL | FeatureClass::PUBLIC | true | false | FeatureClass::PUBLIC
+ ProjectClass::PUBLIC | FeatureClass::DISABLED | true | false | FeatureClass::DISABLED
+ ProjectClass::PUBLIC | FeatureClass::PRIVATE | true | false | FeatureClass::ENABLED # need to update
+ ProjectClass::PUBLIC | FeatureClass::ENABLED | true | false | FeatureClass::ENABLED
+ ProjectClass::PUBLIC | FeatureClass::PUBLIC | true | false | FeatureClass::ENABLED # invalid state, need to update
+ end
+
+ with_them do
+ it 'fixes settings' do
+ perform_enqueued_jobs do
+ project = create_project(visibility_level, pages_access_level, pages_deployed, ac_is_enabled_in_config)
+
+ expect(features_table.find_by(project_id: project.id).pages_access_level).to eq(pages_access_level)
+
+ migrate!
+
+ expect(features_table.find_by(project_id: project.id).pages_access_level).to eq(result_pages_access_level)
+ end
+ end
+ end
+
+ def create_project(visibility_level, pages_access_level, pages_deployed, ac_is_enabled_in_config, path = 'project')
+ project = projects_table.create!(path: path, visibility_level: visibility_level,
+ namespace_id: subgroup.id)
+
+ pages_metadata_table.create!(project_id: project.id, deployed: pages_deployed)
+
+ if pages_deployed
+ FileUtils.mkdir_p(ProjectClass.find(project.id).public_pages_path)
+
+ # write config.json
+ allow(project).to receive(:public_pages?).and_return(!ac_is_enabled_in_config)
+ allow(project).to receive(:pages_domains).and_return([])
+ allow(project).to receive(:project_id).and_return(project.id)
+ allow(project).to receive(:pages_path).and_return(ProjectClass.find(project.id).pages_path)
+ Projects::UpdatePagesConfigurationService.new(project).execute
+ end
+
+ project.update!(visibility_level: visibility_level)
+ features_table.create!(project_id: project.id, pages_access_level: pages_access_level)
+
+ project
+ end
+end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index e2a0acf85f6..5a421cad0f8 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -2267,7 +2267,7 @@ describe MergeRequest do
allow(subject).to receive(:head_pipeline) { pipeline }
end
- it { expect(subject.mergeable_ci_state?).to be_truthy }
+ it { expect(subject.mergeable_ci_state?).to be_falsey }
end
context 'when no pipeline is associated' do
diff --git a/spec/models/project_services/chat_message/pipeline_message_spec.rb b/spec/models/project_services/chat_message/pipeline_message_spec.rb
index cf7c7bf7e61..366ef01924e 100644
--- a/spec/models/project_services/chat_message/pipeline_message_spec.rb
+++ b/spec/models/project_services/chat_message/pipeline_message_spec.rb
@@ -159,6 +159,45 @@ describe ChatMessage::PipelineMessage do
)
end
end
+
+ context 'when ref type is tag' do
+ before do
+ args[:object_attributes][:tag] = true
+ args[:object_attributes][:ref] = 'new_tag'
+ end
+
+ it "returns the pipeline summary in the activity's title" do
+ expect(subject.activity[:title]).to eq(
+ "Pipeline [#123](http://example.gitlab.com/pipelines/123)" \
+ " of tag [new_tag](http://example.gitlab.com/-/tags/new_tag)" \
+ " by The Hacker (hacker) passed"
+ )
+ end
+
+ it "returns the pipeline summary as the attachment's text property" do
+ expect(subject.attachments.first[:text]).to eq(
+ "<http://example.gitlab.com|project_name>:" \
+ " Pipeline <http://example.gitlab.com/pipelines/123|#123>" \
+ " of tag <http://example.gitlab.com/-/tags/new_tag|new_tag>" \
+ " by The Hacker (hacker) passed in 02:00:10"
+ )
+ end
+
+ context 'when rendering markdown' do
+ before do
+ args[:markdown] = true
+ end
+
+ it 'returns the pipeline summary as the attachments in markdown format' do
+ expect(subject.attachments).to eq(
+ "[project_name](http://example.gitlab.com):" \
+ " Pipeline [#123](http://example.gitlab.com/pipelines/123)" \
+ " of tag [new_tag](http://example.gitlab.com/-/tags/new_tag)" \
+ " by The Hacker (hacker) passed in 02:00:10"
+ )
+ end
+ end
+ end
end
context 'when the fancy_pipeline_slack_notifications feature flag is enabled' do
diff --git a/spec/models/project_services/chat_message/push_message_spec.rb b/spec/models/project_services/chat_message/push_message_spec.rb
index 2bde0b93fda..fe0b2fe3440 100644
--- a/spec/models/project_services/chat_message/push_message_spec.rb
+++ b/spec/models/project_services/chat_message/push_message_spec.rb
@@ -96,7 +96,7 @@ describe ChatMessage::PushMessage do
context 'without markdown' do
it 'returns a message regarding pushes' do
expect(subject.pretext).to eq('test.user pushed new tag ' \
- '<http://url.com/commits/new_tag|new_tag> to ' \
+ '<http://url.com/-/tags/new_tag|new_tag> to ' \
'<http://url.com|project_name>')
expect(subject.attachments).to be_empty
end
@@ -109,10 +109,10 @@ describe ChatMessage::PushMessage do
it 'returns a message regarding pushes' do
expect(subject.pretext).to eq(
- 'test.user pushed new tag [new_tag](http://url.com/commits/new_tag) to [project_name](http://url.com)')
+ 'test.user pushed new tag [new_tag](http://url.com/-/tags/new_tag) to [project_name](http://url.com)')
expect(subject.attachments).to be_empty
expect(subject.activity).to eq(
- title: 'test.user pushed new tag [new_tag](http://url.com/commits/new_tag)',
+ title: 'test.user pushed new tag [new_tag](http://url.com/-/tags/new_tag)',
subtitle: 'in [project_name](http://url.com)',
text: '[Compare changes](http://url.com/compare/0000000000000000000000000000000000000000...after)',
image: 'http://someavatar.com'