diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-22 15:06:20 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-22 15:06:20 +0300 |
commit | b1bcdba89bc241e2cede910f26cf3f5fff8d7901 (patch) | |
tree | 41b45ec9ff1ba56c93b29b00435495e7e5abf02b /spec | |
parent | 30dc5b50569db30fef06cc7ab66e7341161b3c70 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
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' |