diff options
Diffstat (limited to 'spec')
554 files changed, 6247 insertions, 960 deletions
diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb index 8decd8f1382..df6a6e00f73 100644 --- a/spec/controllers/projects/graphs_controller_spec.rb +++ b/spec/controllers/projects/graphs_controller_spec.rb @@ -27,6 +27,7 @@ describe Projects::GraphsController do describe 'charts' do context 'when languages were previously detected' do + let(:project) { create(:project, :repository, detected_repository_languages: true) } let!(:repository_language) { create(:repository_language, project: project) } it 'sets the languages properly' do diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 79f97aa4170..c8fa93a74ee 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -86,6 +86,10 @@ describe Projects::MergeRequestsController do end describe 'as json' do + before do + expect(::Gitlab::GitalyClient).to receive(:allow_ref_name_caching).and_call_original + end + context 'with basic serializer param' do it 'renders basic MR entity as json' do go(serializer: 'basic', format: :json) diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index ece8532cb84..b64ae552efc 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -28,6 +28,8 @@ describe Projects::PipelinesController do end it 'returns serialized pipelines', :request_store do + expect(::Gitlab::GitalyClient).to receive(:allow_ref_name_caching).and_call_original + queries = ActiveRecord::QueryRecorder.new do get_pipelines_index_json end diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index a1662658ade..356d606d5c5 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -369,6 +369,23 @@ describe ProjectsController do end end + it 'does not update namespace' do + controller.instance_variable_set(:@project, project) + + params = { + namespace_id: 'test' + } + + expect do + put :update, + params: { + namespace_id: project.namespace, + id: project.id, + project: params + } + end.not_to change { project.namespace.reload } + end + def update_project(**parameters) put :update, params: { diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb index 897b4411055..40c3a6d90d0 100644 --- a/spec/db/schema_spec.rb +++ b/spec/db/schema_spec.rb @@ -25,12 +25,12 @@ describe 'Database schema' do events: %w[target_id], forked_project_links: %w[forked_from_project_id], identities: %w[user_id], - issues: %w[last_edited_by_id], + issues: %w[last_edited_by_id state_id], keys: %w[user_id], label_links: %w[target_id], lfs_objects_projects: %w[lfs_object_id project_id], members: %w[source_id created_by_id], - merge_requests: %w[last_edited_by_id], + merge_requests: %w[last_edited_by_id state_id], namespaces: %w[owner_id parent_id], notes: %w[author_id commit_id noteable_id updated_by_id resolved_by_id discussion_id], notification_settings: %w[source_id], diff --git a/spec/factories/clusters/clusters.rb b/spec/factories/clusters/clusters.rb index 1cc3c0e03d8..97405ec7c58 100644 --- a/spec/factories/clusters/clusters.rb +++ b/spec/factories/clusters/clusters.rb @@ -3,6 +3,7 @@ FactoryBot.define do user name 'test-cluster' cluster_type :project_type + managed true trait :instance do cluster_type { Clusters::Cluster.cluster_types[:instance_type] } @@ -63,5 +64,9 @@ FactoryBot.define do trait :with_domain do domain 'example.com' end + + trait :user_managed do + managed false + end end end diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb index a1809a26265..abf0e6bccb7 100644 --- a/spec/factories/merge_requests.rb +++ b/spec/factories/merge_requests.rb @@ -117,9 +117,20 @@ FactoryBot.define do end end + trait :with_legacy_detached_merge_request_pipeline do + after(:create) do |merge_request| + merge_request.merge_request_pipelines << create(:ci_pipeline, + source: :merge_request_event, + merge_request: merge_request, + project: merge_request.source_project, + ref: merge_request.source_branch, + sha: merge_request.source_branch_sha) + end + end + trait :with_detached_merge_request_pipeline do - after(:build) do |merge_request| - merge_request.merge_request_pipelines << build(:ci_pipeline, + after(:create) do |merge_request| + merge_request.merge_request_pipelines << create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, project: merge_request.source_project, @@ -135,7 +146,7 @@ FactoryBot.define do target_sha { target_branch_sha } end - after(:build) do |merge_request, evaluator| + after(:create) do |merge_request, evaluator| merge_request.merge_request_pipelines << create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, diff --git a/spec/features/clusters/cluster_detail_page_spec.rb b/spec/features/clusters/cluster_detail_page_spec.rb index b9fc52d0dce..d2e46d15730 100644 --- a/spec/features/clusters/cluster_detail_page_spec.rb +++ b/spec/features/clusters/cluster_detail_page_spec.rb @@ -53,12 +53,80 @@ describe 'Clusterable > Show page' do end end + shared_examples 'editing a GCP cluster' do + before do + clusterable.add_maintainer(current_user) + visit cluster_path + end + + it 'is not able to edit the name, API url, CA certificate nor token' do + within('#js-cluster-details') do + cluster_name_field = find('.cluster-name') + api_url_field = find('#cluster_platform_kubernetes_attributes_api_url') + ca_certificate_field = find('#cluster_platform_kubernetes_attributes_ca_cert') + token_field = find('#cluster_platform_kubernetes_attributes_token') + + expect(cluster_name_field).to be_readonly + expect(api_url_field).to be_readonly + expect(ca_certificate_field).to be_readonly + expect(token_field).to be_readonly + end + end + + it 'displays GKE information' do + within('#advanced-settings-section') do + expect(page).to have_content('Google Kubernetes Engine') + expect(page).to have_content('Manage your Kubernetes cluster by visiting') + end + end + end + + shared_examples 'editing a user-provided cluster' do + before do + clusterable.add_maintainer(current_user) + visit cluster_path + end + + it 'is able to edit the name, API url, CA certificate and token' do + within('#js-cluster-details') do + cluster_name_field = find('#cluster_name') + api_url_field = find('#cluster_platform_kubernetes_attributes_api_url') + ca_certificate_field = find('#cluster_platform_kubernetes_attributes_ca_cert') + token_field = find('#cluster_platform_kubernetes_attributes_token') + + expect(cluster_name_field).not_to be_readonly + expect(api_url_field).not_to be_readonly + expect(ca_certificate_field).not_to be_readonly + expect(token_field).not_to be_readonly + end + end + + it 'does not display GKE information' do + within('#advanced-settings-section') do + expect(page).not_to have_content('Google Kubernetes Engine') + expect(page).not_to have_content('Manage your Kubernetes cluster by visiting') + end + end + end + context 'when clusterable is a project' do it_behaves_like 'editing domain' do let(:clusterable) { create(:project) } let(:cluster) { create(:cluster, :provided_by_gcp, :project, projects: [clusterable]) } let(:cluster_path) { project_cluster_path(clusterable, cluster) } end + + it_behaves_like 'editing a GCP cluster' do + let(:clusterable) { create(:project) } + let(:cluster) { create(:cluster, :provided_by_gcp, :project, projects: [clusterable]) } + let(:cluster_path) { project_cluster_path(clusterable, cluster) } + end + + it_behaves_like 'editing a user-provided cluster' do + let(:clusterable) { create(:project) } + let(:cluster) { create(:cluster, :provided_by_user, :project, projects: [clusterable]) } + let(:cluster_path) { project_cluster_path(clusterable, cluster) } + end end context 'when clusterable is a group' do @@ -67,5 +135,17 @@ describe 'Clusterable > Show page' do let(:cluster) { create(:cluster, :provided_by_gcp, :group, groups: [clusterable]) } let(:cluster_path) { group_cluster_path(clusterable, cluster) } end + + it_behaves_like 'editing a GCP cluster' do + let(:clusterable) { create(:group) } + let(:cluster) { create(:cluster, :provided_by_gcp, :group, groups: [clusterable]) } + let(:cluster_path) { group_cluster_path(clusterable, cluster) } + end + + it_behaves_like 'editing a user-provided cluster' do + let(:clusterable) { create(:group) } + let(:cluster) { create(:cluster, :provided_by_user, :group, groups: [clusterable]) } + let(:cluster_path) { group_cluster_path(clusterable, cluster) } + end end end diff --git a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb index 693ad89069c..0a006011c89 100644 --- a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb +++ b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb @@ -1,6 +1,7 @@ require 'rails_helper' describe 'User creates branch and merge request on issue page', :js do + let(:membership_level) { :developer } let(:user) { create(:user) } let!(:project) { create(:project, :repository) } let(:issue) { create(:issue, project: project, title: 'Cherry-Coloured Funk') } @@ -17,7 +18,7 @@ describe 'User creates branch and merge request on issue page', :js do context 'when signed in' do before do - project.add_developer(user) + project.add_user(user, membership_level) sign_in(user) end @@ -167,6 +168,39 @@ describe 'User creates branch and merge request on issue page', :js do expect(page).not_to have_css('.create-mr-dropdown-wrap') end end + + context 'when related branch exists' do + let!(:project) { create(:project, :repository, :private) } + let(:branch_name) { "#{issue.iid}-foo" } + + before do + project.repository.create_branch(branch_name, 'master') + + visit project_issue_path(project, issue) + end + + context 'when user is developer' do + it 'shows related branches' do + expect(page).to have_css('#related-branches') + + wait_for_requests + + expect(page).to have_content(branch_name) + end + end + + context 'when user is guest' do + let(:membership_level) { :guest } + + it 'does not show related branches' do + expect(page).not_to have_css('#related-branches') + + wait_for_requests + + expect(page).not_to have_content(branch_name) + end + end + end end private diff --git a/spec/features/issues/user_uses_quick_actions_spec.rb b/spec/features/issues/user_uses_quick_actions_spec.rb index b5e7c3954e2..362f8a468ec 100644 --- a/spec/features/issues/user_uses_quick_actions_spec.rb +++ b/spec/features/issues/user_uses_quick_actions_spec.rb @@ -3,8 +3,41 @@ require 'rails_helper' describe 'Issues > User uses quick actions', :js do include Spec::Support::Helpers::Features::NotesHelpers - it_behaves_like 'issuable record that supports quick actions in its description and notes', :issue do + context "issuable common quick actions" do + let(:new_url_opts) { {} } + let(:maintainer) { create(:user) } + let(:project) { create(:project, :public) } + let!(:label_bug) { create(:label, project: project, title: 'bug') } + let!(:label_feature) { create(:label, project: project, title: 'feature') } + let!(:milestone) { create(:milestone, project: project, title: 'ASAP') } let(:issuable) { create(:issue, project: project) } + let(:source_issuable) { create(:issue, project: project, milestone: milestone, labels: [label_bug, label_feature])} + + it_behaves_like 'assign quick action', :issue + it_behaves_like 'unassign quick action', :issue + it_behaves_like 'close quick action', :issue + it_behaves_like 'reopen quick action', :issue + it_behaves_like 'title quick action', :issue + it_behaves_like 'todo quick action', :issue + it_behaves_like 'done quick action', :issue + it_behaves_like 'subscribe quick action', :issue + it_behaves_like 'unsubscribe quick action', :issue + it_behaves_like 'lock quick action', :issue + it_behaves_like 'unlock quick action', :issue + it_behaves_like 'milestone quick action', :issue + it_behaves_like 'remove_milestone quick action', :issue + it_behaves_like 'label quick action', :issue + it_behaves_like 'unlabel quick action', :issue + it_behaves_like 'relabel quick action', :issue + it_behaves_like 'award quick action', :issue + it_behaves_like 'estimate quick action', :issue + it_behaves_like 'remove_estimate quick action', :issue + it_behaves_like 'spend quick action', :issue + it_behaves_like 'remove_time_spent quick action', :issue + it_behaves_like 'shrug quick action', :issue + it_behaves_like 'tableflip quick action', :issue + it_behaves_like 'copy_metadata quick action', :issue + it_behaves_like 'issuable time tracker', :issue end describe 'issue-only commands' do @@ -15,37 +48,17 @@ describe 'Issues > User uses quick actions', :js do project.add_maintainer(user) sign_in(user) visit project_issue_path(project, issue) + wait_for_all_requests end after do wait_for_requests end - describe 'time tracking' do - let(:issue) { create(:issue, project: project) } - - before do - visit project_issue_path(project, issue) - end - - it_behaves_like 'issuable time tracker' - end - describe 'adding a due date from note' do let(:issue) { create(:issue, project: project) } - context 'when the current user can update the due date' do - it 'does not create a note, and sets the due date accordingly' do - add_note("/due 2016-08-28") - - expect(page).not_to have_content '/due 2016-08-28' - expect(page).to have_content 'Commands applied' - - issue.reload - - expect(issue.due_date).to eq Date.new(2016, 8, 28) - end - end + it_behaves_like 'due quick action available and date can be added' context 'when the current user cannot update the due date' do let(:guest) { create(:user) } @@ -56,35 +69,14 @@ describe 'Issues > User uses quick actions', :js do visit project_issue_path(project, issue) end - it 'does not create a note, and sets the due date accordingly' do - add_note("/due 2016-08-28") - - expect(page).not_to have_content 'Commands applied' - - issue.reload - - expect(issue.due_date).to be_nil - end + it_behaves_like 'due quick action not available' end end describe 'removing a due date from note' do let(:issue) { create(:issue, project: project, due_date: Date.new(2016, 8, 28)) } - context 'when the current user can update the due date' do - it 'does not create a note, and removes the due date accordingly' do - expect(issue.due_date).to eq Date.new(2016, 8, 28) - - add_note("/remove_due_date") - - expect(page).not_to have_content '/remove_due_date' - expect(page).to have_content 'Commands applied' - - issue.reload - - expect(issue.due_date).to be_nil - end - end + it_behaves_like 'remove_due_date action available and due date can be removed' context 'when the current user cannot update the due date' do let(:guest) { create(:user) } @@ -95,15 +87,7 @@ describe 'Issues > User uses quick actions', :js do visit project_issue_path(project, issue) end - it 'does not create a note, and sets the due date accordingly' do - add_note("/remove_due_date") - - expect(page).not_to have_content 'Commands applied' - - issue.reload - - expect(issue.due_date).to eq Date.new(2016, 8, 28) - end + it_behaves_like 'remove_due_date action not available' end end @@ -200,6 +184,7 @@ describe 'Issues > User uses quick actions', :js do gitlab_sign_out sign_in(user) visit project_issue_path(project, issue) + wait_for_requests end it 'moves the issue' do @@ -221,6 +206,7 @@ describe 'Issues > User uses quick actions', :js do gitlab_sign_out sign_in(user) visit project_issue_path(project, issue) + wait_for_requests end it 'does not move the issue' do @@ -238,6 +224,7 @@ describe 'Issues > User uses quick actions', :js do gitlab_sign_out sign_in(user) visit project_issue_path(project, issue) + wait_for_requests end it 'does not move the issue' do diff --git a/spec/features/merge_request/user_posts_notes_spec.rb b/spec/features/merge_request/user_posts_notes_spec.rb index dc0862be6fc..e5770905dbd 100644 --- a/spec/features/merge_request/user_posts_notes_spec.rb +++ b/spec/features/merge_request/user_posts_notes_spec.rb @@ -67,18 +67,7 @@ describe 'Merge request > User posts notes', :js do end end - describe 'when reply_to_individual_notes feature flag is disabled' do - before do - stub_feature_flags(reply_to_individual_notes: false) - visit project_merge_request_path(project, merge_request) - end - - it 'does not show a reply button' do - expect(page).to have_no_selector('.js-reply-button') - end - end - - describe 'when reply_to_individual_notes feature flag is not set' do + describe 'reply button' do before do visit project_merge_request_path(project, merge_request) end diff --git a/spec/features/merge_request/user_resolves_conflicts_spec.rb b/spec/features/merge_request/user_resolves_conflicts_spec.rb index 16c058ab6bd..8fd44b87e5a 100644 --- a/spec/features/merge_request/user_resolves_conflicts_spec.rb +++ b/spec/features/merge_request/user_resolves_conflicts_spec.rb @@ -164,6 +164,21 @@ describe 'Merge request > User resolves conflicts', :js do expect(page).to have_content('Gregor Samsa woke from troubled dreams') end end + + context "with malicious branch name" do + let(:bad_branch_name) { "malicious-branch-{{toString.constructor('alert(/xss/)')()}}" } + let(:branch) { project.repository.create_branch(bad_branch_name, 'conflict-resolvable') } + let(:merge_request) { create_merge_request(branch.name) } + + before do + visit project_merge_request_path(project, merge_request) + click_link('conflicts', href: %r{/conflicts\Z}) + end + + it "renders bad name without xss issues" do + expect(find('.resolve-conflicts-form .resolve-info')).to have_content(bad_branch_name) + end + end end UNRESOLVABLE_CONFLICTS = { diff --git a/spec/features/merge_request/user_uses_quick_actions_spec.rb b/spec/features/merge_request/user_uses_quick_actions_spec.rb index b81478a481f..a2b5859bd1e 100644 --- a/spec/features/merge_request/user_uses_quick_actions_spec.rb +++ b/spec/features/merge_request/user_uses_quick_actions_spec.rb @@ -9,9 +9,41 @@ describe 'Merge request > User uses quick actions', :js do let(:merge_request) { create(:merge_request, source_project: project) } let!(:milestone) { create(:milestone, project: project, title: 'ASAP') } - it_behaves_like 'issuable record that supports quick actions in its description and notes', :merge_request do + context "issuable common quick actions" do + let!(:new_url_opts) { { merge_request: { source_branch: 'feature', target_branch: 'master' } } } + let(:maintainer) { create(:user) } + let(:project) { create(:project, :public, :repository) } + let!(:label_bug) { create(:label, project: project, title: 'bug') } + let!(:label_feature) { create(:label, project: project, title: 'feature') } + let!(:milestone) { create(:milestone, project: project, title: 'ASAP') } let(:issuable) { create(:merge_request, source_project: project) } - let(:new_url_opts) { { merge_request: { source_branch: 'feature', target_branch: 'master' } } } + let(:source_issuable) { create(:issue, project: project, milestone: milestone, labels: [label_bug, label_feature])} + + it_behaves_like 'assign quick action', :merge_request + it_behaves_like 'unassign quick action', :merge_request + it_behaves_like 'close quick action', :merge_request + it_behaves_like 'reopen quick action', :merge_request + it_behaves_like 'title quick action', :merge_request + it_behaves_like 'todo quick action', :merge_request + it_behaves_like 'done quick action', :merge_request + it_behaves_like 'subscribe quick action', :merge_request + it_behaves_like 'unsubscribe quick action', :merge_request + it_behaves_like 'lock quick action', :merge_request + it_behaves_like 'unlock quick action', :merge_request + it_behaves_like 'milestone quick action', :merge_request + it_behaves_like 'remove_milestone quick action', :merge_request + it_behaves_like 'label quick action', :merge_request + it_behaves_like 'unlabel quick action', :merge_request + it_behaves_like 'relabel quick action', :merge_request + it_behaves_like 'award quick action', :merge_request + it_behaves_like 'estimate quick action', :merge_request + it_behaves_like 'remove_estimate quick action', :merge_request + it_behaves_like 'spend quick action', :merge_request + it_behaves_like 'remove_time_spent quick action', :merge_request + it_behaves_like 'shrug quick action', :merge_request + it_behaves_like 'tableflip quick action', :merge_request + it_behaves_like 'copy_metadata quick action', :merge_request + it_behaves_like 'issuable time tracker', :merge_request end describe 'merge-request-only commands' do @@ -24,20 +56,12 @@ describe 'Merge request > User uses quick actions', :js do project.add_maintainer(user) end - describe 'time tracking' do - before do - sign_in(user) - visit project_merge_request_path(project, merge_request) - end - - it_behaves_like 'issuable time tracker' - end - describe 'toggling the WIP prefix in the title from note' do context 'when the current user can toggle the WIP prefix' do before do sign_in(user) visit project_merge_request_path(project, merge_request) + wait_for_requests end it 'adds the WIP: prefix to the title' do @@ -135,11 +159,16 @@ describe 'Merge request > User uses quick actions', :js do visit project_merge_request_path(project, merge_request) end - it 'does not recognize the command nor create a note' do - add_note('/due 2016-08-28') + it_behaves_like 'due quick action not available' + end - expect(page).not_to have_content '/due 2016-08-28' + describe 'removing a due date from note' do + before do + sign_in(user) + visit project_merge_request_path(project, merge_request) end + + it_behaves_like 'remove_due_date action not available' end describe '/target_branch command in merge request' do diff --git a/spec/features/projects/graph_spec.rb b/spec/features/projects/graph_spec.rb index 9665f1755d6..e1bc18519a2 100644 --- a/spec/features/projects/graph_spec.rb +++ b/spec/features/projects/graph_spec.rb @@ -6,6 +6,8 @@ describe 'Project Graph', :js do let(:branch_name) { 'master' } before do + ::Projects::DetectRepositoryLanguagesService.new(project, user).execute + project.add_maintainer(user) sign_in(user) diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index 9fdf78baa1e..b197557039d 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -59,11 +59,11 @@ describe 'Pipeline', :js do let(:project) { create(:project, :repository) } let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id, user: user) } - before do - visit project_pipeline_path(project, pipeline) - end + subject(:visit_pipeline) { visit project_pipeline_path(project, pipeline) } it 'shows the pipeline graph' do + visit_pipeline + expect(page).to have_selector('.pipeline-visualization') expect(page).to have_content('Build') expect(page).to have_content('Test') @@ -73,14 +73,20 @@ describe 'Pipeline', :js do end it 'shows Pipeline tab pane as active' do + visit_pipeline + expect(page).to have_css('#js-tab-pipeline.active') end it 'shows link to the pipeline ref' do + visit_pipeline + expect(page).to have_link(pipeline.ref) end it 'shows the pipeline information' do + visit_pipeline + within '.pipeline-info' do expect(page).to have_content("#{pipeline.statuses.count} jobs " \ "for #{pipeline.ref} ") @@ -96,6 +102,10 @@ describe 'Pipeline', :js do end describe 'pipeline graph' do + before do + visit_pipeline + end + context 'when pipeline has running builds' do it 'shows a running icon and a cancel action for the running build' do page.within('#ci-badge-deploy') do @@ -227,6 +237,10 @@ describe 'Pipeline', :js do end context 'page tabs' do + before do + visit_pipeline + end + it 'shows Pipeline, Jobs and Failed Jobs tabs with link' do expect(page).to have_link('Pipeline') expect(page).to have_link('Jobs') @@ -253,6 +267,10 @@ describe 'Pipeline', :js do end context 'retrying jobs' do + before do + visit_pipeline + end + it { expect(page).not_to have_content('retried') } context 'when retrying' do @@ -265,6 +283,10 @@ describe 'Pipeline', :js do end context 'canceling jobs' do + before do + visit_pipeline + end + it { expect(page).not_to have_selector('.ci-canceled') } context 'when canceling' do @@ -284,6 +306,10 @@ describe 'Pipeline', :js do user: user) end + before do + visit_pipeline + end + it 'does not render link to the pipeline ref' do expect(page).not_to have_link(pipeline.ref) expect(page).to have_content(pipeline.ref) @@ -305,6 +331,10 @@ describe 'Pipeline', :js do merge_request.all_pipelines.last end + before do + visit_pipeline + end + it 'shows the pipeline information' do within '.pipeline-info' do expect(page).to have_content("#{pipeline.statuses.count} jobs " \ @@ -356,6 +386,8 @@ describe 'Pipeline', :js do before do pipeline.update(user: user) + + visit_pipeline end it 'shows the pipeline information' do diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb index 368a814874f..9d5780d29b0 100644 --- a/spec/features/users/login_spec.rb +++ b/spec/features/users/login_spec.rb @@ -447,7 +447,7 @@ describe 'Login' do 'You can leave Group 1 and leave Group 2. '\ 'You need to do this '\ 'before '\ - "#{(Time.zone.now + 2.days).strftime("%a, %-d %b %Y %H:%M:%S %z")}" + "#{(Time.zone.now + 2.days).strftime("%a, %d %b %Y %H:%M:%S %z")}" ) end end diff --git a/spec/frontend/.eslintrc.yml b/spec/frontend/.eslintrc.yml index 046215e4c93..054dc27cda6 100644 --- a/spec/frontend/.eslintrc.yml +++ b/spec/frontend/.eslintrc.yml @@ -2,8 +2,13 @@ env: jest/globals: true plugins: -- jest + - jest settings: import/resolver: jest: - jestConfigFile: "jest.config.js" + jestConfigFile: 'jest.config.js' +globals: + getJSONFixture: false + loadFixtures: false + preloadFixtures: false + setFixtures: false diff --git a/spec/frontend/environment.js b/spec/frontend/environment.js index cb128c7d880..34df8019a2e 100644 --- a/spec/frontend/environment.js +++ b/spec/frontend/environment.js @@ -6,6 +6,7 @@ const JSDOMEnvironment = require('jest-environment-jsdom'); class CustomEnvironment extends JSDOMEnvironment { constructor(config, context) { super(config, context); + Object.assign(context.console, { error(...args) { throw new ErrorWithStack( @@ -21,6 +22,30 @@ class CustomEnvironment extends JSDOMEnvironment { ); }, }); + + const { testEnvironmentOptions } = config; + this.global.gon = { + ee: testEnvironmentOptions.IS_EE, + }; + + this.rejectedPromises = []; + + this.global.promiseRejectionHandler = error => { + this.rejectedPromises.push(error); + }; + } + + async teardown() { + await new Promise(setImmediate); + + if (this.rejectedPromises.length > 0) { + throw new ErrorWithStack( + `Unhandled Promise rejections: ${this.rejectedPromises.join(', ')}`, + this.teardown, + ); + } + + await super.teardown(); } } diff --git a/spec/frontend/helpers/class_spec_helper.js b/spec/frontend/helpers/class_spec_helper.js new file mode 100644 index 00000000000..7a60d33b471 --- /dev/null +++ b/spec/frontend/helpers/class_spec_helper.js @@ -0,0 +1,9 @@ +export default class ClassSpecHelper { + static itShouldBeAStaticMethod(base, method) { + return it('should be a static method', () => { + expect(Object.prototype.hasOwnProperty.call(base, method)).toBeTruthy(); + }); + } +} + +window.ClassSpecHelper = ClassSpecHelper; diff --git a/spec/frontend/helpers/fixtures.js b/spec/frontend/helpers/fixtures.js index de9058d7832..f0351aa31c6 100644 --- a/spec/frontend/helpers/fixtures.js +++ b/spec/frontend/helpers/fixtures.js @@ -1,5 +1,3 @@ -/* eslint-disable import/prefer-default-export, global-require, import/no-dynamic-require */ - import fs from 'fs'; import path from 'path'; @@ -7,16 +5,32 @@ import { ErrorWithStack } from 'jest-util'; const fixturesBasePath = path.join(process.cwd(), 'spec', 'javascripts', 'fixtures'); -export function getJSONFixture(relativePath, ee = false) { - const absolutePath = path.join(fixturesBasePath, ee ? 'ee' : '', relativePath); +export function getFixture(relativePath) { + const absolutePath = path.join(fixturesBasePath, relativePath); if (!fs.existsSync(absolutePath)) { throw new ErrorWithStack( `Fixture file ${relativePath} does not exist. Did you run bin/rake karma:fixtures?`, - getJSONFixture, + getFixture, ); } - return require(absolutePath); + return fs.readFileSync(absolutePath, 'utf8'); } + +export const getJSONFixture = relativePath => JSON.parse(getFixture(relativePath)); + +export const resetHTMLFixture = () => { + document.body.textContent = ''; +}; + +export const setHTMLFixture = (htmlContent, resetHook = afterEach) => { + document.body.outerHTML = htmlContent; + resetHook(resetHTMLFixture); +}; + +export const loadHTMLFixture = (relativePath, resetHook = afterEach) => { + const fileContent = getFixture(relativePath); + setHTMLFixture(fileContent, resetHook); +}; diff --git a/spec/frontend/helpers/locale_helper.js b/spec/frontend/helpers/locale_helper.js new file mode 100644 index 00000000000..80047b06003 --- /dev/null +++ b/spec/frontend/helpers/locale_helper.js @@ -0,0 +1,11 @@ +/* eslint-disable import/prefer-default-export */ + +export const setLanguage = languageCode => { + const htmlElement = document.querySelector('html'); + + if (languageCode) { + htmlElement.setAttribute('lang', languageCode); + } else { + htmlElement.removeAttribute('lang'); + } +}; diff --git a/spec/frontend/helpers/scroll_into_view_promise.js b/spec/frontend/helpers/scroll_into_view_promise.js new file mode 100644 index 00000000000..0edea2103da --- /dev/null +++ b/spec/frontend/helpers/scroll_into_view_promise.js @@ -0,0 +1,28 @@ +export default function scrollIntoViewPromise(intersectionTarget, timeout = 100, maxTries = 5) { + return new Promise((resolve, reject) => { + let intersectionObserver; + let retry = 0; + + const intervalId = setInterval(() => { + if (retry >= maxTries) { + intersectionObserver.disconnect(); + clearInterval(intervalId); + reject(new Error(`Could not scroll target into viewPort within ${timeout * maxTries} ms`)); + } + retry += 1; + intersectionTarget.scrollIntoView(); + }, timeout); + + intersectionObserver = new IntersectionObserver(entries => { + if (entries[0].isIntersecting) { + intersectionObserver.disconnect(); + clearInterval(intervalId); + resolve(); + } + }); + + intersectionObserver.observe(intersectionTarget); + + intersectionTarget.scrollIntoView(); + }); +} diff --git a/spec/frontend/helpers/set_timeout_promise_helper.js b/spec/frontend/helpers/set_timeout_promise_helper.js new file mode 100644 index 00000000000..47087619187 --- /dev/null +++ b/spec/frontend/helpers/set_timeout_promise_helper.js @@ -0,0 +1,4 @@ +export default (time = 0) => + new Promise(resolve => { + setTimeout(resolve, time); + }); diff --git a/spec/frontend/helpers/user_mock_data_helper.js b/spec/frontend/helpers/user_mock_data_helper.js new file mode 100644 index 00000000000..6999fa1f8a1 --- /dev/null +++ b/spec/frontend/helpers/user_mock_data_helper.js @@ -0,0 +1,14 @@ +export default { + createNumberRandomUsers(numberUsers) { + const users = []; + for (let i = 0; i < numberUsers; i += 1) { + users.push({ + avatar: 'https://gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon', + id: i + 1, + name: `GitLab User ${i}`, + username: `gitlab${i}`, + }); + } + return users; + }, +}; diff --git a/spec/frontend/helpers/vue_component_helper.js b/spec/frontend/helpers/vue_component_helper.js new file mode 100644 index 00000000000..e0fe18e5560 --- /dev/null +++ b/spec/frontend/helpers/vue_component_helper.js @@ -0,0 +1,18 @@ +/** + * Replaces line break with an empty space + * @param {*} data + */ +export const removeBreakLine = data => data.replace(/\r?\n|\r/g, ' '); + +/** + * Removes line breaks, spaces and trims the given text + * @param {String} str + * @returns {String} + */ +export const trimText = str => + str + .replace(/\r?\n|\r/g, '') + .replace(/\s\s+/g, ' ') + .trim(); + +export const removeWhitespace = str => str.replace(/\s\s+/g, ' '); diff --git a/spec/frontend/helpers/vue_resource_helper.js b/spec/frontend/helpers/vue_resource_helper.js new file mode 100644 index 00000000000..0f58af09933 --- /dev/null +++ b/spec/frontend/helpers/vue_resource_helper.js @@ -0,0 +1,11 @@ +// eslint-disable-next-line import/prefer-default-export +export const headersInterceptor = (request, next) => { + next(response => { + const headers = {}; + response.headers.forEach((value, key) => { + headers[key] = value; + }); + // eslint-disable-next-line no-param-reassign + response.headers = headers; + }); +}; diff --git a/spec/frontend/helpers/vue_test_utils_helper.js b/spec/frontend/helpers/vue_test_utils_helper.js new file mode 100644 index 00000000000..19e27388eeb --- /dev/null +++ b/spec/frontend/helpers/vue_test_utils_helper.js @@ -0,0 +1,19 @@ +/* eslint-disable import/prefer-default-export */ + +const vNodeContainsText = (vnode, text) => + (vnode.text && vnode.text.includes(text)) || + (vnode.children && vnode.children.filter(child => vNodeContainsText(child, text)).length); + +/** + * Determines whether a `shallowMount` Wrapper contains text + * within one of it's slots. This will also work on Wrappers + * acquired with `find()`, but only if it's parent Wrapper + * was shallowMounted. + * NOTE: Prefer checking the rendered output of a component + * wherever possible using something like `text()` instead. + * @param {Wrapper} shallowWrapper - Vue test utils wrapper (shallowMounted) + * @param {String} slotName + * @param {String} text + */ +export const shallowWrapperContainsSlotText = (shallowWrapper, slotName, text) => + !!shallowWrapper.vm.$slots[slotName].filter(vnode => vNodeContainsText(vnode, text)).length; diff --git a/spec/frontend/helpers/vuex_action_helper.js b/spec/frontend/helpers/vuex_action_helper.js new file mode 100644 index 00000000000..88652202a8e --- /dev/null +++ b/spec/frontend/helpers/vuex_action_helper.js @@ -0,0 +1,104 @@ +const noop = () => {}; + +/** + * Helper for testing action with expected mutations inspired in + * https://vuex.vuejs.org/en/testing.html + * + * @param {Function} action to be tested + * @param {Object} payload will be provided to the action + * @param {Object} state will be provided to the action + * @param {Array} [expectedMutations=[]] mutations expected to be committed + * @param {Array} [expectedActions=[]] actions expected to be dispatched + * @param {Function} [done=noop] to be executed after the tests + * @return {Promise} + * + * @example + * testAction( + * actions.actionName, // action + * { }, // mocked payload + * state, //state + * // expected mutations + * [ + * { type: types.MUTATION} + * { type: types.MUTATION_1, payload: jasmine.any(Number)} + * ], + * // expected actions + * [ + * { type: 'actionName', payload: {param: 'foobar'}}, + * { type: 'actionName1'} + * ] + * done, + * ); + * + * @example + * testAction( + * actions.actionName, // action + * { }, // mocked payload + * state, //state + * [ { type: types.MUTATION} ], // expected mutations + * [], // expected actions + * ).then(done) + * .catch(done.fail); + */ +export default ( + action, + payload, + state, + expectedMutations = [], + expectedActions = [], + done = noop, +) => { + const mutations = []; + const actions = []; + + // mock commit + const commit = (type, mutationPayload) => { + const mutation = { type }; + + if (typeof mutationPayload !== 'undefined') { + mutation.payload = mutationPayload; + } + + mutations.push(mutation); + }; + + // mock dispatch + const dispatch = (type, actionPayload) => { + const dispatchedAction = { type }; + + if (typeof actionPayload !== 'undefined') { + dispatchedAction.payload = actionPayload; + } + + actions.push(dispatchedAction); + }; + + const validateResults = () => { + expect({ + mutations, + actions, + }).toEqual({ + mutations: expectedMutations, + actions: expectedActions, + }); + done(); + }; + + const result = action( + { commit, state, dispatch, rootState: state, rootGetters: state, getters: state }, + payload, + ); + + return new Promise(resolve => { + setImmediate(resolve); + }) + .then(() => result) + .catch(error => { + validateResults(); + throw error; + }) + .then(data => { + validateResults(); + return data; + }); +}; diff --git a/spec/frontend/helpers/wait_for_attribute_change.js b/spec/frontend/helpers/wait_for_attribute_change.js new file mode 100644 index 00000000000..8f22d569222 --- /dev/null +++ b/spec/frontend/helpers/wait_for_attribute_change.js @@ -0,0 +1,16 @@ +export default (domElement, attributes, timeout = 1500) => + new Promise((resolve, reject) => { + let observer; + const timeoutId = setTimeout(() => { + observer.disconnect(); + reject(new Error(`Could not see an attribute update within ${timeout} ms`)); + }, timeout); + + observer = new MutationObserver(() => { + clearTimeout(timeoutId); + observer.disconnect(); + resolve(); + }); + + observer.observe(domElement, { attributes: true, attributeFilter: attributes }); + }); diff --git a/spec/frontend/helpers/wait_for_promises.js b/spec/frontend/helpers/wait_for_promises.js new file mode 100644 index 00000000000..1d2b53fc770 --- /dev/null +++ b/spec/frontend/helpers/wait_for_promises.js @@ -0,0 +1 @@ +export default () => new Promise(resolve => requestAnimationFrame(resolve)); diff --git a/spec/frontend/ide/lib/files_spec.js b/spec/frontend/ide/lib/files_spec.js index fe791aa2b74..aa1fa0373db 100644 --- a/spec/frontend/ide/lib/files_spec.js +++ b/spec/frontend/ide/lib/files_spec.js @@ -1,5 +1,5 @@ import { viewerInformationForPath } from '~/vue_shared/components/content_viewer/lib/viewer_utils'; -import { decorateFiles, splitParent } from '~/ide/lib/files'; +import { decorateFiles, splitParent, escapeFileUrl } from '~/ide/lib/files'; import { decorateData } from '~/ide/stores/utils'; const TEST_BRANCH_ID = 'lorem-ipsum'; @@ -20,7 +20,7 @@ const createEntries = paths => { id: path, name, path, - url: createUrl(`/${TEST_PROJECT_ID}/${type}/${TEST_BRANCH_ID}/-/${path}`), + url: createUrl(`/${TEST_PROJECT_ID}/${type}/${TEST_BRANCH_ID}/-/${escapeFileUrl(path)}`), type, previewMode: viewerInformationForPath(path), parentPath: parent, @@ -28,7 +28,7 @@ const createEntries = paths => { ? parentEntry.url : createUrl(`/${TEST_PROJECT_ID}/${type}/${TEST_BRANCH_ID}`), }), - tree: children.map(childName => jasmine.objectContaining({ name: childName })), + tree: children.map(childName => expect.objectContaining({ name: childName })), }; return acc; @@ -36,10 +36,10 @@ const createEntries = paths => { const entries = paths.reduce(createEntry, {}); - // Wrap entries in jasmine.objectContaining. + // Wrap entries in expect.objectContaining. // We couldn't do this earlier because we still need to select properties from parent entries. return Object.keys(entries).reduce((acc, key) => { - acc[key] = jasmine.objectContaining(entries[key]); + acc[key] = expect.objectContaining(entries[key]); return acc; }, {}); @@ -47,13 +47,14 @@ const createEntries = paths => { describe('IDE lib decorate files', () => { it('creates entries and treeList', () => { - const data = ['app/assets/apples/foo.js', 'app/bugs.js', 'README.md']; + const data = ['app/assets/apples/foo.js', 'app/bugs.js', 'app/#weird#file?.txt', 'README.md']; const expectedEntries = createEntries([ - { path: 'app', type: 'tree', children: ['assets', 'bugs.js'] }, + { path: 'app', type: 'tree', children: ['assets', '#weird#file?.txt', 'bugs.js'] }, { path: 'app/assets', type: 'tree', children: ['apples'] }, { path: 'app/assets/apples', type: 'tree', children: ['foo.js'] }, { path: 'app/assets/apples/foo.js', type: 'blob', children: [] }, { path: 'app/bugs.js', type: 'blob', children: [] }, + { path: 'app/#weird#file?.txt', type: 'blob', children: [] }, { path: 'README.md', type: 'blob', children: [] }, ]); @@ -64,7 +65,7 @@ describe('IDE lib decorate files', () => { }); // Here we test the keys and then each key/value individually because `expect(entries).toEqual(expectedEntries)` - // was taking a very long time for some reason. Probably due to large objects and nested `jasmine.objectContaining`. + // was taking a very long time for some reason. Probably due to large objects and nested `expect.objectContaining`. const entryKeys = Object.keys(entries); expect(entryKeys).toEqual(Object.keys(expectedEntries)); diff --git a/spec/javascripts/pages/admin/abuse_reports/abuse_reports_spec.js b/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js index f7637964c60..1e0bc708c31 100644 --- a/spec/javascripts/pages/admin/abuse_reports/abuse_reports_spec.js +++ b/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js @@ -16,9 +16,9 @@ describe('Abuse Reports', () => { preloadFixtures(FIXTURE); - beforeEach(function() { + beforeEach(() => { loadFixtures(FIXTURE); - this.abuseReports = new AbuseReports(); + new AbuseReports(); // eslint-disable-line no-new $messages = $('.abuse-reports .message'); }); diff --git a/spec/javascripts/reports/components/report_section_spec.js b/spec/frontend/reports/components/report_section_spec.js index b02af8baaec..3b609484b9e 100644 --- a/spec/javascripts/reports/components/report_section_spec.js +++ b/spec/frontend/reports/components/report_section_spec.js @@ -1,6 +1,6 @@ import Vue from 'vue'; import reportSection from '~/reports/components/report_section.vue'; -import mountComponent, { mountComponentWithSlots } from 'spec/helpers/vue_mount_component_helper'; +import mountComponent, { mountComponentWithSlots } from 'helpers/vue_mount_component_helper'; describe('Report section', () => { let vm; diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js index 006fc60ef57..c57e0e7cfc6 100644 --- a/spec/frontend/test_setup.js +++ b/spec/frontend/test_setup.js @@ -1,12 +1,19 @@ import Vue from 'vue'; +import * as jqueryMatchers from 'custom-jquery-matchers'; import Translate from '~/vue_shared/translate'; import axios from '~/lib/utils/axios_utils'; import { initializeTestTimeout } from './helpers/timeout'; +import { getJSONFixture, loadHTMLFixture, setHTMLFixture } from './helpers/fixtures'; -// wait for pending setTimeout()s -afterEach(() => { - jest.runAllTimers(); -}); +process.on('unhandledRejection', global.promiseRejectionHandler); + +afterEach(() => + // give Promises a bit more time so they fail the right test + new Promise(setImmediate).then(() => { + // wait for pending setTimeout()s + jest.runAllTimers(); + }), +); initializeTestTimeout(300); @@ -22,4 +29,31 @@ beforeEach(done => { done(); }); +Vue.config.devtools = false; +Vue.config.productionTip = false; + Vue.use(Translate); + +// workaround for JSDOM not supporting innerText +// see https://github.com/jsdom/jsdom/issues/1245 +Object.defineProperty(global.Element.prototype, 'innerText', { + get() { + return this.textContent; + }, + configurable: true, // make it so that it doesn't blow chunks on re-running tests with things like --watch +}); + +// convenience wrapper for migration from Karma +Object.assign(global, { + loadFixtures: loadHTMLFixture, + loadJSONFixtures: getJSONFixture, + preloadFixtures() {}, + setFixtures: setHTMLFixture, +}); + +// custom-jquery-matchers was written for an old Jest version, we need to make it compatible +Object.entries(jqueryMatchers).forEach(([matcherName, matcherFactory]) => { + expect.extend({ + [matcherName]: matcherFactory().compare, + }); +}); diff --git a/spec/graphql/types/permission_types/issue_spec.rb b/spec/graphql/types/permission_types/issue_spec.rb index c3f84629aa2..f0fbeda202f 100644 --- a/spec/graphql/types/permission_types/issue_spec.rb +++ b/spec/graphql/types/permission_types/issue_spec.rb @@ -7,6 +7,8 @@ describe Types::PermissionTypes::Issue do :create_note, :reopen_issue ] - expect(described_class).to have_graphql_fields(expected_permissions) + expected_permissions.each do |permission| + expect(described_class).to have_graphql_field(permission) + end end end diff --git a/spec/graphql/types/permission_types/project_spec.rb b/spec/graphql/types/permission_types/project_spec.rb index 4288412eda3..4974995b587 100644 --- a/spec/graphql/types/permission_types/project_spec.rb +++ b/spec/graphql/types/permission_types/project_spec.rb @@ -13,6 +13,8 @@ describe Types::PermissionTypes::Project do :update_wiki, :destroy_wiki, :create_pages, :destroy_pages, :read_pages_content ] - expect(described_class).to have_graphql_fields(expected_permissions) + expected_permissions.each do |permission| + expect(described_class).to have_graphql_field(permission) + end end end diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb index 2bc3933809f..6808ed86c9a 100644 --- a/spec/helpers/blob_helper_spec.rb +++ b/spec/helpers/blob_helper_spec.rb @@ -230,5 +230,18 @@ describe BlobHelper do expect(helper.ide_edit_path(project, "master", "")).to eq("/gitlab/-/ide/project/#{project.namespace.path}/#{project.path}/edit/master") end + + it 'escapes special characters' do + Rails.application.routes.default_url_options[:script_name] = nil + + expect(helper.ide_edit_path(project, "testing/#hashes", "readme.md#test")).to eq("/-/ide/project/#{project.namespace.path}/#{project.path}/edit/testing/#hashes/-/readme.md%23test") + expect(helper.ide_edit_path(project, "testing/#hashes", "src#/readme.md#test")).to eq("/-/ide/project/#{project.namespace.path}/#{project.path}/edit/testing/#hashes/-/src%23/readme.md%23test") + end + + it 'does not escape "/" character' do + Rails.application.routes.default_url_options[:script_name] = nil + + expect(helper.ide_edit_path(project, "testing/slashes", "readme.md/")).to eq("/-/ide/project/#{project.namespace.path}/#{project.path}/edit/testing/slashes/-/readme.md/") + end end end diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb index 91541a16c13..1763c46389a 100644 --- a/spec/helpers/groups_helper_spec.rb +++ b/spec/helpers/groups_helper_spec.rb @@ -229,4 +229,37 @@ describe GroupsHelper do expect(helper.group_sidebar_links).not_to include(*cross_project_features) end end + + describe 'parent_group_options', :nested_groups do + let(:current_user) { create(:user) } + let(:group) { create(:group, name: 'group') } + let(:group2) { create(:group, name: 'group2') } + + before do + group.add_owner(current_user) + group2.add_owner(current_user) + end + + it 'includes explicitly owned groups except self' do + expect(parent_group_options(group2)).to eq([{ id: group.id, text: group.human_name }].to_json) + end + + it 'excludes parent group' do + subgroup = create(:group, parent: group2) + + expect(parent_group_options(subgroup)).to eq([{ id: group.id, text: group.human_name }].to_json) + end + + it 'includes subgroups with inherited ownership' do + subgroup = create(:group, parent: group) + + expect(parent_group_options(group2)).to eq([{ id: group.id, text: group.human_name }, { id: subgroup.id, text: subgroup.human_name }].to_json) + end + + it 'excludes own subgroups' do + create(:group, parent: group2) + + expect(parent_group_options(group2)).to eq([{ id: group.id, text: group.human_name }].to_json) + end + end end diff --git a/spec/javascripts/boards/components/board_spec.js b/spec/javascripts/boards/components/board_spec.js index 6e6b3e6950b..d08ee41802b 100644 --- a/spec/javascripts/boards/components/board_spec.js +++ b/spec/javascripts/boards/components/board_spec.js @@ -103,4 +103,18 @@ describe('Board component', () => { }) .catch(done.fail); }); + + it('does render add issue button', () => { + expect(vm.$el.querySelector('.issue-count-badge-add-button')).not.toBeNull(); + }); + + it('does not render add issue button when list type is blank', done => { + vm.list.type = 'blank'; + + Vue.nextTick(() => { + expect(vm.$el.querySelector('.issue-count-badge-add-button')).toBeNull(); + + done(); + }); + }); }); diff --git a/spec/javascripts/diffs/components/diff_file_header_spec.js b/spec/javascripts/diffs/components/diff_file_header_spec.js index e10193c25b7..6614069f44d 100644 --- a/spec/javascripts/diffs/components/diff_file_header_spec.js +++ b/spec/javascripts/diffs/components/diff_file_header_spec.js @@ -3,7 +3,7 @@ import Vuex from 'vuex'; import diffsModule from '~/diffs/store/modules'; import notesModule from '~/notes/stores/modules'; import DiffFileHeader from '~/diffs/components/diff_file_header.vue'; -import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; +import mountComponent, { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; import diffDiscussionsMockData from '../mock_data/diff_discussions'; import { diffViewerModes } from '~/ide/constants'; @@ -249,6 +249,75 @@ describe('diff_file_header', () => { expect(vm.$emit).not.toHaveBeenCalled(); }); }); + + describe('handleFileNameClick', () => { + let e; + + beforeEach(() => { + e = { preventDefault: () => {} }; + spyOn(e, 'preventDefault'); + }); + + describe('when file name links to other page', () => { + it('does not call preventDefault if submodule tree url exists', () => { + vm = mountComponent(Component, { + ...props, + diffFile: { ...props.diffFile, submodule_tree_url: 'foobar.com' }, + }); + + vm.handleFileNameClick(e); + + expect(e.preventDefault).not.toHaveBeenCalled(); + }); + + it('does not call preventDefault if submodule_link exists', () => { + vm = mountComponent(Component, { + ...props, + diffFile: { ...props.diffFile, submodule_link: 'foobar.com' }, + }); + vm.handleFileNameClick(e); + + expect(e.preventDefault).not.toHaveBeenCalled(); + }); + + it('does not call preventDefault if discussionPath exists', () => { + vm = mountComponent(Component, { + ...props, + discussionPath: 'Foo bar', + }); + + vm.handleFileNameClick(e); + + expect(e.preventDefault).not.toHaveBeenCalled(); + }); + }); + + describe('scrolling to diff', () => { + let scrollToElement; + let el; + + beforeEach(() => { + el = document.createElement('div'); + spyOn(document, 'querySelector').and.returnValue(el); + scrollToElement = spyOnDependency(DiffFileHeader, 'scrollToElement'); + vm = mountComponent(Component, props); + + vm.handleFileNameClick(e); + }); + + it('calls scrollToElement with file content', () => { + expect(scrollToElement).toHaveBeenCalledWith(el); + }); + + it('element adds the content id to the window location', () => { + expect(window.location.hash).toContain(props.diffFile.file_hash); + }); + + it('calls preventDefault when button does not link to other page', () => { + expect(e.preventDefault).toHaveBeenCalled(); + }); + }); + }); }); describe('template', () => { diff --git a/spec/javascripts/diffs/components/diff_file_spec.js b/spec/javascripts/diffs/components/diff_file_spec.js index d9b298e84da..ef4589ada48 100644 --- a/spec/javascripts/diffs/components/diff_file_spec.js +++ b/spec/javascripts/diffs/components/diff_file_spec.js @@ -141,18 +141,16 @@ describe('DiffFile', () => { it('should have too large warning and blob link', done => { const BLOB_LINK = '/file/view/path'; vm.file.viewer.error = diffViewerErrors.too_large; + vm.file.viewer.error_message = + 'This source diff could not be displayed because it is too large'; vm.file.view_path = BLOB_LINK; + vm.file.renderIt = true; vm.$nextTick(() => { expect(vm.$el.innerText).toContain( 'This source diff could not be displayed because it is too large', ); - expect(vm.$el.querySelector('.js-too-large-diff')).toBeDefined(); - expect( - vm.$el.querySelector('.js-too-large-diff a').href.indexOf(BLOB_LINK), - ).toBeGreaterThan(-1); - done(); }); }); diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js index 0bb43c94f6a..2084c36e484 100644 --- a/spec/javascripts/lib/utils/common_utils_spec.js +++ b/spec/javascripts/lib/utils/common_utils_spec.js @@ -2,6 +2,7 @@ import axios from '~/lib/utils/axios_utils'; import * as commonUtils from '~/lib/utils/common_utils'; import MockAdapter from 'axios-mock-adapter'; import { faviconDataUrl, overlayDataUrl, faviconWithOverlayDataUrl } from './mock_data'; +import BreakpointInstance from '~/breakpoints'; const PIXEL_TOLERANCE = 0.2; @@ -380,6 +381,38 @@ describe('common_utils', () => { }); }); + describe('contentTop', () => { + it('does not add height for fileTitle or compareVersionsHeader if screen is too small', () => { + spyOn(BreakpointInstance, 'getBreakpointSize').and.returnValue('sm'); + + setFixtures(` + <div class="diff-file file-title-flex-parent"> + blah blah blah + </div> + <div class="mr-version-controls"> + more blah blah blah + </div> + `); + + expect(commonUtils.contentTop()).toBe(0); + }); + + it('adds height for fileTitle and compareVersionsHeader screen is large enough', () => { + spyOn(BreakpointInstance, 'getBreakpointSize').and.returnValue('lg'); + + setFixtures(` + <div class="diff-file file-title-flex-parent"> + blah blah blah + </div> + <div class="mr-version-controls"> + more blah blah blah + </div> + `); + + expect(commonUtils.contentTop()).toBe(18); + }); + }); + describe('parseBoolean', () => { const { parseBoolean } = commonUtils; diff --git a/spec/javascripts/monitoring/charts/area_spec.js b/spec/javascripts/monitoring/charts/area_spec.js index fb49290be19..549a7935c0f 100644 --- a/spec/javascripts/monitoring/charts/area_spec.js +++ b/spec/javascripts/monitoring/charts/area_spec.js @@ -203,6 +203,10 @@ describe('Area component', () => { .length, ).toBe(data.length); }); + + it('formats line width correctly', () => { + expect(chartData[0].lineStyle.width).toBe(2); + }); }); describe('scatterSeries', () => { diff --git a/spec/javascripts/monitoring/mock_data.js b/spec/javascripts/monitoring/mock_data.js index ffc7148fde2..6d4ef960c1a 100644 --- a/spec/javascripts/monitoring/mock_data.js +++ b/spec/javascripts/monitoring/mock_data.js @@ -330,6 +330,11 @@ export const metricsGroupsAPIResponse = { weight: 1, queries: [ { + appearance: { + line: { + width: 2, + }, + }, query_range: 'avg(rate(container_cpu_usage_seconds_total{%{environment_filter}}[2m])) * 100', label: 'Core Usage', diff --git a/spec/javascripts/notes/components/note_actions_spec.js b/spec/javascripts/notes/components/note_actions_spec.js index d604e90b529..0cfcc994234 100644 --- a/spec/javascripts/notes/components/note_actions_spec.js +++ b/spec/javascripts/notes/components/note_actions_spec.js @@ -128,87 +128,33 @@ describe('noteActions', () => { }); }); - describe('with feature flag replyToIndividualNotes enabled', () => { + describe('for showReply = true', () => { beforeEach(() => { - gon.features = { - replyToIndividualNotes: true, - }; - }); - - afterEach(() => { - gon.features = {}; - }); - - describe('for showReply = true', () => { - beforeEach(() => { - wrapper = shallowMountNoteActions({ - ...props, - showReply: true, - }); - }); - - it('shows a reply button', () => { - const replyButton = wrapper.find({ ref: 'replyButton' }); - - expect(replyButton.exists()).toBe(true); + wrapper = shallowMountNoteActions({ + ...props, + showReply: true, }); }); - describe('for showReply = false', () => { - beforeEach(() => { - wrapper = shallowMountNoteActions({ - ...props, - showReply: false, - }); - }); - - it('does not show a reply button', () => { - const replyButton = wrapper.find({ ref: 'replyButton' }); + it('shows a reply button', () => { + const replyButton = wrapper.find({ ref: 'replyButton' }); - expect(replyButton.exists()).toBe(false); - }); + expect(replyButton.exists()).toBe(true); }); }); - describe('with feature flag replyToIndividualNotes disabled', () => { + describe('for showReply = false', () => { beforeEach(() => { - gon.features = { - replyToIndividualNotes: false, - }; - }); - - afterEach(() => { - gon.features = {}; - }); - - describe('for showReply = true', () => { - beforeEach(() => { - wrapper = shallowMountNoteActions({ - ...props, - showReply: true, - }); - }); - - it('does not show a reply button', () => { - const replyButton = wrapper.find({ ref: 'replyButton' }); - - expect(replyButton.exists()).toBe(false); + wrapper = shallowMountNoteActions({ + ...props, + showReply: false, }); }); - describe('for showReply = false', () => { - beforeEach(() => { - wrapper = shallowMountNoteActions({ - ...props, - showReply: false, - }); - }); - - it('does not show a reply button', () => { - const replyButton = wrapper.find({ ref: 'replyButton' }); + it('does not show a reply button', () => { + const replyButton = wrapper.find({ ref: 'replyButton' }); - expect(replyButton.exists()).toBe(false); - }); + expect(replyButton.exists()).toBe(false); }); }); }); diff --git a/spec/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js b/spec/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js new file mode 100644 index 00000000000..a89952ee435 --- /dev/null +++ b/spec/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js @@ -0,0 +1,167 @@ +import $ from 'jquery'; +import GLDropdown from '~/gl_dropdown'; // eslint-disable-line no-unused-vars +import TimezoneDropdown, { + formatUtcOffset, + formatTimezone, +} from '~/pages/projects/pipeline_schedules/shared/components/timezone_dropdown'; + +describe('Timezone Dropdown', function() { + preloadFixtures('pipeline_schedules/edit.html'); + + let $inputEl = null; + let $dropdownEl = null; + let $wrapper = null; + const tzListSel = '.dropdown-content ul li a.is-active'; + + describe('Initialize', () => { + describe('with dropdown already loaded', () => { + beforeEach(() => { + loadFixtures('pipeline_schedules/edit.html'); + $wrapper = $('.dropdown'); + $inputEl = $('#schedule_cron_timezone'); + $dropdownEl = $('.js-timezone-dropdown'); + + // eslint-disable-next-line no-new + new TimezoneDropdown({ + $inputEl, + $dropdownEl, + }); + }); + + it('can take an $inputEl in the constructor', () => { + const tzStr = '[UTC + 5.5] Sri Jayawardenepura'; + const tzValue = 'Asia/Colombo'; + + expect($inputEl.val()).toBe('UTC'); + + $(`${tzListSel}:contains('${tzStr}')`, $wrapper).trigger('click'); + + const val = $inputEl.val(); + + expect(val).toBe(tzValue); + expect(val).not.toBe('UTC'); + }); + + it('will format data array of timezones into a list of offsets', () => { + const data = $dropdownEl.data('data'); + const formatted = $wrapper.find(tzListSel).text(); + + data.forEach(item => { + expect(formatted).toContain(formatTimezone(item)); + }); + }); + + it('will default the timezone to UTC', () => { + const tz = $inputEl.val(); + + expect(tz).toBe('UTC'); + }); + }); + + describe('without dropdown loaded', () => { + beforeEach(() => { + loadFixtures('pipeline_schedules/edit.html'); + $wrapper = $('.dropdown'); + $inputEl = $('#schedule_cron_timezone'); + $dropdownEl = $('.js-timezone-dropdown'); + }); + + it('will populate the list of UTC offsets after the dropdown is loaded', () => { + expect($wrapper.find(tzListSel).length).toEqual(0); + + // eslint-disable-next-line no-new + new TimezoneDropdown({ + $inputEl, + $dropdownEl, + }); + + expect($wrapper.find(tzListSel).length).toEqual($($dropdownEl).data('data').length); + }); + + it('will call a provided handler when a new timezone is selected', () => { + const onSelectTimezone = jasmine.createSpy('onSelectTimezoneMock'); + // eslint-disable-next-line no-new + new TimezoneDropdown({ + $inputEl, + $dropdownEl, + onSelectTimezone, + }); + + $wrapper + .find(tzListSel) + .first() + .trigger('click'); + + expect(onSelectTimezone).toHaveBeenCalled(); + }); + }); + }); + + describe('formatUtcOffset', () => { + it('will convert negative utc offsets in seconds to hours and minutes', () => { + expect(formatUtcOffset(-21600)).toEqual('- 6'); + }); + + it('will convert positive utc offsets in seconds to hours and minutes', () => { + expect(formatUtcOffset(25200)).toEqual('+ 7'); + expect(formatUtcOffset(49500)).toEqual('+ 13.75'); + }); + + it('will return 0 when given a string', () => { + expect(formatUtcOffset('BLAH')).toEqual('0'); + expect(formatUtcOffset('$%$%')).toEqual('0'); + }); + + it('will return 0 when given an array', () => { + expect(formatUtcOffset(['an', 'array'])).toEqual('0'); + }); + + it('will return 0 when given an object', () => { + expect(formatUtcOffset({ some: '', object: '' })).toEqual('0'); + }); + + it('will return 0 when given null', () => { + expect(formatUtcOffset(null)).toEqual('0'); + }); + + it('will return 0 when given undefined', () => { + expect(formatUtcOffset(undefined)).toEqual('0'); + }); + + it('will return 0 when given empty input', () => { + expect(formatUtcOffset('')).toEqual('0'); + }); + }); + + describe('formatTimezone', () => { + it('given name: "Chatham Is.", offset: "49500", will format for display as "[UTC + 13.75] Chatham Is."', () => { + expect( + formatTimezone({ + name: 'Chatham Is.', + offset: 49500, + identifier: 'Pacific/Chatham', + }), + ).toEqual('[UTC + 13.75] Chatham Is.'); + }); + + it('given name: "Saskatchewan", offset: "-21600", will format for display as "[UTC - 6] Saskatchewan"', () => { + expect( + formatTimezone({ + name: 'Saskatchewan', + offset: -21600, + identifier: 'America/Regina', + }), + ).toEqual('[UTC - 6] Saskatchewan'); + }); + + it('given name: "Accra", offset: "0", will format for display as "[UTC 0] Accra"', () => { + expect( + formatTimezone({ + name: 'Accra', + offset: 0, + identifier: 'Africa/Accra', + }), + ).toEqual('[UTC 0] Accra'); + }); + }); +}); diff --git a/spec/javascripts/pdf/index_spec.js b/spec/javascripts/pdf/index_spec.js index 699cf4871aa..6df4ded92f0 100644 --- a/spec/javascripts/pdf/index_spec.js +++ b/spec/javascripts/pdf/index_spec.js @@ -1,11 +1,11 @@ import Vue from 'vue'; -import { PDFJS } from 'vendor/pdf'; +import { GlobalWorkerOptions } from 'vendor/pdf'; import workerSrc from 'vendor/pdf.worker.min'; import PDFLab from '~/pdf/index.vue'; import pdf from '../fixtures/blob/pdf/test.pdf'; -PDFJS.workerSrc = workerSrc; +GlobalWorkerOptions.workerSrc = workerSrc; const Component = Vue.extend(PDFLab); describe('PDF component', () => { diff --git a/spec/javascripts/pdf/page_spec.js b/spec/javascripts/pdf/page_spec.js index ef967210b65..b2e9fa42a63 100644 --- a/spec/javascripts/pdf/page_spec.js +++ b/spec/javascripts/pdf/page_spec.js @@ -12,7 +12,7 @@ describe('Page component', () => { let testPage; beforeEach(done => { - pdfjsLib.PDFJS.workerSrc = workerSrc; + pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc; pdfjsLib .getDocument(testPDF) .then(pdf => pdf.getPage(1)) diff --git a/spec/lib/api/entities/job_request/image_spec.rb b/spec/lib/api/entities/job_request/image_spec.rb new file mode 100644 index 00000000000..092c181ae9c --- /dev/null +++ b/spec/lib/api/entities/job_request/image_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe API::Entities::JobRequest::Image do + let(:ports) { [{ number: 80, protocol: 'http', name: 'name' }]} + let(:image) { double(name: 'image_name', entrypoint: ['foo'], ports: ports)} + let(:entity) { described_class.new(image) } + + subject { entity.as_json } + + it 'returns the image name' do + expect(subject[:name]).to eq 'image_name' + end + + it 'returns the entrypoint' do + expect(subject[:entrypoint]).to eq ['foo'] + end + + it 'returns the ports' do + expect(subject[:ports]).to eq ports + end + + context 'when the ports param is nil' do + let(:ports) { nil } + + it 'does not return the ports' do + expect(subject[:ports]).to be_nil + end + end +end diff --git a/spec/lib/api/entities/job_request/port_spec.rb b/spec/lib/api/entities/job_request/port_spec.rb new file mode 100644 index 00000000000..40ab4cd6231 --- /dev/null +++ b/spec/lib/api/entities/job_request/port_spec.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe ::API::Entities::JobRequest::Port do + let(:port) { double(number: 80, protocol: 'http', name: 'name')} + let(:entity) { described_class.new(port) } + + subject { entity.as_json } + + it 'returns the port number' do + expect(subject[:number]).to eq 80 + end + + it 'returns if the port protocol' do + expect(subject[:protocol]).to eq 'http' + end + + it 'returns the port name' do + expect(subject[:name]).to eq 'name' + end +end diff --git a/spec/lib/gitlab/ci/build/image_spec.rb b/spec/lib/gitlab/ci/build/image_spec.rb index 773a52cdfbc..6e20e0ef5c3 100644 --- a/spec/lib/gitlab/ci/build/image_spec.rb +++ b/spec/lib/gitlab/ci/build/image_spec.rb @@ -18,11 +18,16 @@ describe Gitlab::Ci::Build::Image do it 'populates fabricated object with the proper name attribute' do expect(subject.name).to eq(image_name) end + + it 'does not populate the ports' do + expect(subject.ports).to be_empty + end end context 'when image is defined as hash' do let(:entrypoint) { '/bin/sh' } - let(:job) { create(:ci_build, options: { image: { name: image_name, entrypoint: entrypoint } } ) } + + let(:job) { create(:ci_build, options: { image: { name: image_name, entrypoint: entrypoint, ports: [80] } } ) } it 'fabricates an object of the proper class' do is_expected.to be_kind_of(described_class) @@ -32,6 +37,13 @@ describe Gitlab::Ci::Build::Image do expect(subject.name).to eq(image_name) expect(subject.entrypoint).to eq(entrypoint) end + + it 'populates the ports' do + port = subject.ports.first + expect(port.number).to eq 80 + expect(port.protocol).to eq 'http' + expect(port.name).to eq 'default_port' + end end context 'when image name is empty' do @@ -67,6 +79,10 @@ describe Gitlab::Ci::Build::Image do expect(subject.first).to be_kind_of(described_class) expect(subject.first.name).to eq(service_image_name) end + + it 'does not populate the ports' do + expect(subject.first.ports).to be_empty + end end context 'when service is defined as hash' do @@ -75,7 +91,7 @@ describe Gitlab::Ci::Build::Image do let(:service_command) { 'sleep 30' } let(:job) do create(:ci_build, options: { services: [{ name: service_image_name, entrypoint: service_entrypoint, - alias: service_alias, command: service_command }] }) + alias: service_alias, command: service_command, ports: [80] }] }) end it 'fabricates an non-empty array of objects' do @@ -89,6 +105,11 @@ describe Gitlab::Ci::Build::Image do expect(subject.first.entrypoint).to eq(service_entrypoint) expect(subject.first.alias).to eq(service_alias) expect(subject.first.command).to eq(service_command) + + port = subject.first.ports.first + expect(port.number).to eq 80 + expect(port.protocol).to eq 'http' + expect(port.name).to eq 'default_port' end end diff --git a/spec/lib/gitlab/ci/build/policy/refs_spec.rb b/spec/lib/gitlab/ci/build/policy/refs_spec.rb index b4ddbf89b70..ec0450643c3 100644 --- a/spec/lib/gitlab/ci/build/policy/refs_spec.rb +++ b/spec/lib/gitlab/ci/build/policy/refs_spec.rb @@ -92,10 +92,23 @@ describe Gitlab::Ci::Build::Policy::Refs do .to be_satisfied_by(pipeline) end + it 'is satisfied when case-insensitive regexp matches pipeline ref' do + expect(described_class.new(['/DOCS-.*/i'])) + .to be_satisfied_by(pipeline) + end + it 'is not satisfied when regexp does not match pipeline ref' do expect(described_class.new(['/fix-.*/'])) .not_to be_satisfied_by(pipeline) end end + + context 'malicious regexp' do + let(:pipeline) { build_stubbed(:ci_pipeline, ref: malicious_text) } + + subject { described_class.new([malicious_regexp_ruby]) } + + include_examples 'malicious regexp' + end end end diff --git a/spec/lib/gitlab/ci/build/port_spec.rb b/spec/lib/gitlab/ci/build/port_spec.rb new file mode 100644 index 00000000000..1413780dfa6 --- /dev/null +++ b/spec/lib/gitlab/ci/build/port_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Ci::Build::Port do + subject { described_class.new(port) } + + context 'when port is defined as an integer' do + let(:port) { 80 } + + it 'populates the object' do + expect(subject.number).to eq 80 + expect(subject.protocol).to eq described_class::DEFAULT_PORT_PROTOCOL + expect(subject.name).to eq described_class::DEFAULT_PORT_NAME + end + end + + context 'when port is defined as hash' do + let(:port) { { number: 80, protocol: 'https', name: 'port_name' } } + + it 'populates the object' do + expect(subject.number).to eq 80 + expect(subject.protocol).to eq 'https' + expect(subject.name).to eq 'port_name' + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/image_spec.rb b/spec/lib/gitlab/ci/config/entry/image_spec.rb index 1a4d9ed5517..1ebdda398b9 100644 --- a/spec/lib/gitlab/ci/config/entry/image_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/image_spec.rb @@ -35,6 +35,12 @@ describe Gitlab::Ci::Config::Entry::Image do expect(entry.entrypoint).to be_nil end end + + describe '#ports' do + it "returns image's ports" do + expect(entry.ports).to be_nil + end + end end context 'when configuration is a hash' do @@ -69,6 +75,38 @@ describe Gitlab::Ci::Config::Entry::Image do expect(entry.entrypoint).to eq %w(/bin/sh run) end end + + context 'when configuration has ports' do + let(:ports) { [{ number: 80, protocol: 'http', name: 'foobar' }] } + let(:config) { { name: 'ruby:2.2', entrypoint: %w(/bin/sh run), ports: ports } } + let(:entry) { described_class.new(config, { with_image_ports: image_ports }) } + let(:image_ports) { false } + + context 'when with_image_ports metadata is not enabled' do + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + expect(entry.errors).to include("image config contains disallowed keys: ports") + end + end + end + + context 'when with_image_ports metadata is enabled' do + let(:image_ports) { true } + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + + describe '#ports' do + it "returns image's ports" do + expect(entry.ports).to eq ports + end + end + end + end end context 'when entry value is not correct' do @@ -76,8 +114,8 @@ describe Gitlab::Ci::Config::Entry::Image do describe '#errors' do it 'saves errors' do - expect(entry.errors) - .to include 'image config should be a hash or a string' + expect(entry.errors.first) + .to match /config should be a hash or a string/ end end @@ -93,8 +131,8 @@ describe Gitlab::Ci::Config::Entry::Image do describe '#errors' do it 'saves errors' do - expect(entry.errors) - .to include 'image config contains unknown keys: non_existing' + expect(entry.errors.first) + .to match /config contains unknown keys: non_existing/ end end diff --git a/spec/lib/gitlab/ci/config/entry/port_spec.rb b/spec/lib/gitlab/ci/config/entry/port_spec.rb new file mode 100644 index 00000000000..5f8f294334e --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/port_spec.rb @@ -0,0 +1,173 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Port do + let(:entry) { described_class.new(config) } + + before do + entry.compose! + end + + context 'when configuration is a string' do + let(:config) { 80 } + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + + describe '#value' do + it 'returns valid hash' do + expect(entry.value).to eq(number: 80) + end + end + + describe '#number' do + it "returns port number" do + expect(entry.number).to eq 80 + end + end + + describe '#protocol' do + it "is nil" do + expect(entry.protocol).to be_nil + end + end + + describe '#name' do + it "is nil" do + expect(entry.name).to be_nil + end + end + end + + context 'when configuration is a hash' do + context 'with the complete hash' do + let(:config) do + { number: 80, + protocol: 'http', + name: 'foobar' } + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + + describe '#value' do + it 'returns valid hash' do + expect(entry.value).to eq config + end + end + + describe '#number' do + it "returns port number" do + expect(entry.number).to eq 80 + end + end + + describe '#protocol' do + it "returns port protocol" do + expect(entry.protocol).to eq 'http' + end + end + + describe '#name' do + it "returns port name" do + expect(entry.name).to eq 'foobar' + end + end + end + + context 'with only the port number' do + let(:config) { { number: 80 } } + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + + describe '#value' do + it 'returns valid hash' do + expect(entry.value).to eq(number: 80) + end + end + + describe '#number' do + it "returns port number" do + expect(entry.number).to eq 80 + end + end + + describe '#protocol' do + it "is nil" do + expect(entry.protocol).to be_nil + end + end + + describe '#name' do + it "is nil" do + expect(entry.name).to be_nil + end + end + end + + context 'without the number' do + let(:config) { { protocol: 'http' } } + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + end + end + + context 'when configuration is invalid' do + let(:config) { '80' } + + describe '#valid?' do + it 'is valid' do + expect(entry).not_to be_valid + end + end + end + + context 'when protocol' do + let(:config) { { number: 80, protocol: protocol, name: 'foobar' } } + + context 'is http' do + let(:protocol) { 'http' } + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'is https' do + let(:protocol) { 'https' } + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'is neither http nor https' do + let(:protocol) { 'foo' } + + describe '#valid?' do + it 'is invalid' do + expect(entry.errors).to include("port protocol should be http or https") + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/ports_spec.rb b/spec/lib/gitlab/ci/config/entry/ports_spec.rb new file mode 100644 index 00000000000..2063bd1d86c --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/ports_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Ports do + let(:entry) { described_class.new(config) } + + before do + entry.compose! + end + + context 'when configuration is valid' do + let(:config) { [{ number: 80, protocol: 'http', name: 'foobar' }] } + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + + describe '#value' do + it 'returns valid array' do + expect(entry.value).to eq(config) + end + end + end + + context 'when configuration is invalid' do + let(:config) { 'postgresql:9.5' } + + describe '#valid?' do + it 'is invalid' do + expect(entry).not_to be_valid + end + end + + context 'when any of the ports' do + before do + expect(entry).not_to be_valid + expect(entry.errors.count).to eq 1 + end + + context 'have the same name' do + let(:config) do + [{ number: 80, protocol: 'http', name: 'foobar' }, + { number: 81, protocol: 'http', name: 'foobar' }] + end + + describe '#valid?' do + it 'is invalid' do + expect(entry.errors.first).to match /each port name must be different/ + end + end + end + + context 'have the same port' do + let(:config) do + [{ number: 80, protocol: 'http', name: 'foobar' }, + { number: 80, protocol: 'http', name: 'foobar1' }] + end + + describe '#valid?' do + it 'is invalid' do + expect(entry.errors.first).to match /each port number can only be referenced once/ + end + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/service_spec.rb b/spec/lib/gitlab/ci/config/entry/service_spec.rb index 9ebf947a751..d5bd139b5f1 100644 --- a/spec/lib/gitlab/ci/config/entry/service_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/service_spec.rb @@ -39,6 +39,12 @@ describe Gitlab::Ci::Config::Entry::Service do expect(entry.command).to be_nil end end + + describe '#ports' do + it "returns service's ports" do + expect(entry.ports).to be_nil + end + end end context 'when configuration is a hash' do @@ -81,6 +87,40 @@ describe Gitlab::Ci::Config::Entry::Service do expect(entry.entrypoint).to eq %w(/bin/sh run) end end + + context 'when configuration has ports' do + let(:ports) { [{ number: 80, protocol: 'http', name: 'foobar' }] } + let(:config) do + { name: 'postgresql:9.5', alias: 'db', command: %w(cmd run), entrypoint: %w(/bin/sh run), ports: ports } + end + let(:entry) { described_class.new(config, { with_image_ports: image_ports }) } + let(:image_ports) { false } + + context 'when with_image_ports metadata is not enabled' do + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + expect(entry.errors).to include("service config contains disallowed keys: ports") + end + end + end + + context 'when with_image_ports metadata is enabled' do + let(:image_ports) { true } + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + + describe '#ports' do + it "returns image's ports" do + expect(entry.ports).to eq ports + end + end + end + end end context 'when entry value is not correct' do @@ -88,8 +128,8 @@ describe Gitlab::Ci::Config::Entry::Service do describe '#errors' do it 'saves errors' do - expect(entry.errors) - .to include 'service config should be a hash or a string' + expect(entry.errors.first) + .to match /config should be a hash or a string/ end end @@ -105,8 +145,8 @@ describe Gitlab::Ci::Config::Entry::Service do describe '#errors' do it 'saves errors' do - expect(entry.errors) - .to include 'service config contains unknown keys: non_existing' + expect(entry.errors.first) + .to match /config contains unknown keys: non_existing/ end end @@ -116,4 +156,26 @@ describe Gitlab::Ci::Config::Entry::Service do end end end + + context 'when service has ports' do + let(:ports) { [{ number: 80, protocol: 'http', name: 'foobar' }] } + let(:config) do + { name: 'postgresql:9.5', command: %w(cmd run), entrypoint: %w(/bin/sh run), ports: ports } + end + + it 'alias field is mandatory' do + expect(entry).not_to be_valid + expect(entry.errors).to include("service alias can't be blank") + end + end + + context 'when service does not have ports' do + let(:config) do + { name: 'postgresql:9.5', alias: 'db', command: %w(cmd run), entrypoint: %w(/bin/sh run) } + end + + it 'alias field is optional' do + expect(entry).to be_valid + end + end end diff --git a/spec/lib/gitlab/ci/config/entry/services_spec.rb b/spec/lib/gitlab/ci/config/entry/services_spec.rb index 7c4319aee63..d5a1316f665 100644 --- a/spec/lib/gitlab/ci/config/entry/services_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/services_spec.rb @@ -32,4 +32,91 @@ describe Gitlab::Ci::Config::Entry::Services do end end end + + context 'when configuration has ports' do + let(:ports) { [{ number: 80, protocol: 'http', name: 'foobar' }] } + let(:config) { ['postgresql:9.5', { name: 'postgresql:9.1', alias: 'postgres_old', ports: ports }] } + let(:entry) { described_class.new(config, { with_image_ports: image_ports }) } + let(:image_ports) { false } + + context 'when with_image_ports metadata is not enabled' do + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + expect(entry.errors).to include("service config contains disallowed keys: ports") + end + end + end + + context 'when with_image_ports metadata is enabled' do + let(:image_ports) { true } + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + + describe '#value' do + it 'returns valid array' do + expect(entry.value).to eq([{ name: 'postgresql:9.5' }, { name: 'postgresql:9.1', alias: 'postgres_old', ports: ports }]) + end + end + + describe 'services alias' do + context 'when they are not unique' do + let(:config) do + ['postgresql:9.5', + { name: 'postgresql:9.1', alias: 'postgres_old', ports: [80] }, + { name: 'ruby', alias: 'postgres_old', ports: [81] }] + end + + describe '#valid?' do + it 'is invalid' do + expect(entry).not_to be_valid + expect(entry.errors).to include("services config alias must be unique in services with ports") + end + end + end + + context 'when they are unique' do + let(:config) do + ['postgresql:9.5', + { name: 'postgresql:9.1', alias: 'postgres_old', ports: [80] }, + { name: 'ruby', alias: 'ruby', ports: [81] }] + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when one of the duplicated alias is in a service without ports' do + let(:config) do + ['postgresql:9.5', + { name: 'postgresql:9.1', alias: 'postgres_old', ports: [80] }, + { name: 'ruby', alias: 'postgres_old' }] + end + + it 'is valid' do + expect(entry).to be_valid + end + end + + context 'when there are not any ports' do + let(:config) do + ['postgresql:9.5', + { name: 'postgresql:9.1', alias: 'postgres_old' }, + { name: 'ruby', alias: 'postgres_old' }] + end + + it 'is valid' do + expect(entry).to be_valid + end + end + end + end + end end diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb index 18f255c1ab7..00b2753c5fc 100644 --- a/spec/lib/gitlab/ci/config_spec.rb +++ b/spec/lib/gitlab/ci/config_spec.rb @@ -123,6 +123,63 @@ describe Gitlab::Ci::Config do ) end end + + context 'when ports have been set' do + context 'in the main image' do + let(:yml) do + <<-EOS + image: + name: ruby:2.2 + ports: + - 80 + EOS + end + + it 'raises an error' do + expect(config.errors).to include("image config contains disallowed keys: ports") + end + end + + context 'in the job image' do + let(:yml) do + <<-EOS + image: ruby:2.2 + + test: + script: rspec + image: + name: ruby:2.2 + ports: + - 80 + EOS + end + + it 'raises an error' do + expect(config.errors).to include("jobs:test:image config contains disallowed keys: ports") + end + end + + context 'in the services' do + let(:yml) do + <<-EOS + image: ruby:2.2 + + test: + script: rspec + image: ruby:2.2 + services: + - name: test + alias: test + ports: + - 80 + EOS + end + + it 'raises an error' do + expect(config.errors).to include("jobs:test:services:service config contains disallowed keys: ports") + end + end + end end context "when using 'include' directive" do diff --git a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb index dab0fb51bcc..5181e9c1583 100644 --- a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb @@ -48,6 +48,24 @@ describe Gitlab::Ci::Pipeline::Chain::Command do end end + describe '#merge_request_ref_exists?' do + subject { command.merge_request_ref_exists? } + + let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) } + + context 'for existing merge request ref' do + let(:origin_ref) { merge_request.ref_path } + + it { is_expected.to eq(true) } + end + + context 'for branch ref' do + let(:origin_ref) { merge_request.source_branch } + + it { is_expected.to eq(false) } + end + end + describe '#ref' do subject { command.ref } diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/abilities_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/abilities_spec.rb index 8ba56d73838..7d750877d09 100644 --- a/spec/lib/gitlab/ci/pipeline/chain/validate/abilities_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/chain/validate/abilities_spec.rb @@ -10,12 +10,33 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Abilities do let(:command) do Gitlab::Ci::Pipeline::Chain::Command.new( - project: project, current_user: user, origin_ref: ref) + project: project, current_user: user, origin_ref: origin_ref, merge_request: merge_request) end let(:step) { described_class.new(pipeline, command) } let(:ref) { 'master' } + let(:origin_ref) { ref } + let(:merge_request) { nil } + + shared_context 'detached merge request pipeline' do + let(:merge_request) do + create(:merge_request, + source_project: project, + source_branch: ref, + target_project: project, + target_branch: 'feature') + end + + let(:pipeline) do + build(:ci_pipeline, + source: :merge_request_event, + merge_request: merge_request, + project: project) + end + + let(:origin_ref) { merge_request.ref_path } + end context 'when users has no ability to run a pipeline' do before do @@ -58,6 +79,12 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Abilities do it { is_expected.to be_truthy } + context 'when pipeline is a detached merge request pipeline' do + include_context 'detached merge request pipeline' + + it { is_expected.to be_truthy } + end + context 'when the branch is protected' do let!(:protected_branch) do create(:protected_branch, project: project, name: ref) @@ -65,6 +92,12 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Abilities do it { is_expected.to be_falsey } + context 'when pipeline is a detached merge request pipeline' do + include_context 'detached merge request pipeline' + + it { is_expected.to be_falsey } + end + context 'when developers are allowed to merge' do let!(:protected_branch) do create(:protected_branch, @@ -74,6 +107,12 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Abilities do end it { is_expected.to be_truthy } + + context 'when pipeline is a detached merge request pipeline' do + include_context 'detached merge request pipeline' + + it { is_expected.to be_truthy } + end end end @@ -112,6 +151,12 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Abilities do end it { is_expected.to be_truthy } + + context 'when pipeline is a detached merge request pipeline' do + include_context 'detached merge request pipeline' + + it { is_expected.to be_truthy } + end end context 'when the tag is protected' do diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb index a7cad423d09..2e8c9d70098 100644 --- a/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb @@ -42,6 +42,25 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Repository do end end + context 'when origin ref is a merge request ref' do + let(:command) do + Gitlab::Ci::Pipeline::Chain::Command.new( + project: project, current_user: user, origin_ref: origin_ref, checkout_sha: checkout_sha) + end + + let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } + let(:origin_ref) { merge_request.ref_path } + let(:checkout_sha) { project.repository.commit(merge_request.ref_path).id } + + it 'does not break the chain' do + expect(step.break?).to be false + end + + it 'does not append pipeline errors' do + expect(pipeline.errors).to be_empty + end + end + context 'when ref is ambiguous' do let(:project) do create(:project, :repository).tap do |proj| diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/pattern_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/pattern_spec.rb index 3ebc2e94727..cff7f57ceff 100644 --- a/spec/lib/gitlab/ci/pipeline/expression/lexeme/pattern_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/pattern_spec.rb @@ -85,7 +85,7 @@ describe Gitlab::Ci::Pipeline::Expression::Lexeme::Pattern do end it 'raises error if evaluated regexp is not valid' do - allow(Gitlab::UntrustedRegexp).to receive(:valid?).and_return(true) + allow(Gitlab::UntrustedRegexp::RubySyntax).to receive(:valid?).and_return(true) regexp = described_class.new('/invalid ( .*/') diff --git a/spec/lib/gitlab/ci/templates/templates_spec.rb b/spec/lib/gitlab/ci/templates/templates_spec.rb index fbbd58280a9..e20a621168c 100644 --- a/spec/lib/gitlab/ci/templates/templates_spec.rb +++ b/spec/lib/gitlab/ci/templates/templates_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe "CI YML Templates" do ABSTRACT_TEMPLATES = %w[Serverless].freeze + PROJECT_DEPENDENT_TEMPLATES = %w[Auto-DevOps].freeze def self.concrete_templates Gitlab::Template::GitlabCiYmlTemplate.all.reject do |template| @@ -20,7 +21,10 @@ describe "CI YML Templates" do describe 'concrete templates with CI/CD jobs' do concrete_templates.each do |template| it "#{template.name} template should be valid" do - expect { Gitlab::Ci::YamlProcessor.new(template.content) } + # Trigger processing of included files + project = create(:project, :test_repo) if PROJECT_DEPENDENT_TEMPLATES.include?(template.name) + + expect { Gitlab::Ci::YamlProcessor.new(template.content, project: project) } .not_to raise_error end end diff --git a/spec/lib/gitlab/ci/trace/stream_spec.rb b/spec/lib/gitlab/ci/trace/stream_spec.rb index 38626f728d7..e45ea1c2528 100644 --- a/spec/lib/gitlab/ci/trace/stream_spec.rb +++ b/spec/lib/gitlab/ci/trace/stream_spec.rb @@ -414,7 +414,7 @@ describe Gitlab::Ci::Trace::Stream, :clean_gitlab_redis_cache do context 'malicious regexp' do let(:data) { malicious_text } - let(:regex) { malicious_regexp } + let(:regex) { malicious_regexp_re2 } include_examples 'malicious regexp' end diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb index 29638ef47c5..63a0d54dcfc 100644 --- a/spec/lib/gitlab/ci/yaml_processor_spec.rb +++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb @@ -1233,7 +1233,7 @@ module Gitlab config = YAML.dump({ services: [10, "test"], rspec: { script: "test" } }) expect do Gitlab::Ci::YamlProcessor.new(config) - end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "service config should be a hash or a string") + end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "services:service config should be a hash or a string") end it "returns errors if job services parameter is not an array" do @@ -1247,7 +1247,7 @@ module Gitlab config = YAML.dump({ rspec: { script: "test", services: [10, "test"] } }) expect do Gitlab::Ci::YamlProcessor.new(config) - end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "service config should be a hash or a string") + end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:services:service config should be a hash or a string") end it "returns error if job configuration is invalid" do diff --git a/spec/lib/gitlab/current_settings_spec.rb b/spec/lib/gitlab/current_settings_spec.rb index 17d5eae24f5..909dbffa38f 100644 --- a/spec/lib/gitlab/current_settings_spec.rb +++ b/spec/lib/gitlab/current_settings_spec.rb @@ -115,9 +115,8 @@ describe Gitlab::CurrentSettings do shared_examples 'a non-persisted ApplicationSetting object' do let(:current_settings) { described_class.current_application_settings } - it 'returns a non-persisted ApplicationSetting object' do - expect(current_settings).to be_a(ApplicationSetting) - expect(current_settings).not_to be_persisted + it 'returns a FakeApplicationSettings object' do + expect(current_settings).to be_a(Gitlab::FakeApplicationSettings) end it 'uses the default value from ApplicationSetting.defaults' do @@ -146,6 +145,16 @@ describe Gitlab::CurrentSettings do it 'uses the value from the DB attribute if present and not overridden by an accessor' do expect(current_settings.home_page_url).to eq(db_settings.home_page_url) end + + context 'when a new column is used before being migrated' do + before do + allow(ApplicationSetting).to receive(:defaults).and_return({ foo: 'bar' }) + end + + it 'uses the default value if present' do + expect(current_settings.foo).to eq('bar') + end + end end end diff --git a/spec/lib/gitlab/encoding_helper_spec.rb b/spec/lib/gitlab/encoding_helper_spec.rb index 429816efec3..88ea98eb1e1 100644 --- a/spec/lib/gitlab/encoding_helper_spec.rb +++ b/spec/lib/gitlab/encoding_helper_spec.rb @@ -189,14 +189,23 @@ describe Gitlab::EncodingHelper do end end - describe '#binary_stringio' do + describe '#binary_io' do it 'does not mutate the original string encoding' do test = 'my-test' - io_stream = ext_class.binary_stringio(test) + io_stream = ext_class.binary_io(test) expect(io_stream.external_encoding.name).to eq('ASCII-8BIT') expect(test.encoding.name).to eq('UTF-8') end + + it 'returns a copy of the IO with the correct encoding' do + test = fixture_file_upload('spec/fixtures/doc_sample.txt').to_io + + io_stream = ext_class.binary_io(test) + + expect(io_stream.external_encoding.name).to eq('ASCII-8BIT') + expect(test).not_to eq(io_stream) + end end end diff --git a/spec/lib/gitlab/git/tree_spec.rb b/spec/lib/gitlab/git/tree_spec.rb index 60060c41616..7ad3cde97f8 100644 --- a/spec/lib/gitlab/git/tree_spec.rb +++ b/spec/lib/gitlab/git/tree_spec.rb @@ -19,7 +19,7 @@ describe Gitlab::Git::Tree, :seed_helper do it 'returns a list of tree objects' do entries = described_class.where(repository, SeedRepo::Commit::ID, 'files', true) - expect(entries.count).to be > 10 + expect(entries.count).to be >= 5 expect(entries).to all(be_a(Gitlab::Git::Tree)) end diff --git a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb index d7bd757149d..6d6107ca3e7 100644 --- a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb +++ b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb @@ -221,6 +221,21 @@ describe Gitlab::GitalyClient::CommitService do expect(commit).to eq(commit_dbl) end end + + context 'when caching of the ref name is enabled' do + it 'returns a cached commit' do + expect_any_instance_of(Gitaly::CommitService::Stub).to receive(:find_commit).once.and_return(double(commit: commit_dbl)) + + commit = nil + 2.times do + ::Gitlab::GitalyClient.allow_ref_name_caching do + commit = described_class.new(repository).find_commit('master') + end + end + + expect(commit).to eq(commit_dbl) + end + end end end diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 496567b0036..d0ed588f05f 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -11,6 +11,7 @@ Issue: - branch_name - description - state +- state_id - iid - updated_by_id - confidential @@ -158,6 +159,7 @@ MergeRequest: - created_at - updated_at - state +- state_id - merge_status - target_project_id - iid diff --git a/spec/lib/gitlab/quick_actions/command_definition_spec.rb b/spec/lib/gitlab/quick_actions/command_definition_spec.rb index 136cfb5bcc5..b6e0adbc1c2 100644 --- a/spec/lib/gitlab/quick_actions/command_definition_spec.rb +++ b/spec/lib/gitlab/quick_actions/command_definition_spec.rb @@ -69,6 +69,36 @@ describe Gitlab::QuickActions::CommandDefinition do expect(subject.available?(opts)).to be true end end + + context "when the command has types" do + before do + subject.types = [Issue, Commit] + end + + context "when the command target type is allowed" do + it "returns true" do + opts[:quick_action_target] = Issue.new + expect(subject.available?(opts)).to be true + end + end + + context "when the command target type is not allowed" do + it "returns true" do + opts[:quick_action_target] = MergeRequest.new + expect(subject.available?(opts)).to be false + end + end + end + + context "when the command has no types" do + it "any target type is allowed" do + opts[:quick_action_target] = Issue.new + expect(subject.available?(opts)).to be true + + opts[:quick_action_target] = MergeRequest.new + expect(subject.available?(opts)).to be true + end + end end describe "#execute" do diff --git a/spec/lib/gitlab/quick_actions/dsl_spec.rb b/spec/lib/gitlab/quick_actions/dsl_spec.rb index fd4df8694ba..185adab1ff6 100644 --- a/spec/lib/gitlab/quick_actions/dsl_spec.rb +++ b/spec/lib/gitlab/quick_actions/dsl_spec.rb @@ -48,13 +48,19 @@ describe Gitlab::QuickActions::Dsl do substitution :something do |text| "#{text} Some complicated thing you want in here" end + + desc 'A command with types' + types Issue, Commit + command :has_types do + "Has Issue and Commit types" + end end end describe '.command_definitions' do it 'returns an array with commands definitions' do no_args_def, explanation_with_aliases_def, dynamic_description_def, - cc_def, cond_action_def, with_params_parsing_def, substitution_def = + cc_def, cond_action_def, with_params_parsing_def, substitution_def, has_types = DummyClass.command_definitions expect(no_args_def.name).to eq(:no_args) @@ -63,6 +69,7 @@ describe Gitlab::QuickActions::Dsl do expect(no_args_def.explanation).to eq('') expect(no_args_def.params).to eq([]) expect(no_args_def.condition_block).to be_nil + expect(no_args_def.types).to eq([]) expect(no_args_def.action_block).to be_a_kind_of(Proc) expect(no_args_def.parse_params_block).to be_nil expect(no_args_def.warning).to eq('') @@ -73,6 +80,7 @@ describe Gitlab::QuickActions::Dsl do expect(explanation_with_aliases_def.explanation).to eq('Static explanation') expect(explanation_with_aliases_def.params).to eq(['The first argument']) expect(explanation_with_aliases_def.condition_block).to be_nil + expect(explanation_with_aliases_def.types).to eq([]) expect(explanation_with_aliases_def.action_block).to be_a_kind_of(Proc) expect(explanation_with_aliases_def.parse_params_block).to be_nil expect(explanation_with_aliases_def.warning).to eq('Possible problem!') @@ -83,6 +91,7 @@ describe Gitlab::QuickActions::Dsl do expect(dynamic_description_def.explanation).to eq('') expect(dynamic_description_def.params).to eq(['The first argument', 'The second argument']) expect(dynamic_description_def.condition_block).to be_nil + expect(dynamic_description_def.types).to eq([]) expect(dynamic_description_def.action_block).to be_a_kind_of(Proc) expect(dynamic_description_def.parse_params_block).to be_nil expect(dynamic_description_def.warning).to eq('') @@ -93,6 +102,7 @@ describe Gitlab::QuickActions::Dsl do expect(cc_def.explanation).to eq('') expect(cc_def.params).to eq([]) expect(cc_def.condition_block).to be_nil + expect(cc_def.types).to eq([]) expect(cc_def.action_block).to be_nil expect(cc_def.parse_params_block).to be_nil expect(cc_def.warning).to eq('') @@ -103,6 +113,7 @@ describe Gitlab::QuickActions::Dsl do expect(cond_action_def.explanation).to be_a_kind_of(Proc) expect(cond_action_def.params).to eq([]) expect(cond_action_def.condition_block).to be_a_kind_of(Proc) + expect(cond_action_def.types).to eq([]) expect(cond_action_def.action_block).to be_a_kind_of(Proc) expect(cond_action_def.parse_params_block).to be_nil expect(cond_action_def.warning).to eq('') @@ -113,6 +124,7 @@ describe Gitlab::QuickActions::Dsl do expect(with_params_parsing_def.explanation).to eq('') expect(with_params_parsing_def.params).to eq([]) expect(with_params_parsing_def.condition_block).to be_nil + expect(with_params_parsing_def.types).to eq([]) expect(with_params_parsing_def.action_block).to be_a_kind_of(Proc) expect(with_params_parsing_def.parse_params_block).to be_a_kind_of(Proc) expect(with_params_parsing_def.warning).to eq('') @@ -123,9 +135,21 @@ describe Gitlab::QuickActions::Dsl do expect(substitution_def.explanation).to eq('') expect(substitution_def.params).to eq(['<Comment>']) expect(substitution_def.condition_block).to be_nil + expect(substitution_def.types).to eq([]) expect(substitution_def.action_block.call('text')).to eq('text Some complicated thing you want in here') expect(substitution_def.parse_params_block).to be_nil expect(substitution_def.warning).to eq('') + + expect(has_types.name).to eq(:has_types) + expect(has_types.aliases).to eq([]) + expect(has_types.description).to eq('A command with types') + expect(has_types.explanation).to eq('') + expect(has_types.params).to eq([]) + expect(has_types.condition_block).to be_nil + expect(has_types.types).to eq([Issue, Commit]) + expect(has_types.action_block).to be_a_kind_of(Proc) + expect(has_types.parse_params_block).to be_nil + expect(has_types.warning).to eq('') end end end diff --git a/spec/lib/gitlab/route_map_spec.rb b/spec/lib/gitlab/route_map_spec.rb index d672f7b5675..a39c774429e 100644 --- a/spec/lib/gitlab/route_map_spec.rb +++ b/spec/lib/gitlab/route_map_spec.rb @@ -60,7 +60,7 @@ describe Gitlab::RouteMap do subject do map = described_class.new(<<-"MAP".strip_heredoc) - - source: '#{malicious_regexp}' + - source: '#{malicious_regexp_re2}' public: '/' MAP diff --git a/spec/lib/gitlab/sanitizers/exif_spec.rb b/spec/lib/gitlab/sanitizers/exif_spec.rb new file mode 100644 index 00000000000..bd5f330c7a1 --- /dev/null +++ b/spec/lib/gitlab/sanitizers/exif_spec.rb @@ -0,0 +1,120 @@ +require 'spec_helper' + +describe Gitlab::Sanitizers::Exif do + let(:sanitizer) { described_class.new } + + describe '#batch_clean' do + context 'with image uploads' do + let!(:uploads) { create_list(:upload, 3, :with_file, :issuable_upload) } + + it 'processes all uploads if range ID is not set' do + expect(sanitizer).to receive(:clean).exactly(3).times + + sanitizer.batch_clean + end + + it 'processes only uploads in the selected range' do + expect(sanitizer).to receive(:clean).once + + sanitizer.batch_clean(start_id: uploads[1].id, stop_id: uploads[1].id) + end + + it 'pauses if sleep_time is set' do + expect(sanitizer).to receive(:sleep).exactly(3).times.with(1.second) + expect(sanitizer).to receive(:clean).exactly(3).times + + sanitizer.batch_clean(sleep_time: 1) + end + end + + it 'filters only jpg/tiff images' do + create(:upload, path: 'filename.jpg') + create(:upload, path: 'filename.jpeg') + create(:upload, path: 'filename.JPG') + create(:upload, path: 'filename.tiff') + create(:upload, path: 'filename.TIFF') + create(:upload, path: 'filename.png') + create(:upload, path: 'filename.txt') + + expect(sanitizer).to receive(:clean).exactly(5).times + sanitizer.batch_clean + end + end + + describe '#clean' do + let(:uploader) { create(:upload, :with_file, :issuable_upload).build_uploader } + + context "no dry run" do + it "removes exif from the image" do + uploader.store!(fixture_file_upload('spec/fixtures/rails_sample.jpg')) + + original_upload = uploader.upload + expected_args = ["exiftool", "-all=", "-tagsFromFile", "@", *Gitlab::Sanitizers::Exif::EXCLUDE_PARAMS, "--IPTC:all", "--XMP-iptcExt:all", kind_of(String)] + + expect(sanitizer).to receive(:extra_tags).and_return(["", 0]) + expect(sanitizer).to receive(:exec_remove_exif!).once.and_call_original + expect(uploader).to receive(:store!).and_call_original + expect(Gitlab::Popen).to receive(:popen).with(expected_args) do |args| + File.write("#{args.last}_original", "foo") if args.last.start_with?(Dir.tmpdir) + + [expected_args, 0] + end + + sanitizer.clean(uploader, dry_run: false) + + expect(uploader.upload.id).not_to eq(original_upload.id) + expect(uploader.upload.path).to eq(original_upload.path) + end + + it "ignores image without exif" do + expected_args = ["exiftool", "-all", "-j", "-sort", "--IPTC:all", "--XMP-iptcExt:all", kind_of(String)] + + expect(Gitlab::Popen).to receive(:popen).with(expected_args).and_return(["[{}]", 0]) + expect(sanitizer).not_to receive(:exec_remove_exif!) + expect(uploader).not_to receive(:store!) + + sanitizer.clean(uploader, dry_run: false) + end + + it "raises an error if the exiftool fails with an error" do + expect(Gitlab::Popen).to receive(:popen).and_return(["error", 1]) + + expect { sanitizer.clean(uploader, dry_run: false) }.to raise_exception(RuntimeError, "failed to get exif tags: error") + end + end + + context "dry run" do + it "doesn't change the image" do + expect(sanitizer).to receive(:extra_tags).and_return({ 'foo' => 'bar' }) + expect(sanitizer).not_to receive(:exec_remove_exif!) + expect(uploader).not_to receive(:store!) + + sanitizer.clean(uploader, dry_run: true) + end + end + end + + describe "#extra_tags" do + it "returns a list of keys for exif file" do + tags = '[{ + "DigitalSourceType": "some source", + "ImageHeight": 654 + }]' + + expect(Gitlab::Popen).to receive(:popen).and_return([tags, 0]) + + expect(sanitizer.extra_tags('filename')).not_to be_empty + end + + it "returns an empty list for file with only whitelisted and ignored tags" do + tags = '[{ + "ImageHeight": 654, + "Megapixels": 0.641 + }]' + + expect(Gitlab::Popen).to receive(:popen).and_return([tags, 0]) + + expect(sanitizer.extra_tags('some file')).to be_empty + end + end +end diff --git a/spec/lib/gitlab/untrusted_regexp/ruby_syntax_spec.rb b/spec/lib/gitlab/untrusted_regexp/ruby_syntax_spec.rb new file mode 100644 index 00000000000..005d41580de --- /dev/null +++ b/spec/lib/gitlab/untrusted_regexp/ruby_syntax_spec.rb @@ -0,0 +1,72 @@ +require 'fast_spec_helper' +require 'support/shared_examples/malicious_regexp_shared_examples' + +describe Gitlab::UntrustedRegexp::RubySyntax do + describe '.matches_syntax?' do + it 'returns true if regexp is valid' do + expect(described_class.matches_syntax?('/some .* thing/')) + .to be true + end + + it 'returns true if regexp is invalid, but resembles regexp' do + expect(described_class.matches_syntax?('/some ( thing/')) + .to be true + end + end + + describe '.valid?' do + it 'returns true if regexp is valid' do + expect(described_class.valid?('/some .* thing/')) + .to be true + end + + it 'returns false if regexp is invalid' do + expect(described_class.valid?('/some ( thing/')) + .to be false + end + end + + describe '.fabricate' do + context 'when regexp is valid' do + it 'fabricates regexp without flags' do + expect(described_class.fabricate('/some .* thing/')).not_to be_nil + end + end + + context 'when regexp is a raw pattern' do + it 'returns error' do + expect(described_class.fabricate('some .* thing')).to be_nil + end + end + end + + describe '.fabricate!' do + context 'when regexp is using /regexp/ scheme with flags' do + it 'fabricates regexp with a single flag' do + regexp = described_class.fabricate!('/something/i') + + expect(regexp).to eq Gitlab::UntrustedRegexp.new('(?i)something') + expect(regexp.scan('SOMETHING')).to be_one + end + + it 'fabricates regexp with multiple flags' do + regexp = described_class.fabricate!('/something/im') + + expect(regexp).to eq Gitlab::UntrustedRegexp.new('(?im)something') + end + + it 'fabricates regexp without flags' do + regexp = described_class.fabricate!('/something/') + + expect(regexp).to eq Gitlab::UntrustedRegexp.new('something') + end + end + + context 'when regexp is a raw pattern' do + it 'raises an error' do + expect { described_class.fabricate!('some .* thing') } + .to raise_error(RegexpError) + end + end + end +end diff --git a/spec/lib/gitlab/untrusted_regexp_spec.rb b/spec/lib/gitlab/untrusted_regexp_spec.rb index 0a6ac0aa294..9d483f13a5e 100644 --- a/spec/lib/gitlab/untrusted_regexp_spec.rb +++ b/spec/lib/gitlab/untrusted_regexp_spec.rb @@ -2,48 +2,6 @@ require 'fast_spec_helper' require 'support/shared_examples/malicious_regexp_shared_examples' describe Gitlab::UntrustedRegexp do - describe '.valid?' do - it 'returns true if regexp is valid' do - expect(described_class.valid?('/some ( thing/')) - .to be false - end - - it 'returns true if regexp is invalid' do - expect(described_class.valid?('/some .* thing/')) - .to be true - end - end - - describe '.fabricate' do - context 'when regexp is using /regexp/ scheme with flags' do - it 'fabricates regexp with a single flag' do - regexp = described_class.fabricate('/something/i') - - expect(regexp).to eq described_class.new('(?i)something') - expect(regexp.scan('SOMETHING')).to be_one - end - - it 'fabricates regexp with multiple flags' do - regexp = described_class.fabricate('/something/im') - - expect(regexp).to eq described_class.new('(?im)something') - end - - it 'fabricates regexp without flags' do - regexp = described_class.fabricate('/something/') - - expect(regexp).to eq described_class.new('something') - end - end - - context 'when regexp is a raw pattern' do - it 'raises an error' do - expect { described_class.fabricate('some .* thing') } - .to raise_error(RegexpError) - end - end - end - describe '#initialize' do subject { described_class.new(pattern) } @@ -92,11 +50,41 @@ describe Gitlab::UntrustedRegexp do end end + describe '#match?' do + subject { described_class.new(regexp).match?(text) } + + context 'malicious regexp' do + let(:text) { malicious_text } + let(:regexp) { malicious_regexp_re2 } + + include_examples 'malicious regexp' + end + + context 'matching regexp' do + let(:regexp) { 'foo' } + let(:text) { 'foo' } + + it 'returns an array of nil matches' do + is_expected.to eq(true) + end + end + + context 'non-matching regexp' do + let(:regexp) { 'boo' } + let(:text) { 'foo' } + + it 'returns an array of nil matches' do + is_expected.to eq(false) + end + end + end + describe '#scan' do subject { described_class.new(regexp).scan(text) } + context 'malicious regexp' do let(:text) { malicious_text } - let(:regexp) { malicious_regexp } + let(:regexp) { malicious_regexp_re2 } include_examples 'malicious regexp' end diff --git a/spec/lib/gitlab_spec.rb b/spec/lib/gitlab_spec.rb index 8232715d00e..767b5779a79 100644 --- a/spec/lib/gitlab_spec.rb +++ b/spec/lib/gitlab_spec.rb @@ -10,7 +10,7 @@ describe Gitlab do end describe '.revision' do - let(:cmd) { %W[#{described_class.config.git.bin_path} log --pretty=format:%h -n 1] } + let(:cmd) { %W[#{described_class.config.git.bin_path} log --pretty=format:%h --abbrev=11 -n 1] } around do |example| described_class.instance_variable_set(:@_revision, nil) diff --git a/spec/lib/sentry/client_spec.rb b/spec/lib/sentry/client_spec.rb index 88e7e2e5ebb..3333f8307ae 100644 --- a/spec/lib/sentry/client_spec.rb +++ b/spec/lib/sentry/client_spec.rb @@ -65,7 +65,9 @@ describe Sentry::Client do let(:issue_status) { 'unresolved' } let(:limit) { 20 } - let!(:sentry_api_request) { stub_sentry_request(sentry_url + '/issues/?limit=20&query=is:unresolved', body: issues_sample_response) } + let(:sentry_api_response) { issues_sample_response } + + let!(:sentry_api_request) { stub_sentry_request(sentry_url + '/issues/?limit=20&query=is:unresolved', body: sentry_api_response) } subject { client.list_issues(issue_status: issue_status, limit: limit) } @@ -74,6 +76,14 @@ describe Sentry::Client do it_behaves_like 'has correct return type', Gitlab::ErrorTracking::Error it_behaves_like 'has correct length', 1 + shared_examples 'has correct external_url' do + context 'external_url' do + it 'is constructed correctly' do + expect(subject[0].external_url).to eq('https://sentrytest.gitlab.com/sentry-org/sentry-project/issues/11') + end + end + end + context 'error object created from sentry response' do using RSpec::Parameterized::TableSyntax @@ -96,14 +106,10 @@ describe Sentry::Client do end with_them do - it { expect(subject[0].public_send(error_object)).to eq(issues_sample_response[0].dig(*sentry_response)) } + it { expect(subject[0].public_send(error_object)).to eq(sentry_api_response[0].dig(*sentry_response)) } end - context 'external_url' do - it 'is constructed correctly' do - expect(subject[0].external_url).to eq('https://sentrytest.gitlab.com/sentry-org/sentry-project/issues/11') - end - end + it_behaves_like 'has correct external_url' end context 'redirects' do @@ -135,12 +141,42 @@ describe Sentry::Client do expect(valid_req_stub).to have_been_requested end end + + context 'Older sentry versions where keys are not present' do + let(:sentry_api_response) do + issues_sample_response[0...1].map do |issue| + issue[:project].delete(:id) + issue + end + end + + it_behaves_like 'calls sentry api' + + it_behaves_like 'has correct return type', Gitlab::ErrorTracking::Error + it_behaves_like 'has correct length', 1 + + it_behaves_like 'has correct external_url' + end + + context 'essential keys missing in API response' do + let(:sentry_api_response) do + issues_sample_response[0...1].map do |issue| + issue.except(:id) + end + end + + it 'raises exception' do + expect { subject }.to raise_error(Sentry::Client::MissingKeysError, 'Sentry API response is missing keys. key not found: "id"') + end + end end describe '#list_projects' do let(:sentry_list_projects_url) { 'https://sentrytest.gitlab.com/api/0/projects/' } - let!(:sentry_api_request) { stub_sentry_request(sentry_list_projects_url, body: projects_sample_response) } + let(:sentry_api_response) { projects_sample_response } + + let!(:sentry_api_request) { stub_sentry_request(sentry_list_projects_url, body: sentry_api_response) } subject { client.list_projects } @@ -149,14 +185,31 @@ describe Sentry::Client do it_behaves_like 'has correct return type', Gitlab::ErrorTracking::Project it_behaves_like 'has correct length', 2 - context 'keys missing in API response' do - it 'raises exception' do - projects_sample_response[0].delete(:slug) + context 'essential keys missing in API response' do + let(:sentry_api_response) do + projects_sample_response[0...1].map do |project| + project.except(:slug) + end + end - stub_sentry_request(sentry_list_projects_url, body: projects_sample_response) + it 'raises exception' do + expect { subject }.to raise_error(Sentry::Client::MissingKeysError, 'Sentry API response is missing keys. key not found: "slug"') + end + end - expect { subject }.to raise_error(Sentry::Client::SentryError, 'Sentry API response is missing keys. key not found: "slug"') + context 'optional keys missing in sentry response' do + let(:sentry_api_response) do + projects_sample_response[0...1].map do |project| + project[:organization].delete(:id) + project.delete(:id) + project.except(:status) + end end + + it_behaves_like 'calls sentry api' + + it_behaves_like 'has correct return type', Gitlab::ErrorTracking::Project + it_behaves_like 'has correct length', 1 end context 'error object created from sentry response' do @@ -173,7 +226,11 @@ describe Sentry::Client do end with_them do - it { expect(subject[0].public_send(sentry_project_object)).to eq(projects_sample_response[0].dig(*sentry_response)) } + it do + expect(subject[0].public_send(sentry_project_object)).to( + eq(sentry_api_response[0].dig(*sentry_response)) + ) + end end end diff --git a/spec/migrations/migrate_cluster_configure_worker_sidekiq_queue_spec.rb b/spec/migrations/migrate_cluster_configure_worker_sidekiq_queue_spec.rb index b2d8f476bb2..a1f243651b5 100644 --- a/spec/migrations/migrate_cluster_configure_worker_sidekiq_queue_spec.rb +++ b/spec/migrations/migrate_cluster_configure_worker_sidekiq_queue_spec.rb @@ -3,12 +3,13 @@ require Rails.root.join('db', 'post_migrate', '20181219145520_migrate_cluster_co describe MigrateClusterConfigureWorkerSidekiqQueue, :sidekiq, :redis do include Gitlab::Database::MigrationHelpers + include StubWorker context 'when there are jobs in the queue' do it 'correctly migrates queue when migrating up' do Sidekiq::Testing.disable! do - stubbed_worker(queue: 'gcp_cluster:cluster_platform_configure').perform_async('Something', [1]) - stubbed_worker(queue: 'gcp_cluster:cluster_configure').perform_async('Something', [1]) + stub_worker(queue: 'gcp_cluster:cluster_platform_configure').perform_async('Something', [1]) + stub_worker(queue: 'gcp_cluster:cluster_configure').perform_async('Something', [1]) described_class.new.up @@ -19,12 +20,12 @@ describe MigrateClusterConfigureWorkerSidekiqQueue, :sidekiq, :redis do it 'does not affect other queues under the same namespace' do Sidekiq::Testing.disable! do - stubbed_worker(queue: 'gcp_cluster:cluster_install_app').perform_async('Something', [1]) - stubbed_worker(queue: 'gcp_cluster:cluster_provision').perform_async('Something', [1]) - stubbed_worker(queue: 'gcp_cluster:cluster_wait_for_app_installation').perform_async('Something', [1]) - stubbed_worker(queue: 'gcp_cluster:wait_for_cluster_creation').perform_async('Something', [1]) - stubbed_worker(queue: 'gcp_cluster:cluster_wait_for_ingress_ip_address').perform_async('Something', [1]) - stubbed_worker(queue: 'gcp_cluster:cluster_project_configure').perform_async('Something', [1]) + stub_worker(queue: 'gcp_cluster:cluster_install_app').perform_async('Something', [1]) + stub_worker(queue: 'gcp_cluster:cluster_provision').perform_async('Something', [1]) + stub_worker(queue: 'gcp_cluster:cluster_wait_for_app_installation').perform_async('Something', [1]) + stub_worker(queue: 'gcp_cluster:wait_for_cluster_creation').perform_async('Something', [1]) + stub_worker(queue: 'gcp_cluster:cluster_wait_for_ingress_ip_address').perform_async('Something', [1]) + stub_worker(queue: 'gcp_cluster:cluster_project_configure').perform_async('Something', [1]) described_class.new.up @@ -39,7 +40,7 @@ describe MigrateClusterConfigureWorkerSidekiqQueue, :sidekiq, :redis do it 'correctly migrates queue when migrating down' do Sidekiq::Testing.disable! do - stubbed_worker(queue: 'gcp_cluster:cluster_configure').perform_async('Something', [1]) + stub_worker(queue: 'gcp_cluster:cluster_configure').perform_async('Something', [1]) described_class.new.down @@ -58,11 +59,4 @@ describe MigrateClusterConfigureWorkerSidekiqQueue, :sidekiq, :redis do expect { described_class.new.down }.not_to raise_error end end - - def stubbed_worker(queue:) - Class.new do - include Sidekiq::Worker - sidekiq_options queue: queue - end - end end diff --git a/spec/migrations/migrate_create_trace_artifact_sidekiq_queue_spec.rb b/spec/migrations/migrate_create_trace_artifact_sidekiq_queue_spec.rb index c18ae3b76d3..66555118a43 100644 --- a/spec/migrations/migrate_create_trace_artifact_sidekiq_queue_spec.rb +++ b/spec/migrations/migrate_create_trace_artifact_sidekiq_queue_spec.rb @@ -3,12 +3,13 @@ require Rails.root.join('db', 'post_migrate', '20180306074045_migrate_create_tra describe MigrateCreateTraceArtifactSidekiqQueue, :sidekiq, :redis do include Gitlab::Database::MigrationHelpers + include StubWorker context 'when there are jobs in the queues' do it 'correctly migrates queue when migrating up' do Sidekiq::Testing.disable! do - stubbed_worker(queue: 'pipeline_default:create_trace_artifact').perform_async('Something', [1]) - stubbed_worker(queue: 'pipeline_background:archive_trace').perform_async('Something', [1]) + stub_worker(queue: 'pipeline_default:create_trace_artifact').perform_async('Something', [1]) + stub_worker(queue: 'pipeline_background:archive_trace').perform_async('Something', [1]) described_class.new.up @@ -19,11 +20,11 @@ describe MigrateCreateTraceArtifactSidekiqQueue, :sidekiq, :redis do it 'does not affect other queues under the same namespace' do Sidekiq::Testing.disable! do - stubbed_worker(queue: 'pipeline_default:build_coverage').perform_async('Something', [1]) - stubbed_worker(queue: 'pipeline_default:build_trace_sections').perform_async('Something', [1]) - stubbed_worker(queue: 'pipeline_default:pipeline_metrics').perform_async('Something', [1]) - stubbed_worker(queue: 'pipeline_default:pipeline_notification').perform_async('Something', [1]) - stubbed_worker(queue: 'pipeline_default:update_head_pipeline_for_merge_request').perform_async('Something', [1]) + stub_worker(queue: 'pipeline_default:build_coverage').perform_async('Something', [1]) + stub_worker(queue: 'pipeline_default:build_trace_sections').perform_async('Something', [1]) + stub_worker(queue: 'pipeline_default:pipeline_metrics').perform_async('Something', [1]) + stub_worker(queue: 'pipeline_default:pipeline_notification').perform_async('Something', [1]) + stub_worker(queue: 'pipeline_default:update_head_pipeline_for_merge_request').perform_async('Something', [1]) described_class.new.up @@ -37,7 +38,7 @@ describe MigrateCreateTraceArtifactSidekiqQueue, :sidekiq, :redis do it 'correctly migrates queue when migrating down' do Sidekiq::Testing.disable! do - stubbed_worker(queue: 'pipeline_background:archive_trace').perform_async('Something', [1]) + stub_worker(queue: 'pipeline_background:archive_trace').perform_async('Something', [1]) described_class.new.down @@ -56,11 +57,4 @@ describe MigrateCreateTraceArtifactSidekiqQueue, :sidekiq, :redis do expect { described_class.new.down }.not_to raise_error end end - - def stubbed_worker(queue:) - Class.new do - include Sidekiq::Worker - sidekiq_options queue: queue - end - end end diff --git a/spec/migrations/migrate_object_storage_upload_sidekiq_queue_spec.rb b/spec/migrations/migrate_object_storage_upload_sidekiq_queue_spec.rb index 1ee6c440cf4..6ce04805e5d 100644 --- a/spec/migrations/migrate_object_storage_upload_sidekiq_queue_spec.rb +++ b/spec/migrations/migrate_object_storage_upload_sidekiq_queue_spec.rb @@ -3,12 +3,13 @@ require Rails.root.join('db', 'post_migrate', '20180603190921_migrate_object_sto describe MigrateObjectStorageUploadSidekiqQueue, :sidekiq, :redis do include Gitlab::Database::MigrationHelpers + include StubWorker context 'when there are jobs in the queue' do it 'correctly migrates queue when migrating up' do Sidekiq::Testing.disable! do - stubbed_worker(queue: 'object_storage_upload').perform_async('Something', [1]) - stubbed_worker(queue: 'object_storage:object_storage_background_move').perform_async('Something', [1]) + stub_worker(queue: 'object_storage_upload').perform_async('Something', [1]) + stub_worker(queue: 'object_storage:object_storage_background_move').perform_async('Something', [1]) described_class.new.up @@ -23,11 +24,4 @@ describe MigrateObjectStorageUploadSidekiqQueue, :sidekiq, :redis do expect { described_class.new.up }.not_to raise_error end end - - def stubbed_worker(queue:) - Class.new do - include Sidekiq::Worker - sidekiq_options queue: queue - end - end end diff --git a/spec/migrations/migrate_pipeline_sidekiq_queues_spec.rb b/spec/migrations/migrate_pipeline_sidekiq_queues_spec.rb index e02bcd2f4da..e38044ccceb 100644 --- a/spec/migrations/migrate_pipeline_sidekiq_queues_spec.rb +++ b/spec/migrations/migrate_pipeline_sidekiq_queues_spec.rb @@ -3,12 +3,13 @@ require Rails.root.join('db', 'post_migrate', '20170822101017_migrate_pipeline_s describe MigratePipelineSidekiqQueues, :sidekiq, :redis do include Gitlab::Database::MigrationHelpers + include StubWorker context 'when there are jobs in the queues' do it 'correctly migrates queue when migrating up' do Sidekiq::Testing.disable! do - stubbed_worker(queue: :pipeline).perform_async('Something', [1]) - stubbed_worker(queue: :build).perform_async('Something', [1]) + stub_worker(queue: :pipeline).perform_async('Something', [1]) + stub_worker(queue: :build).perform_async('Something', [1]) described_class.new.up @@ -20,10 +21,10 @@ describe MigratePipelineSidekiqQueues, :sidekiq, :redis do it 'correctly migrates queue when migrating down' do Sidekiq::Testing.disable! do - stubbed_worker(queue: :pipeline_default).perform_async('Class', [1]) - stubbed_worker(queue: :pipeline_processing).perform_async('Class', [2]) - stubbed_worker(queue: :pipeline_hooks).perform_async('Class', [3]) - stubbed_worker(queue: :pipeline_cache).perform_async('Class', [4]) + stub_worker(queue: :pipeline_default).perform_async('Class', [1]) + stub_worker(queue: :pipeline_processing).perform_async('Class', [2]) + stub_worker(queue: :pipeline_hooks).perform_async('Class', [3]) + stub_worker(queue: :pipeline_cache).perform_async('Class', [4]) described_class.new.down @@ -45,11 +46,4 @@ describe MigratePipelineSidekiqQueues, :sidekiq, :redis do expect { described_class.new.down }.not_to raise_error end end - - def stubbed_worker(queue:) - Class.new do - include Sidekiq::Worker - sidekiq_options queue: queue - end - end end diff --git a/spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb b/spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb index f8cf76cb339..94de208e53e 100644 --- a/spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb +++ b/spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb @@ -3,11 +3,12 @@ require Rails.root.join('db', 'post_migrate', '20190124200344_migrate_storage_mi describe MigrateStorageMigratorSidekiqQueue, :sidekiq, :redis do include Gitlab::Database::MigrationHelpers + include StubWorker context 'when there are jobs in the queues' do it 'correctly migrates queue when migrating up' do Sidekiq::Testing.disable! do - stubbed_worker(queue: :storage_migrator).perform_async(1, 5) + stub_worker(queue: :storage_migrator).perform_async(1, 5) described_class.new.up @@ -18,7 +19,7 @@ describe MigrateStorageMigratorSidekiqQueue, :sidekiq, :redis do it 'correctly migrates queue when migrating down' do Sidekiq::Testing.disable! do - stubbed_worker(queue: :'hashed_storage:hashed_storage_migrator').perform_async(1, 5) + stub_worker(queue: :'hashed_storage:hashed_storage_migrator').perform_async(1, 5) described_class.new.down @@ -37,11 +38,4 @@ describe MigrateStorageMigratorSidekiqQueue, :sidekiq, :redis do expect { described_class.new.down }.not_to raise_error end end - - def stubbed_worker(queue:) - Class.new do - include Sidekiq::Worker - sidekiq_options queue: queue - end - end end diff --git a/spec/migrations/migrate_update_head_pipeline_for_merge_request_sidekiq_queue_spec.rb b/spec/migrations/migrate_update_head_pipeline_for_merge_request_sidekiq_queue_spec.rb index 5e3b20ab4a8..976f3ce07d7 100644 --- a/spec/migrations/migrate_update_head_pipeline_for_merge_request_sidekiq_queue_spec.rb +++ b/spec/migrations/migrate_update_head_pipeline_for_merge_request_sidekiq_queue_spec.rb @@ -3,12 +3,13 @@ require Rails.root.join('db', 'post_migrate', '20180307012445_migrate_update_hea describe MigrateUpdateHeadPipelineForMergeRequestSidekiqQueue, :sidekiq, :redis do include Gitlab::Database::MigrationHelpers + include StubWorker context 'when there are jobs in the queues' do it 'correctly migrates queue when migrating up' do Sidekiq::Testing.disable! do - stubbed_worker(queue: 'pipeline_default:update_head_pipeline_for_merge_request').perform_async('Something', [1]) - stubbed_worker(queue: 'pipeline_processing:update_head_pipeline_for_merge_request').perform_async('Something', [1]) + stub_worker(queue: 'pipeline_default:update_head_pipeline_for_merge_request').perform_async('Something', [1]) + stub_worker(queue: 'pipeline_processing:update_head_pipeline_for_merge_request').perform_async('Something', [1]) described_class.new.up @@ -19,10 +20,10 @@ describe MigrateUpdateHeadPipelineForMergeRequestSidekiqQueue, :sidekiq, :redis it 'does not affect other queues under the same namespace' do Sidekiq::Testing.disable! do - stubbed_worker(queue: 'pipeline_default:build_coverage').perform_async('Something', [1]) - stubbed_worker(queue: 'pipeline_default:build_trace_sections').perform_async('Something', [1]) - stubbed_worker(queue: 'pipeline_default:pipeline_metrics').perform_async('Something', [1]) - stubbed_worker(queue: 'pipeline_default:pipeline_notification').perform_async('Something', [1]) + stub_worker(queue: 'pipeline_default:build_coverage').perform_async('Something', [1]) + stub_worker(queue: 'pipeline_default:build_trace_sections').perform_async('Something', [1]) + stub_worker(queue: 'pipeline_default:pipeline_metrics').perform_async('Something', [1]) + stub_worker(queue: 'pipeline_default:pipeline_notification').perform_async('Something', [1]) described_class.new.up @@ -35,7 +36,7 @@ describe MigrateUpdateHeadPipelineForMergeRequestSidekiqQueue, :sidekiq, :redis it 'correctly migrates queue when migrating down' do Sidekiq::Testing.disable! do - stubbed_worker(queue: 'pipeline_processing:update_head_pipeline_for_merge_request').perform_async('Something', [1]) + stub_worker(queue: 'pipeline_processing:update_head_pipeline_for_merge_request').perform_async('Something', [1]) described_class.new.down @@ -54,11 +55,4 @@ describe MigrateUpdateHeadPipelineForMergeRequestSidekiqQueue, :sidekiq, :redis expect { described_class.new.down }.not_to raise_error end end - - def stubbed_worker(queue:) - Class.new do - include Sidekiq::Worker - sidekiq_options queue: queue - end - end end diff --git a/spec/migrations/schedule_sync_issuables_state_id_spec.rb b/spec/migrations/schedule_sync_issuables_state_id_spec.rb new file mode 100644 index 00000000000..bf974d60b24 --- /dev/null +++ b/spec/migrations/schedule_sync_issuables_state_id_spec.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +require 'spec_helper' +require Rails.root.join('db', 'post_migrate', '20190214112022_schedule_sync_issuables_state_id.rb') + +describe ScheduleSyncIssuablesStateId, :migration do + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + let(:merge_requests) { table(:merge_requests) } + let(:issues) { table(:issues) } + let(:migration) { described_class.new } + let(:group) { namespaces.create!(name: 'gitlab', path: 'gitlab') } + let(:project) { projects.create!(namespace_id: group.id) } + + shared_examples 'scheduling migrations' do + before do + Sidekiq::Worker.clear_all + stub_const("#{described_class.name}::BATCH_SIZE", 2) + end + + it 'correctly schedules issuable sync background migration' do + Sidekiq::Testing.fake! do + Timecop.freeze do + migrate! + + expect(migration).to be_scheduled_delayed_migration(120.seconds, resource_1.id, resource_2.id) + expect(migration).to be_scheduled_delayed_migration(240.seconds, resource_3.id, resource_4.id) + expect(BackgroundMigrationWorker.jobs.size).to eq(2) + end + end + end + end + + describe '#up' do + context 'issues' do + it 'migrates state column to integer' do + opened_issue = issues.create!(description: 'first', state: 'opened') + closed_issue = issues.create!(description: 'second', state: 'closed') + invalid_state_issue = issues.create!(description: 'fourth', state: 'not valid') + + migrate! + + expect(opened_issue.reload.state_id).to eq(Issue.available_states[:opened]) + expect(closed_issue.reload.state_id).to eq(Issue.available_states[:closed]) + expect(invalid_state_issue.reload.state_id).to be_nil + end + + it_behaves_like 'scheduling migrations' do + let(:migration) { described_class::ISSUES_MIGRATION } + let!(:resource_1) { issues.create!(description: 'first', state: 'opened') } + let!(:resource_2) { issues.create!(description: 'second', state: 'closed') } + let!(:resource_3) { issues.create!(description: 'third', state: 'closed') } + let!(:resource_4) { issues.create!(description: 'fourth', state: 'closed') } + end + end + + context 'merge requests' do + it 'migrates state column to integer' do + opened_merge_request = merge_requests.create!(state: 'opened', target_project_id: project.id, target_branch: 'feature1', source_branch: 'master') + closed_merge_request = merge_requests.create!(state: 'closed', target_project_id: project.id, target_branch: 'feature2', source_branch: 'master') + merged_merge_request = merge_requests.create!(state: 'merged', target_project_id: project.id, target_branch: 'feature3', source_branch: 'master') + locked_merge_request = merge_requests.create!(state: 'locked', target_project_id: project.id, target_branch: 'feature4', source_branch: 'master') + + migrate! + + expect(opened_merge_request.reload.state_id).to eq(MergeRequest.available_states[:opened]) + expect(closed_merge_request.reload.state_id).to eq(MergeRequest.available_states[:closed]) + expect(merged_merge_request.reload.state_id).to eq(MergeRequest.available_states[:merged]) + expect(locked_merge_request.reload.state_id).to eq(MergeRequest.available_states[:locked]) + end + + it_behaves_like 'scheduling migrations' do + let(:migration) { described_class::MERGE_REQUESTS_MIGRATION } + let!(:resource_1) { merge_requests.create!(state: 'opened', target_project_id: project.id, target_branch: 'feature1', source_branch: 'master') } + let!(:resource_2) { merge_requests.create!(state: 'closed', target_project_id: project.id, target_branch: 'feature2', source_branch: 'master') } + let!(:resource_3) { merge_requests.create!(state: 'merged', target_project_id: project.id, target_branch: 'feature3', source_branch: 'master') } + let!(:resource_4) { merge_requests.create!(state: 'locked', target_project_id: project.id, target_branch: 'feature4', source_branch: 'master') } + end + end + end +end diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index eee80e9bad7..d9d60e02a97 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ability do diff --git a/spec/models/abuse_report_spec.rb b/spec/models/abuse_report_spec.rb index f49a61062c1..a5f8e999d5d 100644 --- a/spec/models/abuse_report_spec.rb +++ b/spec/models/abuse_report_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe AbuseReport do diff --git a/spec/models/active_session_spec.rb b/spec/models/active_session_spec.rb index e128fe8a4b7..b523f393ece 100644 --- a/spec/models/active_session_spec.rb +++ b/spec/models/active_session_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do diff --git a/spec/models/appearance_spec.rb b/spec/models/appearance_spec.rb index 3e95aa2b5dd..209d138f956 100644 --- a/spec/models/appearance_spec.rb +++ b/spec/models/appearance_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe Appearance do diff --git a/spec/models/application_setting/term_spec.rb b/spec/models/application_setting/term_spec.rb index aa49594f4d1..dd263335b81 100644 --- a/spec/models/application_setting/term_spec.rb +++ b/spec/models/application_setting/term_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ApplicationSetting::Term do diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 314f0728b8e..c5579dafb4a 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ApplicationSetting do diff --git a/spec/models/award_emoji_spec.rb b/spec/models/award_emoji_spec.rb index 3f52091698c..8452ac69734 100644 --- a/spec/models/award_emoji_spec.rb +++ b/spec/models/award_emoji_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe AwardEmoji do diff --git a/spec/models/badge_spec.rb b/spec/models/badge_spec.rb index 33dc19e3432..314d7d1e9f4 100644 --- a/spec/models/badge_spec.rb +++ b/spec/models/badge_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Badge do diff --git a/spec/models/badges/group_badge_spec.rb b/spec/models/badges/group_badge_spec.rb index ed7f83d0489..c297bc957ea 100644 --- a/spec/models/badges/group_badge_spec.rb +++ b/spec/models/badges/group_badge_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe GroupBadge do diff --git a/spec/models/badges/project_badge_spec.rb b/spec/models/badges/project_badge_spec.rb index 0e1a8159cb6..e683d110252 100644 --- a/spec/models/badges/project_badge_spec.rb +++ b/spec/models/badges/project_badge_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProjectBadge do diff --git a/spec/models/blob_spec.rb b/spec/models/blob_spec.rb index 05cf242e84d..d0e1688cce3 100644 --- a/spec/models/blob_spec.rb +++ b/spec/models/blob_spec.rb @@ -1,4 +1,6 @@ # encoding: utf-8 +# frozen_string_literal: true + require 'rails_helper' describe Blob do diff --git a/spec/models/blob_viewer/base_spec.rb b/spec/models/blob_viewer/base_spec.rb index 7ba28f72215..39c7a34f052 100644 --- a/spec/models/blob_viewer/base_spec.rb +++ b/spec/models/blob_viewer/base_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BlobViewer::Base do diff --git a/spec/models/blob_viewer/changelog_spec.rb b/spec/models/blob_viewer/changelog_spec.rb index db41eca0fc8..0fcc94182af 100644 --- a/spec/models/blob_viewer/changelog_spec.rb +++ b/spec/models/blob_viewer/changelog_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BlobViewer::Changelog do diff --git a/spec/models/blob_viewer/composer_json_spec.rb b/spec/models/blob_viewer/composer_json_spec.rb index 85b0d9668a0..eda34779679 100644 --- a/spec/models/blob_viewer/composer_json_spec.rb +++ b/spec/models/blob_viewer/composer_json_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BlobViewer::ComposerJson do diff --git a/spec/models/blob_viewer/gemspec_spec.rb b/spec/models/blob_viewer/gemspec_spec.rb index d8c4490637f..b6cc82c03ba 100644 --- a/spec/models/blob_viewer/gemspec_spec.rb +++ b/spec/models/blob_viewer/gemspec_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BlobViewer::Gemspec do diff --git a/spec/models/blob_viewer/gitlab_ci_yml_spec.rb b/spec/models/blob_viewer/gitlab_ci_yml_spec.rb index 16bf947b493..db405ceb4f1 100644 --- a/spec/models/blob_viewer/gitlab_ci_yml_spec.rb +++ b/spec/models/blob_viewer/gitlab_ci_yml_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BlobViewer::GitlabCiYml do diff --git a/spec/models/blob_viewer/license_spec.rb b/spec/models/blob_viewer/license_spec.rb index 222ed166ee0..e02bfae3829 100644 --- a/spec/models/blob_viewer/license_spec.rb +++ b/spec/models/blob_viewer/license_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BlobViewer::License do diff --git a/spec/models/blob_viewer/package_json_spec.rb b/spec/models/blob_viewer/package_json_spec.rb index fbaa8d47a71..b317278f3c8 100644 --- a/spec/models/blob_viewer/package_json_spec.rb +++ b/spec/models/blob_viewer/package_json_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BlobViewer::PackageJson do diff --git a/spec/models/blob_viewer/podspec_json_spec.rb b/spec/models/blob_viewer/podspec_json_spec.rb index 9a23877b23f..7f1fb8666fd 100644 --- a/spec/models/blob_viewer/podspec_json_spec.rb +++ b/spec/models/blob_viewer/podspec_json_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BlobViewer::PodspecJson do diff --git a/spec/models/blob_viewer/podspec_spec.rb b/spec/models/blob_viewer/podspec_spec.rb index 02d06ea24d6..527ae79d766 100644 --- a/spec/models/blob_viewer/podspec_spec.rb +++ b/spec/models/blob_viewer/podspec_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BlobViewer::Podspec do diff --git a/spec/models/blob_viewer/readme_spec.rb b/spec/models/blob_viewer/readme_spec.rb index 8d11d58cfca..958927bddb4 100644 --- a/spec/models/blob_viewer/readme_spec.rb +++ b/spec/models/blob_viewer/readme_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BlobViewer::Readme do diff --git a/spec/models/blob_viewer/route_map_spec.rb b/spec/models/blob_viewer/route_map_spec.rb index c13662427b0..f7ce873c9d1 100644 --- a/spec/models/blob_viewer/route_map_spec.rb +++ b/spec/models/blob_viewer/route_map_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BlobViewer::RouteMap do diff --git a/spec/models/blob_viewer/server_side_spec.rb b/spec/models/blob_viewer/server_side_spec.rb index 63790486200..f95305abe78 100644 --- a/spec/models/blob_viewer/server_side_spec.rb +++ b/spec/models/blob_viewer/server_side_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BlobViewer::ServerSide do diff --git a/spec/models/board_spec.rb b/spec/models/board_spec.rb index 12d29540137..54452faa0e1 100644 --- a/spec/models/board_spec.rb +++ b/spec/models/board_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe Board do diff --git a/spec/models/broadcast_message_spec.rb b/spec/models/broadcast_message_spec.rb index 30ca07d5d2c..3ab013ddc0e 100644 --- a/spec/models/broadcast_message_spec.rb +++ b/spec/models/broadcast_message_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BroadcastMessage do diff --git a/spec/models/chat_name_spec.rb b/spec/models/chat_name_spec.rb index 504bc710b25..82991937644 100644 --- a/spec/models/chat_name_spec.rb +++ b/spec/models/chat_name_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ChatName do diff --git a/spec/models/chat_team_spec.rb b/spec/models/chat_team_spec.rb index 70a9a206faa..76beb3d506b 100644 --- a/spec/models/chat_team_spec.rb +++ b/spec/models/chat_team_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ChatTeam do diff --git a/spec/models/ci/artifact_blob_spec.rb b/spec/models/ci/artifact_blob_spec.rb index 0014bbcf9f5..f63816fd92a 100644 --- a/spec/models/ci/artifact_blob_spec.rb +++ b/spec/models/ci/artifact_blob_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::ArtifactBlob do diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb index b5ec8991720..aacfbe3f180 100644 --- a/spec/models/ci/bridge_spec.rb +++ b/spec/models/ci/bridge_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::Bridge do diff --git a/spec/models/ci/build_metadata_spec.rb b/spec/models/ci/build_metadata_spec.rb index 016a5899eef..917a65ddf21 100644 --- a/spec/models/ci/build_metadata_spec.rb +++ b/spec/models/ci/build_metadata_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::BuildMetadata do diff --git a/spec/models/ci/build_runner_session_spec.rb b/spec/models/ci/build_runner_session_spec.rb index 35622366829..a52c10019e6 100644 --- a/spec/models/ci/build_runner_session_spec.rb +++ b/spec/models/ci/build_runner_session_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::BuildRunnerSession, model: true do diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 7500e6ae5b1..2c41dfa65cd 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::Build do @@ -24,6 +26,8 @@ describe Ci::Build do it { is_expected.to respond_to(:has_trace?) } it { is_expected.to respond_to(:trace) } it { is_expected.to delegate_method(:merge_request_event?).to(:pipeline) } + it { is_expected.to delegate_method(:merge_request_ref?).to(:pipeline) } + it { is_expected.to delegate_method(:legacy_detached_merge_request_pipeline?).to(:pipeline) } it { is_expected.to be_a(ArtifactMigratable) } @@ -3626,6 +3630,24 @@ describe Ci::Build do it { is_expected.to be_falsey } end end + + context 'when refspecs feature is required by build' do + before do + allow(build).to receive(:merge_request_ref?) { true } + end + + context 'when runner provides given feature' do + let(:runner_features) { { refspecs: true } } + + it { is_expected.to be_truthy } + end + + context 'when runner does not provide given feature' do + let(:runner_features) { {} } + + it { is_expected.to be_falsey } + end + end end describe '#deployment_status' do diff --git a/spec/models/ci/build_trace_chunks/database_spec.rb b/spec/models/ci/build_trace_chunks/database_spec.rb index d8fc9d57e95..eb94d7dae38 100644 --- a/spec/models/ci/build_trace_chunks/database_spec.rb +++ b/spec/models/ci/build_trace_chunks/database_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::BuildTraceChunks::Database do diff --git a/spec/models/ci/build_trace_chunks/fog_spec.rb b/spec/models/ci/build_trace_chunks/fog_spec.rb index 8f49190af13..b8d78bcd069 100644 --- a/spec/models/ci/build_trace_chunks/fog_spec.rb +++ b/spec/models/ci/build_trace_chunks/fog_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::BuildTraceChunks::Fog do diff --git a/spec/models/ci/build_trace_chunks/redis_spec.rb b/spec/models/ci/build_trace_chunks/redis_spec.rb index 9da1e6a95ee..6cff33d24fa 100644 --- a/spec/models/ci/build_trace_chunks/redis_spec.rb +++ b/spec/models/ci/build_trace_chunks/redis_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::BuildTraceChunks::Redis, :clean_gitlab_redis_shared_state do diff --git a/spec/models/ci/build_trace_section_name_spec.rb b/spec/models/ci/build_trace_section_name_spec.rb index 386ee6880cb..11e2d27ff79 100644 --- a/spec/models/ci/build_trace_section_name_spec.rb +++ b/spec/models/ci/build_trace_section_name_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::BuildTraceSectionName, model: true do diff --git a/spec/models/ci/build_trace_section_spec.rb b/spec/models/ci/build_trace_section_spec.rb index 541a9a36fb8..5bd3a953ec0 100644 --- a/spec/models/ci/build_trace_section_spec.rb +++ b/spec/models/ci/build_trace_section_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::BuildTraceSection, model: true do diff --git a/spec/models/ci/group_spec.rb b/spec/models/ci/group_spec.rb index 838fa63cb1f..36c65d92840 100644 --- a/spec/models/ci/group_spec.rb +++ b/spec/models/ci/group_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::Group do diff --git a/spec/models/ci/group_variable_spec.rb b/spec/models/ci/group_variable_spec.rb index 21d96bf3454..b3999765e5f 100644 --- a/spec/models/ci/group_variable_spec.rb +++ b/spec/models/ci/group_variable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::GroupVariable do diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb index c68ba02b8de..d7abd54eec1 100644 --- a/spec/models/ci/job_artifact_spec.rb +++ b/spec/models/ci/job_artifact_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::JobArtifact do diff --git a/spec/models/ci/legacy_stage_spec.rb b/spec/models/ci/legacy_stage_spec.rb index 0c33c1466b7..be0307518eb 100644 --- a/spec/models/ci/legacy_stage_spec.rb +++ b/spec/models/ci/legacy_stage_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::LegacyStage do diff --git a/spec/models/ci/pipeline_schedule_spec.rb b/spec/models/ci/pipeline_schedule_spec.rb index 8ee15f0e734..81913f4a3b6 100644 --- a/spec/models/ci/pipeline_schedule_spec.rb +++ b/spec/models/ci/pipeline_schedule_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::PipelineSchedule do diff --git a/spec/models/ci/pipeline_schedule_variable_spec.rb b/spec/models/ci/pipeline_schedule_variable_spec.rb index dc8427f28bc..3c9379ecb0d 100644 --- a/spec/models/ci/pipeline_schedule_variable_spec.rb +++ b/spec/models/ci/pipeline_schedule_variable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::PipelineScheduleVariable do diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 5b8097621e0..83b0f172f03 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::Pipeline, :mailer do @@ -320,43 +322,37 @@ describe Ci::Pipeline, :mailer do end end - describe '.mergeable_merge_request_pipelines' do - subject { described_class.mergeable_merge_request_pipelines(merge_request) } + describe '#merge_request_ref?' do + subject { pipeline.merge_request_ref? } - let!(:pipeline) do - create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, target_sha: target_sha) - end + it 'calls MergeRequest#merge_request_ref?' do + expect(MergeRequest).to receive(:merge_request_ref?).with(pipeline.ref) - let(:merge_request) { create(:merge_request) } - let(:target_sha) { merge_request.target_branch_sha } - - it 'returns mergeable merge pipelines' do - is_expected.to eq([pipeline]) - end - - context 'when target sha does not point the head of the target branch' do - let(:target_sha) { merge_request.diff_head_sha } - - it 'returns empty array' do - is_expected.to be_empty - end + subject end end - describe '#mergeable_merge_request_pipeline?' do - subject { pipeline.mergeable_merge_request_pipeline? } + describe '#legacy_detached_merge_request_pipeline?' do + subject { pipeline.legacy_detached_merge_request_pipeline? } - let!(:pipeline) do - create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, target_sha: target_sha) - end + set(:merge_request) { create(:merge_request) } + let(:ref) { 'feature' } + let(:target_sha) { nil } - let(:merge_request) { create(:merge_request) } - let(:target_sha) { merge_request.target_branch_sha } + let(:pipeline) do + build(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, ref: ref, target_sha: target_sha) + end it { is_expected.to be_truthy } - context 'when target sha does not point the head of the target branch' do - let(:target_sha) { merge_request.diff_head_sha } + context 'when pipeline ref is a merge request ref' do + let(:ref) { 'refs/merge-requests/1/head' } + + it { is_expected.to be_falsy } + end + + context 'when target sha is set' do + let(:target_sha) { 'target-sha' } it { is_expected.to be_falsy } end @@ -1460,6 +1456,14 @@ describe Ci::Pipeline, :mailer do end end + context 'with a branch name as the ref' do + it 'looks up commit with the full ref name' do + expect(pipeline.project).to receive(:commit).with('refs/heads/master').and_call_original + + expect(pipeline).to be_latest + end + end + context 'with not latest sha' do before do pipeline.update( diff --git a/spec/models/ci/pipeline_variable_spec.rb b/spec/models/ci/pipeline_variable_spec.rb index 03d09cb31d6..2ecb688299a 100644 --- a/spec/models/ci/pipeline_variable_spec.rb +++ b/spec/models/ci/pipeline_variable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::PipelineVariable do diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb index eb2daed7f32..b3ab63925dd 100644 --- a/spec/models/ci/runner_spec.rb +++ b/spec/models/ci/runner_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::Runner do diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb index 3228c400155..661958390e2 100644 --- a/spec/models/ci/stage_spec.rb +++ b/spec/models/ci/stage_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::Stage, :models do diff --git a/spec/models/ci/trigger_request_spec.rb b/spec/models/ci/trigger_request_spec.rb index 7dcf3528f73..d04349bec92 100644 --- a/spec/models/ci/trigger_request_spec.rb +++ b/spec/models/ci/trigger_request_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::TriggerRequest do diff --git a/spec/models/ci/trigger_spec.rb b/spec/models/ci/trigger_spec.rb index d4b72205203..fde8375f2a5 100644 --- a/spec/models/ci/trigger_spec.rb +++ b/spec/models/ci/trigger_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::Trigger do diff --git a/spec/models/ci/variable_spec.rb b/spec/models/ci/variable_spec.rb index 02c07a2bd83..d2df6b3344e 100644 --- a/spec/models/ci/variable_spec.rb +++ b/spec/models/ci/variable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::Variable do diff --git a/spec/models/clusters/applications/cert_manager_spec.rb b/spec/models/clusters/applications/cert_manager_spec.rb index cf5cbf8ec5c..af7eadfc74c 100644 --- a/spec/models/clusters/applications/cert_manager_spec.rb +++ b/spec/models/clusters/applications/cert_manager_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe Clusters::Applications::CertManager do @@ -9,7 +11,27 @@ describe Clusters::Applications::CertManager do include_examples 'cluster application initial status specs' describe '#install_command' do - let(:cluster_issuer_file) { { "cluster_issuer.yaml": "---\napiVersion: certmanager.k8s.io/v1alpha1\nkind: ClusterIssuer\nmetadata:\n name: letsencrypt-prod\nspec:\n acme:\n server: https://acme-v02.api.letsencrypt.org/directory\n email: admin@example.com\n privateKeySecretRef:\n name: letsencrypt-prod\n http01: {}\n" } } + let(:cert_email) { 'admin@example.com' } + + let(:cluster_issuer_file) do + file_contents = <<~EOF + --- + apiVersion: certmanager.k8s.io/v1alpha1 + kind: ClusterIssuer + metadata: + name: letsencrypt-prod + spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: #{cert_email} + privateKeySecretRef: + name: letsencrypt-prod + http01: {} + EOF + + { "cluster_issuer.yaml": file_contents } + end + subject { cert_manager.install_command } it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) } @@ -24,9 +46,10 @@ describe Clusters::Applications::CertManager do end context 'for a specific user' do + let(:cert_email) { 'abc@xyz.com' } + before do - cert_manager.email = 'abc@xyz.com' - cluster_issuer_file[:'cluster_issuer.yaml'].gsub! 'admin@example.com', 'abc@xyz.com' + cert_manager.email = cert_email end it 'should use his/her email to register issuer with certificate provider' do diff --git a/spec/models/clusters/applications/helm_spec.rb b/spec/models/clusters/applications/helm_spec.rb index f16eff92167..f97d126d918 100644 --- a/spec/models/clusters/applications/helm_spec.rb +++ b/spec/models/clusters/applications/helm_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe Clusters::Applications::Helm do diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb index a40fa988287..09e60b9a206 100644 --- a/spec/models/clusters/applications/ingress_spec.rb +++ b/spec/models/clusters/applications/ingress_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe Clusters::Applications::Ingress do diff --git a/spec/models/clusters/applications/jupyter_spec.rb b/spec/models/clusters/applications/jupyter_spec.rb index 2967c4076c6..5970a1959b5 100644 --- a/spec/models/clusters/applications/jupyter_spec.rb +++ b/spec/models/clusters/applications/jupyter_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe Clusters::Applications::Jupyter do diff --git a/spec/models/clusters/applications/knative_spec.rb b/spec/models/clusters/applications/knative_spec.rb index 054ed0be240..25493689fbc 100644 --- a/spec/models/clusters/applications/knative_spec.rb +++ b/spec/models/clusters/applications/knative_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe Clusters::Applications::Knative do diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb index 81708b0c2ed..82a502addd4 100644 --- a/spec/models/clusters/applications/prometheus_spec.rb +++ b/spec/models/clusters/applications/prometheus_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe Clusters::Applications::Prometheus do diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb index 3ce8aa1c7bc..7e2f5835279 100644 --- a/spec/models/clusters/applications/runner_spec.rb +++ b/spec/models/clusters/applications/runner_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe Clusters::Applications::Runner do diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb index acbcdc7d170..fabd2806d9a 100644 --- a/spec/models/clusters/cluster_spec.rb +++ b/spec/models/clusters/cluster_spec.rb @@ -620,4 +620,20 @@ describe Clusters::Cluster do end end end + + describe '#provided_by_user?' do + subject { cluster.provided_by_user? } + + context 'with a GCP provider' do + let(:cluster) { create(:cluster, :provided_by_gcp) } + + it { is_expected.to be_falsy } + end + + context 'with an user provider' do + let(:cluster) { create(:cluster, :provided_by_user) } + + it { is_expected.to be_truthy } + end + end end diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb index af65530e663..14bec17a2bd 100644 --- a/spec/models/clusters/platforms/kubernetes_spec.rb +++ b/spec/models/clusters/platforms/kubernetes_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching do @@ -15,7 +17,7 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching it { is_expected.to delegate_method(:project).to(:cluster) } it { is_expected.to delegate_method(:enabled?).to(:cluster) } - it { is_expected.to delegate_method(:managed?).to(:cluster) } + it { is_expected.to delegate_method(:provided_by_user?).to(:cluster) } it { is_expected.to delegate_method(:kubernetes_namespace).to(:cluster) } it_behaves_like 'having unique enum values' diff --git a/spec/models/clusters/project_spec.rb b/spec/models/clusters/project_spec.rb index 82ef5a23c18..2f017e69251 100644 --- a/spec/models/clusters/project_spec.rb +++ b/spec/models/clusters/project_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Clusters::Project do diff --git a/spec/models/clusters/providers/gcp_spec.rb b/spec/models/clusters/providers/gcp_spec.rb index 5012e6f15c6..785db4febe0 100644 --- a/spec/models/clusters/providers/gcp_spec.rb +++ b/spec/models/clusters/providers/gcp_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Clusters::Providers::Gcp do diff --git a/spec/models/commit_collection_spec.rb b/spec/models/commit_collection_spec.rb index 30c504ebea8..0bdf83fa90f 100644 --- a/spec/models/commit_collection_spec.rb +++ b/spec/models/commit_collection_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe CommitCollection do @@ -12,26 +14,26 @@ describe CommitCollection do end end - describe '.authors' do + describe '.committers' do it 'returns a relation of users when users are found' do - user = create(:user, email: commit.author_email.upcase) + user = create(:user, email: commit.committer_email.upcase) collection = described_class.new(project, [commit]) - expect(collection.authors).to contain_exactly(user) + expect(collection.committers).to contain_exactly(user) end - it 'returns empty array when authors cannot be found' do + it 'returns empty array when committers cannot be found' do collection = described_class.new(project, [commit]) - expect(collection.authors).to be_empty + expect(collection.committers).to be_empty end it 'excludes authors of merge commits' do commit = project.commit("60ecb67744cb56576c30214ff52294f8ce2def98") - create(:user, email: commit.author_email.upcase) + create(:user, email: commit.committer_email.upcase) collection = described_class.new(project, [commit]) - expect(collection.authors).to be_empty + expect(collection.committers).to be_empty end end diff --git a/spec/models/commit_range_spec.rb b/spec/models/commit_range_spec.rb index f2efcd9d0e9..b96ca89c893 100644 --- a/spec/models/commit_range_spec.rb +++ b/spec/models/commit_range_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe CommitRange do diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 9d4e18534ae..14f4b4d692f 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Commit do diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb index e2b7f5c6ee2..ca2f9e36c98 100644 --- a/spec/models/commit_status_spec.rb +++ b/spec/models/commit_status_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe CommitStatus do diff --git a/spec/models/compare_spec.rb b/spec/models/compare_spec.rb index 0bc3ee014e6..43c3580bed2 100644 --- a/spec/models/compare_spec.rb +++ b/spec/models/compare_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Compare do diff --git a/spec/models/concerns/access_requestable_spec.rb b/spec/models/concerns/access_requestable_spec.rb index 04d6cfa2c02..de2bc3a387b 100644 --- a/spec/models/concerns/access_requestable_spec.rb +++ b/spec/models/concerns/access_requestable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe AccessRequestable do diff --git a/spec/models/concerns/avatarable_spec.rb b/spec/models/concerns/avatarable_spec.rb index 1ea7f2b9985..c750be6b75c 100644 --- a/spec/models/concerns/avatarable_spec.rb +++ b/spec/models/concerns/avatarable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Avatarable do diff --git a/spec/models/concerns/awardable_spec.rb b/spec/models/concerns/awardable_spec.rb index 5713106418d..9e7106281ee 100644 --- a/spec/models/concerns/awardable_spec.rb +++ b/spec/models/concerns/awardable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Awardable do diff --git a/spec/models/concerns/batch_destroy_dependent_associations_spec.rb b/spec/models/concerns/batch_destroy_dependent_associations_spec.rb index e5392fe0462..1fe90d3cc9a 100644 --- a/spec/models/concerns/batch_destroy_dependent_associations_spec.rb +++ b/spec/models/concerns/batch_destroy_dependent_associations_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BatchDestroyDependentAssociations do diff --git a/spec/models/concerns/blocks_json_serialization_spec.rb b/spec/models/concerns/blocks_json_serialization_spec.rb index 5906b588d0e..e8657c45a93 100644 --- a/spec/models/concerns/blocks_json_serialization_spec.rb +++ b/spec/models/concerns/blocks_json_serialization_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe BlocksJsonSerialization do diff --git a/spec/models/concerns/cache_markdown_field_spec.rb b/spec/models/concerns/cache_markdown_field_spec.rb index 7d555f15e39..78637ff10c6 100644 --- a/spec/models/concerns/cache_markdown_field_spec.rb +++ b/spec/models/concerns/cache_markdown_field_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe CacheMarkdownField do diff --git a/spec/models/concerns/cacheable_attributes_spec.rb b/spec/models/concerns/cacheable_attributes_spec.rb index 43a544cfe26..394fac52aa7 100644 --- a/spec/models/concerns/cacheable_attributes_spec.rb +++ b/spec/models/concerns/cacheable_attributes_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe CacheableAttributes do diff --git a/spec/models/concerns/case_sensitivity_spec.rb b/spec/models/concerns/case_sensitivity_spec.rb index 1bf6c9b3404..d6d41a25eac 100644 --- a/spec/models/concerns/case_sensitivity_spec.rb +++ b/spec/models/concerns/case_sensitivity_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe CaseSensitivity do diff --git a/spec/models/concerns/chronic_duration_attribute_spec.rb b/spec/models/concerns/chronic_duration_attribute_spec.rb index 51221e07ca3..e41d75568f7 100644 --- a/spec/models/concerns/chronic_duration_attribute_spec.rb +++ b/spec/models/concerns/chronic_duration_attribute_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' shared_examples 'ChronicDurationAttribute reader' do diff --git a/spec/models/concerns/deployable_spec.rb b/spec/models/concerns/deployable_spec.rb index 6951be903fe..42bed9434f5 100644 --- a/spec/models/concerns/deployable_spec.rb +++ b/spec/models/concerns/deployable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe Deployable do diff --git a/spec/models/concerns/deployment_platform_spec.rb b/spec/models/concerns/deployment_platform_spec.rb index 19ab4382b53..0e34d8fccf3 100644 --- a/spec/models/concerns/deployment_platform_spec.rb +++ b/spec/models/concerns/deployment_platform_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe DeploymentPlatform do diff --git a/spec/models/concerns/discussion_on_diff_spec.rb b/spec/models/concerns/discussion_on_diff_spec.rb index 64bf04071e8..baddca47dfa 100644 --- a/spec/models/concerns/discussion_on_diff_spec.rb +++ b/spec/models/concerns/discussion_on_diff_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe DiscussionOnDiff do diff --git a/spec/models/concerns/each_batch_spec.rb b/spec/models/concerns/each_batch_spec.rb index 17224c09693..c4cf8e80f7a 100644 --- a/spec/models/concerns/each_batch_spec.rb +++ b/spec/models/concerns/each_batch_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe EachBatch do diff --git a/spec/models/concerns/editable_spec.rb b/spec/models/concerns/editable_spec.rb index 49a9a8ebcbc..4a4a3ca5687 100644 --- a/spec/models/concerns/editable_spec.rb +++ b/spec/models/concerns/editable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Editable do diff --git a/spec/models/concerns/expirable_spec.rb b/spec/models/concerns/expirable_spec.rb index f7b436f32e6..f4f5eab5b86 100644 --- a/spec/models/concerns/expirable_spec.rb +++ b/spec/models/concerns/expirable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Expirable do diff --git a/spec/models/concerns/faster_cache_keys_spec.rb b/spec/models/concerns/faster_cache_keys_spec.rb index 8d3f94267fa..7830acbae3d 100644 --- a/spec/models/concerns/faster_cache_keys_spec.rb +++ b/spec/models/concerns/faster_cache_keys_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe FasterCacheKeys do diff --git a/spec/models/concerns/feature_gate_spec.rb b/spec/models/concerns/feature_gate_spec.rb index 3f601243245..276d3d9e1d5 100644 --- a/spec/models/concerns/feature_gate_spec.rb +++ b/spec/models/concerns/feature_gate_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe FeatureGate do diff --git a/spec/models/concerns/group_descendant_spec.rb b/spec/models/concerns/group_descendant_spec.rb index 28352d8c961..194caac3fce 100644 --- a/spec/models/concerns/group_descendant_spec.rb +++ b/spec/models/concerns/group_descendant_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe GroupDescendant, :nested_groups do diff --git a/spec/models/concerns/has_status_spec.rb b/spec/models/concerns/has_status_spec.rb index e8b1eba67cc..a217dc42537 100644 --- a/spec/models/concerns/has_status_spec.rb +++ b/spec/models/concerns/has_status_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe HasStatus do diff --git a/spec/models/concerns/has_variable_spec.rb b/spec/models/concerns/has_variable_spec.rb index bff96e12ffa..2bb21d7934e 100644 --- a/spec/models/concerns/has_variable_spec.rb +++ b/spec/models/concerns/has_variable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe HasVariable do diff --git a/spec/models/concerns/ignorable_column_spec.rb b/spec/models/concerns/ignorable_column_spec.rb index b70f2331a0e..6b82825d2cc 100644 --- a/spec/models/concerns/ignorable_column_spec.rb +++ b/spec/models/concerns/ignorable_column_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe IgnorableColumn do diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index 72c6161424b..259ac6852a8 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Issuable do diff --git a/spec/models/concerns/issuable_states_spec.rb b/spec/models/concerns/issuable_states_spec.rb new file mode 100644 index 00000000000..70450159cc0 --- /dev/null +++ b/spec/models/concerns/issuable_states_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'spec_helper' + +# This spec checks if state_id column of issues and merge requests +# are being synced on every save. +# It can be removed in the next release. Check https://gitlab.com/gitlab-org/gitlab-ce/issues/51789 for more information. +describe IssuableStates do + [Issue, MergeRequest].each do |klass| + it "syncs state_id column when #{klass.model_name.human} gets created" do + klass.available_states.each do |state, state_id| + issuable = build(klass.model_name.param_key, state: state.to_s) + + issuable.save! + + expect(issuable.state_id).to eq(state_id) + end + end + + it "syncs state_id column when #{klass.model_name.human} gets updated" do + klass.available_states.each do |state, state_id| + issuable = create(klass.model_name.param_key, state: state.to_s) + + issuable.update(state: state) + + expect(issuable.state_id).to eq(state_id) + end + end + end +end diff --git a/spec/models/concerns/loaded_in_group_list_spec.rb b/spec/models/concerns/loaded_in_group_list_spec.rb index 7a279547a3a..7c97b580779 100644 --- a/spec/models/concerns/loaded_in_group_list_spec.rb +++ b/spec/models/concerns/loaded_in_group_list_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe LoadedInGroupList do diff --git a/spec/models/concerns/manual_inverse_association_spec.rb b/spec/models/concerns/manual_inverse_association_spec.rb index ff4a04ea573..ee32e3b165b 100644 --- a/spec/models/concerns/manual_inverse_association_spec.rb +++ b/spec/models/concerns/manual_inverse_association_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ManualInverseAssociation do diff --git a/spec/models/concerns/mentionable_spec.rb b/spec/models/concerns/mentionable_spec.rb index a9b237fa9ea..f31e3e8821d 100644 --- a/spec/models/concerns/mentionable_spec.rb +++ b/spec/models/concerns/mentionable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Mentionable do diff --git a/spec/models/concerns/milestoneish_spec.rb b/spec/models/concerns/milestoneish_spec.rb index 81ca5b638fe..22d4b2cc517 100644 --- a/spec/models/concerns/milestoneish_spec.rb +++ b/spec/models/concerns/milestoneish_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Milestone, 'Milestoneish' do diff --git a/spec/models/concerns/noteable_spec.rb b/spec/models/concerns/noteable_spec.rb index 485a6e165a1..ee613b199ad 100644 --- a/spec/models/concerns/noteable_spec.rb +++ b/spec/models/concerns/noteable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Noteable do diff --git a/spec/models/concerns/participable_spec.rb b/spec/models/concerns/participable_spec.rb index 431f1482615..3d5937c4fc6 100644 --- a/spec/models/concerns/participable_spec.rb +++ b/spec/models/concerns/participable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Participable do diff --git a/spec/models/concerns/presentable_spec.rb b/spec/models/concerns/presentable_spec.rb index 941647a79fb..9db868dd348 100644 --- a/spec/models/concerns/presentable_spec.rb +++ b/spec/models/concerns/presentable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Presentable do diff --git a/spec/models/concerns/project_features_compatibility_spec.rb b/spec/models/concerns/project_features_compatibility_spec.rb index 9041690023f..5aa43b58217 100644 --- a/spec/models/concerns/project_features_compatibility_spec.rb +++ b/spec/models/concerns/project_features_compatibility_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProjectFeaturesCompatibility do diff --git a/spec/models/concerns/prometheus_adapter_spec.rb b/spec/models/concerns/prometheus_adapter_spec.rb index f4b9c57e71a..db20a8b4701 100644 --- a/spec/models/concerns/prometheus_adapter_spec.rb +++ b/spec/models/concerns/prometheus_adapter_spec.rb @@ -1,17 +1,20 @@ +# frozen_string_literal: true + require 'spec_helper' describe PrometheusAdapter, :use_clean_rails_memory_store_caching do include PrometheusHelpers include ReactiveCachingHelpers - class TestClass - include PrometheusAdapter - end - let(:project) { create(:prometheus_project) } let(:service) { project.prometheus_service } - let(:described_class) { TestClass } + let(:described_class) do + Class.new do + include PrometheusAdapter + end + end + let(:environment_query) { Gitlab::Prometheus::Queries::EnvironmentQuery } describe '#query' do diff --git a/spec/models/concerns/protected_ref_access_spec.rb b/spec/models/concerns/protected_ref_access_spec.rb index ce602337647..94798f0590d 100644 --- a/spec/models/concerns/protected_ref_access_spec.rb +++ b/spec/models/concerns/protected_ref_access_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProtectedRefAccess do diff --git a/spec/models/concerns/reactive_caching_spec.rb b/spec/models/concerns/reactive_caching_spec.rb index 03ae45e6b17..32e13d5abed 100644 --- a/spec/models/concerns/reactive_caching_spec.rb +++ b/spec/models/concerns/reactive_caching_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ReactiveCaching, :use_clean_rails_memory_store_caching do diff --git a/spec/models/concerns/redactable_spec.rb b/spec/models/concerns/redactable_spec.rb index 7feeaa54069..57c7d2cb767 100644 --- a/spec/models/concerns/redactable_spec.rb +++ b/spec/models/concerns/redactable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Redactable do diff --git a/spec/models/concerns/redis_cacheable_spec.rb b/spec/models/concerns/redis_cacheable_spec.rb index 23c6c6233e9..a9dca27f258 100644 --- a/spec/models/concerns/redis_cacheable_spec.rb +++ b/spec/models/concerns/redis_cacheable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RedisCacheable do diff --git a/spec/models/concerns/relative_positioning_spec.rb b/spec/models/concerns/relative_positioning_spec.rb index ac8da30b6c9..d0ae45f7871 100644 --- a/spec/models/concerns/relative_positioning_spec.rb +++ b/spec/models/concerns/relative_positioning_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RelativePositioning do diff --git a/spec/models/concerns/resolvable_discussion_spec.rb b/spec/models/concerns/resolvable_discussion_spec.rb index 97b046b0f21..9ea01ca9002 100644 --- a/spec/models/concerns/resolvable_discussion_spec.rb +++ b/spec/models/concerns/resolvable_discussion_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Discussion, ResolvableDiscussion do diff --git a/spec/models/concerns/resolvable_note_spec.rb b/spec/models/concerns/resolvable_note_spec.rb index fcb5250278e..4f46252a044 100644 --- a/spec/models/concerns/resolvable_note_spec.rb +++ b/spec/models/concerns/resolvable_note_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Note, ResolvableNote do diff --git a/spec/models/concerns/routable_spec.rb b/spec/models/concerns/routable_spec.rb index 565266321d3..1fb0dd5030c 100644 --- a/spec/models/concerns/routable_spec.rb +++ b/spec/models/concerns/routable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Group, 'Routable' do diff --git a/spec/models/concerns/sha_attribute_spec.rb b/spec/models/concerns/sha_attribute_spec.rb index 0d3beb6a6e3..a4a81ae126d 100644 --- a/spec/models/concerns/sha_attribute_spec.rb +++ b/spec/models/concerns/sha_attribute_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ShaAttribute do diff --git a/spec/models/concerns/sortable_spec.rb b/spec/models/concerns/sortable_spec.rb index 0a9d2021a19..184f7986a6f 100644 --- a/spec/models/concerns/sortable_spec.rb +++ b/spec/models/concerns/sortable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Sortable do diff --git a/spec/models/concerns/spammable_spec.rb b/spec/models/concerns/spammable_spec.rb index e698207166c..650d49e41a1 100644 --- a/spec/models/concerns/spammable_spec.rb +++ b/spec/models/concerns/spammable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Spammable do diff --git a/spec/models/concerns/strip_attribute_spec.rb b/spec/models/concerns/strip_attribute_spec.rb index 8c945686b66..5c0d1042e06 100644 --- a/spec/models/concerns/strip_attribute_spec.rb +++ b/spec/models/concerns/strip_attribute_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe StripAttribute do diff --git a/spec/models/concerns/subscribable_spec.rb b/spec/models/concerns/subscribable_spec.rb index 45dfb136aea..2f88adf08dd 100644 --- a/spec/models/concerns/subscribable_spec.rb +++ b/spec/models/concerns/subscribable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Subscribable, 'Subscribable' do diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb index 40cb4eef60a..51e28974ae0 100644 --- a/spec/models/concerns/token_authenticatable_spec.rb +++ b/spec/models/concerns/token_authenticatable_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' shared_examples 'TokenAuthenticatable' do diff --git a/spec/models/concerns/token_authenticatable_strategies/base_spec.rb b/spec/models/concerns/token_authenticatable_strategies/base_spec.rb index 2a0182b4294..7332da309d5 100644 --- a/spec/models/concerns/token_authenticatable_strategies/base_spec.rb +++ b/spec/models/concerns/token_authenticatable_strategies/base_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe TokenAuthenticatableStrategies::Base do diff --git a/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb b/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb index ca38f86c5ab..70f41981b3b 100644 --- a/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb +++ b/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe TokenAuthenticatableStrategies::Encrypted do diff --git a/spec/models/concerns/triggerable_hooks_spec.rb b/spec/models/concerns/triggerable_hooks_spec.rb index 265abd6bd72..f28e5f56411 100644 --- a/spec/models/concerns/triggerable_hooks_spec.rb +++ b/spec/models/concerns/triggerable_hooks_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe TriggerableHooks do diff --git a/spec/models/concerns/uniquify_spec.rb b/spec/models/concerns/uniquify_spec.rb index 6cd2de6dcce..9ba35702ba6 100644 --- a/spec/models/concerns/uniquify_spec.rb +++ b/spec/models/concerns/uniquify_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Uniquify do diff --git a/spec/models/container_repository_spec.rb b/spec/models/container_repository_spec.rb index e46945e301e..013112d1d51 100644 --- a/spec/models/container_repository_spec.rb +++ b/spec/models/container_repository_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ContainerRepository do diff --git a/spec/models/conversational_development_index/metric_spec.rb b/spec/models/conversational_development_index/metric_spec.rb index b3193619503..60b1a860dfd 100644 --- a/spec/models/conversational_development_index/metric_spec.rb +++ b/spec/models/conversational_development_index/metric_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe ConversationalDevelopmentIndex::Metric do diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb index 6a6b58fb52b..b22a0340015 100644 --- a/spec/models/cycle_analytics/code_spec.rb +++ b/spec/models/cycle_analytics/code_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'CycleAnalytics#code' do diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb index 45f1b4fe8a3..07d60be091a 100644 --- a/spec/models/cycle_analytics/issue_spec.rb +++ b/spec/models/cycle_analytics/issue_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'CycleAnalytics#issue' do diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb index d366e2b723a..3d22a284264 100644 --- a/spec/models/cycle_analytics/plan_spec.rb +++ b/spec/models/cycle_analytics/plan_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'CycleAnalytics#plan' do diff --git a/spec/models/cycle_analytics/production_spec.rb b/spec/models/cycle_analytics/production_spec.rb index 156eb96cfce..383727cd8f7 100644 --- a/spec/models/cycle_analytics/production_spec.rb +++ b/spec/models/cycle_analytics/production_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'CycleAnalytics#production' do diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb index 0aedfb49cb5..1af5f9cc1f4 100644 --- a/spec/models/cycle_analytics/review_spec.rb +++ b/spec/models/cycle_analytics/review_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'CycleAnalytics#review' do diff --git a/spec/models/cycle_analytics/staging_spec.rb b/spec/models/cycle_analytics/staging_spec.rb index 0cbda50c688..8375944f03c 100644 --- a/spec/models/cycle_analytics/staging_spec.rb +++ b/spec/models/cycle_analytics/staging_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'CycleAnalytics#staging' do diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb index e58b8fdff58..b78258df564 100644 --- a/spec/models/cycle_analytics/test_spec.rb +++ b/spec/models/cycle_analytics/test_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'CycleAnalytics#test' do diff --git a/spec/models/cycle_analytics_spec.rb b/spec/models/cycle_analytics_spec.rb index 0fe24870f02..5d8b5b573cf 100644 --- a/spec/models/cycle_analytics_spec.rb +++ b/spec/models/cycle_analytics_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe CycleAnalytics do diff --git a/spec/models/deploy_key_spec.rb b/spec/models/deploy_key_spec.rb index 41440c6d288..ec6cfb6b826 100644 --- a/spec/models/deploy_key_spec.rb +++ b/spec/models/deploy_key_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe DeployKey, :mailer do diff --git a/spec/models/deploy_keys_project_spec.rb b/spec/models/deploy_keys_project_spec.rb index fca3090ff4a..c137444763b 100644 --- a/spec/models/deploy_keys_project_spec.rb +++ b/spec/models/deploy_keys_project_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe DeployKeysProject do diff --git a/spec/models/deploy_token_spec.rb b/spec/models/deploy_token_spec.rb index 3435f93c999..05320703e25 100644 --- a/spec/models/deploy_token_spec.rb +++ b/spec/models/deploy_token_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe DeployToken do diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb index 5fce9504334..d9170d5fa07 100644 --- a/spec/models/deployment_spec.rb +++ b/spec/models/deployment_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Deployment do diff --git a/spec/models/diff_discussion_spec.rb b/spec/models/diff_discussion_spec.rb index 50b19000799..cfeb4382927 100644 --- a/spec/models/diff_discussion_spec.rb +++ b/spec/models/diff_discussion_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe DiffDiscussion do diff --git a/spec/models/diff_note_spec.rb b/spec/models/diff_note_spec.rb index 67e5f4f7e41..fa19cb47a0d 100644 --- a/spec/models/diff_note_spec.rb +++ b/spec/models/diff_note_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe DiffNote do diff --git a/spec/models/diff_viewer/base_spec.rb b/spec/models/diff_viewer/base_spec.rb index f4efe5a7b3a..b8bdeb781dc 100644 --- a/spec/models/diff_viewer/base_spec.rb +++ b/spec/models/diff_viewer/base_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe DiffViewer::Base do diff --git a/spec/models/diff_viewer/server_side_spec.rb b/spec/models/diff_viewer/server_side_spec.rb index 86b14b6ebf3..27de0584b8a 100644 --- a/spec/models/diff_viewer/server_side_spec.rb +++ b/spec/models/diff_viewer/server_side_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe DiffViewer::ServerSide do diff --git a/spec/models/discussion_spec.rb b/spec/models/discussion_spec.rb index a46f7ed6507..0d02165787a 100644 --- a/spec/models/discussion_spec.rb +++ b/spec/models/discussion_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Discussion do diff --git a/spec/models/email_spec.rb b/spec/models/email_spec.rb index 47eb0717c0c..cae88f39660 100644 --- a/spec/models/email_spec.rb +++ b/spec/models/email_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Email do diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index ab1b306e597..ca5eed60b56 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Environment do @@ -590,7 +592,9 @@ describe Environment do shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do it 'returns the terminals from the deployment service' do - expect(project.deployment_platform) + deployment_platform_target = Gitlab.ee? ? environment : project + + expect(deployment_platform_target.deployment_platform) .to receive(:terminals).with(environment) .and_return(:fake_terminals) diff --git a/spec/models/environment_status_spec.rb b/spec/models/environment_status_spec.rb index 2576a9aba06..c503c35305f 100644 --- a/spec/models/environment_status_spec.rb +++ b/spec/models/environment_status_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe EnvironmentStatus do diff --git a/spec/models/error_tracking/project_error_tracking_setting_spec.rb b/spec/models/error_tracking/project_error_tracking_setting_spec.rb index cbde13a2c7a..21e381d9fb7 100644 --- a/spec/models/error_tracking/project_error_tracking_setting_spec.rb +++ b/spec/models/error_tracking/project_error_tracking_setting_spec.rb @@ -167,7 +167,7 @@ describe ErrorTracking::ProjectErrorTrackingSetting do end end - context 'when sentry client raises exception' do + context 'when sentry client raises Sentry::Client::Error' do let(:sentry_client) { spy(:sentry_client) } before do @@ -179,7 +179,31 @@ describe ErrorTracking::ProjectErrorTrackingSetting do end it 'returns error' do - expect(result).to eq(error: 'error message') + expect(result).to eq( + error: 'error message', + error_type: ErrorTracking::ProjectErrorTrackingSetting::SENTRY_API_ERROR_TYPE_NON_20X_RESPONSE + ) + expect(subject).to have_received(:sentry_client) + expect(sentry_client).to have_received(:list_issues) + end + end + + context 'when sentry client raises Sentry::Client::MissingKeysError' do + let(:sentry_client) { spy(:sentry_client) } + + before do + synchronous_reactive_cache(subject) + + allow(subject).to receive(:sentry_client).and_return(sentry_client) + allow(sentry_client).to receive(:list_issues).with(opts) + .and_raise(Sentry::Client::MissingKeysError, 'Sentry API response is missing keys. key not found: "id"') + end + + it 'returns error' do + expect(result).to eq( + error: 'Sentry API response is missing keys. key not found: "id"', + error_type: ErrorTracking::ProjectErrorTrackingSetting::SENTRY_API_ERROR_TYPE_MISSING_KEYS + ) expect(subject).to have_received(:sentry_client) expect(sentry_client).to have_received(:list_issues) end diff --git a/spec/models/event_collection_spec.rb b/spec/models/event_collection_spec.rb index 6078f429bdc..efe511042c3 100644 --- a/spec/models/event_collection_spec.rb +++ b/spec/models/event_collection_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe EventCollection do diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index ce4f8ee4705..d192fe70506 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Event do diff --git a/spec/models/external_issue_spec.rb b/spec/models/external_issue_spec.rb index 83ba22caa03..9d064d458f0 100644 --- a/spec/models/external_issue_spec.rb +++ b/spec/models/external_issue_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ExternalIssue do diff --git a/spec/models/fork_network_member_spec.rb b/spec/models/fork_network_member_spec.rb index 60d04562e6c..eab758248de 100644 --- a/spec/models/fork_network_member_spec.rb +++ b/spec/models/fork_network_member_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ForkNetworkMember do diff --git a/spec/models/fork_network_spec.rb b/spec/models/fork_network_spec.rb index a43baf1820a..5ec0f8d6b02 100644 --- a/spec/models/fork_network_spec.rb +++ b/spec/models/fork_network_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ForkNetwork do diff --git a/spec/models/generic_commit_status_spec.rb b/spec/models/generic_commit_status_spec.rb index a3e68d2e646..c851810ffb3 100644 --- a/spec/models/generic_commit_status_spec.rb +++ b/spec/models/generic_commit_status_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe GenericCommitStatus do diff --git a/spec/models/global_milestone_spec.rb b/spec/models/global_milestone_spec.rb index f93904065c7..9d901d01a52 100644 --- a/spec/models/global_milestone_spec.rb +++ b/spec/models/global_milestone_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe GlobalMilestone do diff --git a/spec/models/gpg_key_spec.rb b/spec/models/gpg_key_spec.rb index 58a1d2e4ea2..479b39cd139 100644 --- a/spec/models/gpg_key_spec.rb +++ b/spec/models/gpg_key_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe GpgKey do diff --git a/spec/models/gpg_key_subkey_spec.rb b/spec/models/gpg_key_subkey_spec.rb index 3c86837f47f..51d2f9cb9ac 100644 --- a/spec/models/gpg_key_subkey_spec.rb +++ b/spec/models/gpg_key_subkey_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe GpgKeySubkey do diff --git a/spec/models/gpg_signature_spec.rb b/spec/models/gpg_signature_spec.rb index e90319c39b1..47c343edf0e 100644 --- a/spec/models/gpg_signature_spec.rb +++ b/spec/models/gpg_signature_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe GpgSignature do diff --git a/spec/models/group_custom_attribute_spec.rb b/spec/models/group_custom_attribute_spec.rb index 7ecb2022567..7d60c74b62b 100644 --- a/spec/models/group_custom_attribute_spec.rb +++ b/spec/models/group_custom_attribute_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe GroupCustomAttribute do diff --git a/spec/models/group_label_spec.rb b/spec/models/group_label_spec.rb index d0fc1eaa3ec..a3a5c631c3d 100644 --- a/spec/models/group_label_spec.rb +++ b/spec/models/group_label_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe GroupLabel do diff --git a/spec/models/group_milestone_spec.rb b/spec/models/group_milestone_spec.rb index fcc33cd95fe..01856870fe0 100644 --- a/spec/models/group_milestone_spec.rb +++ b/spec/models/group_milestone_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe GroupMilestone do diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index 16624ce47d0..2c6abddca17 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Group do diff --git a/spec/models/guest_spec.rb b/spec/models/guest_spec.rb index fc30f3056e5..93862e98172 100644 --- a/spec/models/guest_spec.rb +++ b/spec/models/guest_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Guest do diff --git a/spec/models/hooks/active_hook_filter_spec.rb b/spec/models/hooks/active_hook_filter_spec.rb index df7edda2213..1249c793f7f 100644 --- a/spec/models/hooks/active_hook_filter_spec.rb +++ b/spec/models/hooks/active_hook_filter_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ActiveHookFilter do diff --git a/spec/models/hooks/project_hook_spec.rb b/spec/models/hooks/project_hook_spec.rb index 5dd31b1b5de..a945f0d1516 100644 --- a/spec/models/hooks/project_hook_spec.rb +++ b/spec/models/hooks/project_hook_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProjectHook do diff --git a/spec/models/hooks/service_hook_spec.rb b/spec/models/hooks/service_hook_spec.rb index e32eaafc13f..936c2fbad27 100644 --- a/spec/models/hooks/service_hook_spec.rb +++ b/spec/models/hooks/service_hook_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ServiceHook do diff --git a/spec/models/hooks/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb index edd1cb455af..e0d4d2e4858 100644 --- a/spec/models/hooks/system_hook_spec.rb +++ b/spec/models/hooks/system_hook_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe SystemHook do diff --git a/spec/models/hooks/web_hook_log_spec.rb b/spec/models/hooks/web_hook_log_spec.rb index 744a6ccae8b..f812149c9be 100644 --- a/spec/models/hooks/web_hook_log_spec.rb +++ b/spec/models/hooks/web_hook_log_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe WebHookLog do diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb index a308ac6e33a..fe08dc4f5e6 100644 --- a/spec/models/hooks/web_hook_spec.rb +++ b/spec/models/hooks/web_hook_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe WebHook do diff --git a/spec/models/identity_spec.rb b/spec/models/identity_spec.rb index e1a7a59dfd1..74ddc2d6284 100644 --- a/spec/models/identity_spec.rb +++ b/spec/models/identity_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Identity do diff --git a/spec/models/import_export_upload_spec.rb b/spec/models/import_export_upload_spec.rb index 58af84b8a08..18a714f4d98 100644 --- a/spec/models/import_export_upload_spec.rb +++ b/spec/models/import_export_upload_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ImportExportUpload do diff --git a/spec/models/instance_configuration_spec.rb b/spec/models/instance_configuration_spec.rb index cb3d6c7cda2..e65f97df3c3 100644 --- a/spec/models/instance_configuration_spec.rb +++ b/spec/models/instance_configuration_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe InstanceConfiguration do @@ -30,8 +32,8 @@ describe InstanceConfiguration do end def stub_pub_file(exist: true) - path = 'spec/fixtures/ssh_host_example_key.pub' - path << 'random' unless exist + path = exist ? 'spec/fixtures/ssh_host_example_key.pub' : 'spec/fixtures/ssh_host_example_key.pub.random' + allow(subject).to receive(:ssh_algorithm_file).and_return(Rails.root.join(path)) end end diff --git a/spec/models/internal_id_spec.rb b/spec/models/internal_id_spec.rb index d32f163f05b..ff2382838ae 100644 --- a/spec/models/internal_id_spec.rb +++ b/spec/models/internal_id_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe InternalId do diff --git a/spec/models/issue/metrics_spec.rb b/spec/models/issue/metrics_spec.rb index b7291eebe64..07858fe8a70 100644 --- a/spec/models/issue/metrics_spec.rb +++ b/spec/models/issue/metrics_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Issue::Metrics do diff --git a/spec/models/issue_collection_spec.rb b/spec/models/issue_collection_spec.rb index 580a98193af..7fc635f100f 100644 --- a/spec/models/issue_collection_spec.rb +++ b/spec/models/issue_collection_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe IssueCollection do diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index 6101df2e099..892dd053e39 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Issue do diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index 06d26ef89f1..a0b6eff88d5 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Key, :mailer do diff --git a/spec/models/label_link_spec.rb b/spec/models/label_link_spec.rb index e2b49bc2de7..b160e72e759 100644 --- a/spec/models/label_link_spec.rb +++ b/spec/models/label_link_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe LabelLink do diff --git a/spec/models/label_priority_spec.rb b/spec/models/label_priority_spec.rb index 9dcb0f06b20..1a93468290f 100644 --- a/spec/models/label_priority_spec.rb +++ b/spec/models/label_priority_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe LabelPriority do diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index 3fc6c06b7fa..5174c590a10 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Label do diff --git a/spec/models/legacy_diff_discussion_spec.rb b/spec/models/legacy_diff_discussion_spec.rb index dae97b69c84..49ea319fbd1 100644 --- a/spec/models/legacy_diff_discussion_spec.rb +++ b/spec/models/legacy_diff_discussion_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe LegacyDiffDiscussion do diff --git a/spec/models/lfs_download_object_spec.rb b/spec/models/lfs_download_object_spec.rb index 88838b127d2..effd8b08124 100644 --- a/spec/models/lfs_download_object_spec.rb +++ b/spec/models/lfs_download_object_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe LfsDownloadObject do diff --git a/spec/models/lfs_file_lock_spec.rb b/spec/models/lfs_file_lock_spec.rb index 41ca1578b94..aa64d66944b 100644 --- a/spec/models/lfs_file_lock_spec.rb +++ b/spec/models/lfs_file_lock_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe LfsFileLock do diff --git a/spec/models/lfs_object_spec.rb b/spec/models/lfs_object_spec.rb index 3f929710862..3d4d4b7d795 100644 --- a/spec/models/lfs_object_spec.rb +++ b/spec/models/lfs_object_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe LfsObject do diff --git a/spec/models/lfs_objects_project_spec.rb b/spec/models/lfs_objects_project_spec.rb index 0a3180f43e8..3e86ee38566 100644 --- a/spec/models/lfs_objects_project_spec.rb +++ b/spec/models/lfs_objects_project_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe LfsObjectsProject do diff --git a/spec/models/license_template_spec.rb b/spec/models/license_template_spec.rb index dd912eefac1..7037277e580 100644 --- a/spec/models/license_template_spec.rb +++ b/spec/models/license_template_spec.rb @@ -1,16 +1,19 @@ +# frozen_string_literal: true + require 'spec_helper' describe LicenseTemplate do describe '#content' do it 'calls a proc exactly once if provided' do - lazy = build_template(-> { 'bar' }) - content = lazy.content + content_proc = -> { 'bar' } + expect(content_proc).to receive(:call).once.and_call_original + + lazy = build_template(content_proc) - expect(content).to eq('bar') - expect(content.object_id).to eq(lazy.content.object_id) + expect(lazy.content).to eq('bar') - content.replace('foo') - expect(lazy.content).to eq('foo') + # Subsequent calls should not call proc again + expect(lazy.content).to eq('bar') end it 'returns a string if provided' do diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb index a51580f8292..18d4549977c 100644 --- a/spec/models/list_spec.rb +++ b/spec/models/list_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe List do diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 188beac1582..c68c3ce2abe 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Member do diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb index bc937368cff..f227abd3dae 100644 --- a/spec/models/members/group_member_spec.rb +++ b/spec/models/members/group_member_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe GroupMember do diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb index 36bfff2c339..497764b6825 100644 --- a/spec/models/members/project_member_spec.rb +++ b/spec/models/members/project_member_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProjectMember do diff --git a/spec/models/merge_request/metrics_spec.rb b/spec/models/merge_request/metrics_spec.rb index 02ff7839739..49573af0fed 100644 --- a/spec/models/merge_request/metrics_spec.rb +++ b/spec/models/merge_request/metrics_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe MergeRequest::Metrics do diff --git a/spec/models/merge_request_diff_commit_spec.rb b/spec/models/merge_request_diff_commit_spec.rb index 10487190a44..ab2aadf7d88 100644 --- a/spec/models/merge_request_diff_commit_spec.rb +++ b/spec/models/merge_request_diff_commit_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe MergeRequestDiffCommit do diff --git a/spec/models/merge_request_diff_file_spec.rb b/spec/models/merge_request_diff_file_spec.rb index faa47660a74..66957c24fdc 100644 --- a/spec/models/merge_request_diff_file_spec.rb +++ b/spec/models/merge_request_diff_file_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe MergeRequestDiffFile do diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb index 0f00ea7e85e..a53add67066 100644 --- a/spec/models/merge_request_diff_spec.rb +++ b/spec/models/merge_request_diff_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe MergeRequestDiff do diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index a1de0c63623..6f34ef9c1bc 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe MergeRequest do @@ -474,7 +476,6 @@ describe MergeRequest do it 'does not cache issues from external trackers' do issue = ExternalIssue.new('JIRA-123', subject.project) commit = double('commit1', safe_message: "Fixes #{issue.to_reference}") - allow(subject).to receive(:commits).and_return([commit]) expect { subject.cache_merge_request_closes_issues!(subject.author) }.not_to raise_error @@ -804,6 +805,14 @@ describe MergeRequest do expect(merge_request.commits).not_to be_empty expect(merge_request.related_notes.count).to eq(3) end + + it "excludes system notes for commits" do + system_note = create(:note_on_commit, :system, commit_id: merge_request.commits.first.id, + project: merge_request.project) + + expect(merge_request.related_notes.count).to eq(2) + expect(merge_request.related_notes).not_to include(system_note) + end end describe '#for_fork?' do @@ -1063,31 +1072,17 @@ describe MergeRequest do end end - describe '#commit_authors' do - it 'returns all the authors of every commit in the merge request' do - users = subject.commits.without_merge_commits.map(&:author_email).uniq.map do |email| + describe '#committers' do + it 'returns all the committers of every commit in the merge request' do + users = subject.commits.without_merge_commits.map(&:committer_email).uniq.map do |email| create(:user, email: email) end - expect(subject.commit_authors).to match_array(users) + expect(subject.committers).to match_array(users) end - it 'returns an empty array if no author is associated with a user' do - expect(subject.commit_authors).to be_empty - end - end - - describe '#authors' do - it 'returns a list with all the commit authors in the merge request and author' do - users = subject.commits.without_merge_commits.map(&:author_email).uniq.map do |email| - create(:user, email: email) - end - - expect(subject.authors).to match_array([subject.author, *users]) - end - - it 'returns only the author if no committer is associated with a user' do - expect(subject.authors).to contain_exactly(subject.author) + it 'returns an empty array if no committer is associated with a user' do + expect(subject.committers).to be_empty end end @@ -2712,14 +2707,21 @@ describe MergeRequest do end describe '#has_commits?' do - before do + it 'returns true when merge request diff has commits' do allow(subject.merge_request_diff).to receive(:commits_count) .and_return(2) - end - it 'returns true when merge request diff has commits' do expect(subject.has_commits?).to be_truthy end + + context 'when commits_count is nil' do + it 'returns false' do + allow(subject.merge_request_diff).to receive(:commits_count) + .and_return(nil) + + expect(subject.has_commits?).to be_falsey + end + end end describe '#has_no_commits?' do @@ -3081,6 +3083,38 @@ describe MergeRequest do end end + describe '#mergeable_to_ref?' do + it 'returns true when merge request is mergeable' do + subject = create(:merge_request) + + expect(subject.mergeable_to_ref?).to be(true) + end + + it 'returns false when merge request is already merged' do + subject = create(:merge_request, :merged) + + expect(subject.mergeable_to_ref?).to be(false) + end + + it 'returns false when merge request is closed' do + subject = create(:merge_request, :closed) + + expect(subject.mergeable_to_ref?).to be(false) + end + + it 'returns false when merge request is work in progress' do + subject = create(:merge_request, title: 'WIP: The feature') + + expect(subject.mergeable_to_ref?).to be(false) + end + + it 'returns false when merge request has no commits' do + subject = create(:merge_request, source_branch: 'empty-branch', target_branch: 'master') + + expect(subject.mergeable_to_ref?).to be(false) + end + end + describe '#merge_participants' do it 'contains author' do expect(subject.merge_participants).to eq([subject.author]) @@ -3115,4 +3149,32 @@ describe MergeRequest do end end end + + describe '.merge_request_ref?' do + subject { described_class.merge_request_ref?(ref) } + + context 'when ref is ref name of a branch' do + let(:ref) { 'feature' } + + it { is_expected.to be_falsey } + end + + context 'when ref is HEAD ref path of a branch' do + let(:ref) { 'refs/heads/feature' } + + it { is_expected.to be_falsey } + end + + context 'when ref is HEAD ref path of a merge request' do + let(:ref) { 'refs/merge-requests/1/head' } + + it { is_expected.to be_truthy } + end + + context 'when ref is merge ref path of a merge request' do + let(:ref) { 'refs/merge-requests/1/merge' } + + it { is_expected.to be_truthy } + end + end end diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb index 717d4ae4ec0..b82368318f2 100644 --- a/spec/models/milestone_spec.rb +++ b/spec/models/milestone_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Milestone do diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index aadc298ae0b..62e7dd3231b 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Namespace do diff --git a/spec/models/network/graph_spec.rb b/spec/models/network/graph_spec.rb index c364dd6643b..d1a2bedf542 100644 --- a/spec/models/network/graph_spec.rb +++ b/spec/models/network/graph_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Network::Graph do diff --git a/spec/models/note_diff_file_spec.rb b/spec/models/note_diff_file_spec.rb index 591c1a89748..99eeac8d778 100644 --- a/spec/models/note_diff_file_spec.rb +++ b/spec/models/note_diff_file_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe NoteDiffFile do diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index eb6f6ff5faf..7a1ab20186a 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Note do diff --git a/spec/models/notification_recipient_spec.rb b/spec/models/notification_recipient_spec.rb index 13fe47799ed..3710f2be287 100644 --- a/spec/models/notification_recipient_spec.rb +++ b/spec/models/notification_recipient_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe NotificationRecipient do diff --git a/spec/models/notification_setting_spec.rb b/spec/models/notification_setting_spec.rb index c8ab564e3bc..85128456918 100644 --- a/spec/models/notification_setting_spec.rb +++ b/spec/models/notification_setting_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe NotificationSetting do diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb index 4b85c5e8720..142ddebbbf8 100644 --- a/spec/models/pages_domain_spec.rb +++ b/spec/models/pages_domain_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PagesDomain do diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb index c82ab9c9e62..e0e1101ffc6 100644 --- a/spec/models/personal_access_token_spec.rb +++ b/spec/models/personal_access_token_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PersonalAccessToken do diff --git a/spec/models/pool_repository_spec.rb b/spec/models/pool_repository_spec.rb index 112d4ab56fc..e5a3a3ad66e 100644 --- a/spec/models/pool_repository_spec.rb +++ b/spec/models/pool_repository_spec.rb @@ -24,14 +24,14 @@ describe PoolRepository do end end - describe '#unlink_repository' do + describe '#mark_obsolete_if_last' do let(:pool) { create(:pool_repository, :ready) } context 'when the last member leaves' do it 'schedules pool removal' do expect(::ObjectPool::DestroyWorker).to receive(:perform_async).with(pool.id).and_call_original - pool.unlink_repository(pool.source_project.repository) + pool.mark_obsolete_if_last(pool.source_project.repository) end end @@ -40,7 +40,7 @@ describe PoolRepository do create(:project, :repository, pool_repository: pool) expect(::ObjectPool::DestroyWorker).not_to receive(:perform_async).with(pool.id) - pool.unlink_repository(pool.source_project.repository) + pool.mark_obsolete_if_last(pool.source_project.repository) end end end diff --git a/spec/models/programming_language_spec.rb b/spec/models/programming_language_spec.rb index 99cd358f863..b327d360461 100644 --- a/spec/models/programming_language_spec.rb +++ b/spec/models/programming_language_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProgrammingLanguage do diff --git a/spec/models/project_authorization_spec.rb b/spec/models/project_authorization_spec.rb index c289ee0859a..6f06fe4e55a 100644 --- a/spec/models/project_authorization_spec.rb +++ b/spec/models/project_authorization_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProjectAuthorization do diff --git a/spec/models/project_auto_devops_spec.rb b/spec/models/project_auto_devops_spec.rb index 7ff64c76e37..8ad28ce68cc 100644 --- a/spec/models/project_auto_devops_spec.rb +++ b/spec/models/project_auto_devops_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProjectAutoDevops do diff --git a/spec/models/project_custom_attribute_spec.rb b/spec/models/project_custom_attribute_spec.rb index 669de5506bc..80638676b49 100644 --- a/spec/models/project_custom_attribute_spec.rb +++ b/spec/models/project_custom_attribute_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProjectCustomAttribute do diff --git a/spec/models/project_deploy_token_spec.rb b/spec/models/project_deploy_token_spec.rb index 9e2e40c2e8f..2a5fefc1ab0 100644 --- a/spec/models/project_deploy_token_spec.rb +++ b/spec/models/project_deploy_token_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe ProjectDeployToken, type: :model do diff --git a/spec/models/project_feature_spec.rb b/spec/models/project_feature_spec.rb index fee7d65c217..50c9d5968ac 100644 --- a/spec/models/project_feature_spec.rb +++ b/spec/models/project_feature_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProjectFeature do diff --git a/spec/models/project_group_link_spec.rb b/spec/models/project_group_link_spec.rb index 5bea21427d4..dad5506900b 100644 --- a/spec/models/project_group_link_spec.rb +++ b/spec/models/project_group_link_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProjectGroupLink do diff --git a/spec/models/project_import_state_spec.rb b/spec/models/project_import_state_spec.rb index e3b2d971419..472bf8f9713 100644 --- a/spec/models/project_import_state_spec.rb +++ b/spec/models/project_import_state_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe ProjectImportState, type: :model do diff --git a/spec/models/project_label_spec.rb b/spec/models/project_label_spec.rb index 689d4e505e5..330aab9f856 100644 --- a/spec/models/project_label_spec.rb +++ b/spec/models/project_label_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProjectLabel do diff --git a/spec/models/project_services/asana_service_spec.rb b/spec/models/project_services/asana_service_spec.rb index e66109fd98f..18e839bcc64 100644 --- a/spec/models/project_services/asana_service_spec.rb +++ b/spec/models/project_services/asana_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe AsanaService do diff --git a/spec/models/project_services/assembla_service_spec.rb b/spec/models/project_services/assembla_service_spec.rb index 5cb6d63659e..7742e33e901 100644 --- a/spec/models/project_services/assembla_service_spec.rb +++ b/spec/models/project_services/assembla_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe AssemblaService do diff --git a/spec/models/project_services/bamboo_service_spec.rb b/spec/models/project_services/bamboo_service_spec.rb index b880d90d28f..08c510f09df 100644 --- a/spec/models/project_services/bamboo_service_spec.rb +++ b/spec/models/project_services/bamboo_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BambooService, :use_clean_rails_memory_store_caching do diff --git a/spec/models/project_services/bugzilla_service_spec.rb b/spec/models/project_services/bugzilla_service_spec.rb index 43f7bcb1a19..6818db48fee 100644 --- a/spec/models/project_services/bugzilla_service_spec.rb +++ b/spec/models/project_services/bugzilla_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BugzillaService do diff --git a/spec/models/project_services/buildkite_service_spec.rb b/spec/models/project_services/buildkite_service_spec.rb index 1615a93a4ca..091d4d8f695 100644 --- a/spec/models/project_services/buildkite_service_spec.rb +++ b/spec/models/project_services/buildkite_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BuildkiteService, :use_clean_rails_memory_store_caching do diff --git a/spec/models/project_services/campfire_service_spec.rb b/spec/models/project_services/campfire_service_spec.rb index ed8347edffd..bf4c52fc7ab 100644 --- a/spec/models/project_services/campfire_service_spec.rb +++ b/spec/models/project_services/campfire_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe CampfireService do diff --git a/spec/models/project_services/chat_message/issue_message_spec.rb b/spec/models/project_services/chat_message/issue_message_spec.rb index f7a35fdc88a..d3adc62c38e 100644 --- a/spec/models/project_services/chat_message/issue_message_spec.rb +++ b/spec/models/project_services/chat_message/issue_message_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ChatMessage::IssueMessage do diff --git a/spec/models/project_services/chat_message/merge_message_spec.rb b/spec/models/project_services/chat_message/merge_message_spec.rb index 7997b5bb6b9..b56eb19dd55 100644 --- a/spec/models/project_services/chat_message/merge_message_spec.rb +++ b/spec/models/project_services/chat_message/merge_message_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ChatMessage::MergeMessage do diff --git a/spec/models/project_services/chat_message/note_message_spec.rb b/spec/models/project_services/chat_message/note_message_spec.rb index 5abbd7bec18..5e7987dc0f6 100644 --- a/spec/models/project_services/chat_message/note_message_spec.rb +++ b/spec/models/project_services/chat_message/note_message_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ChatMessage::NoteMessage 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 0ff20400999..8f9fa310ad4 100644 --- a/spec/models/project_services/chat_message/pipeline_message_spec.rb +++ b/spec/models/project_services/chat_message/pipeline_message_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ChatMessage::PipelineMessage 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 973d6bdb2a0..a89645a3ea8 100644 --- a/spec/models/project_services/chat_message/push_message_spec.rb +++ b/spec/models/project_services/chat_message/push_message_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ChatMessage::PushMessage do diff --git a/spec/models/project_services/chat_message/wiki_page_message_spec.rb b/spec/models/project_services/chat_message/wiki_page_message_spec.rb index 7efcba9bcfd..c3db516f253 100644 --- a/spec/models/project_services/chat_message/wiki_page_message_spec.rb +++ b/spec/models/project_services/chat_message/wiki_page_message_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ChatMessage::WikiPageMessage do diff --git a/spec/models/project_services/chat_notification_service_spec.rb b/spec/models/project_services/chat_notification_service_spec.rb index 46713df77da..6f4ddd223f6 100644 --- a/spec/models/project_services/chat_notification_service_spec.rb +++ b/spec/models/project_services/chat_notification_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ChatNotificationService do diff --git a/spec/models/project_services/custom_issue_tracker_service_spec.rb b/spec/models/project_services/custom_issue_tracker_service_spec.rb index 7e1b1a4f2af..f0e7551693d 100644 --- a/spec/models/project_services/custom_issue_tracker_service_spec.rb +++ b/spec/models/project_services/custom_issue_tracker_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe CustomIssueTrackerService do diff --git a/spec/models/project_services/drone_ci_service_spec.rb b/spec/models/project_services/drone_ci_service_spec.rb index 26597d9b83c..22df19d943f 100644 --- a/spec/models/project_services/drone_ci_service_spec.rb +++ b/spec/models/project_services/drone_ci_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe DroneCiService, :use_clean_rails_memory_store_caching do diff --git a/spec/models/project_services/emails_on_push_service_spec.rb b/spec/models/project_services/emails_on_push_service_spec.rb index d9b7010e5e5..0a58eb367e3 100644 --- a/spec/models/project_services/emails_on_push_service_spec.rb +++ b/spec/models/project_services/emails_on_push_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe EmailsOnPushService do diff --git a/spec/models/project_services/external_wiki_service_spec.rb b/spec/models/project_services/external_wiki_service_spec.rb index 62fd97b038b..bdd8605436f 100644 --- a/spec/models/project_services/external_wiki_service_spec.rb +++ b/spec/models/project_services/external_wiki_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ExternalWikiService do diff --git a/spec/models/project_services/flowdock_service_spec.rb b/spec/models/project_services/flowdock_service_spec.rb index fabcb142858..c1ebe69ee66 100644 --- a/spec/models/project_services/flowdock_service_spec.rb +++ b/spec/models/project_services/flowdock_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe FlowdockService do diff --git a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb index 3237b660a16..11f96c03d46 100644 --- a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb +++ b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe GitlabIssueTrackerService do diff --git a/spec/models/project_services/irker_service_spec.rb b/spec/models/project_services/irker_service_spec.rb index cb9ca76fc3f..2e1f6964692 100644 --- a/spec/models/project_services/irker_service_spec.rb +++ b/spec/models/project_services/irker_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' require 'socket' require 'json' diff --git a/spec/models/project_services/issue_tracker_service_spec.rb b/spec/models/project_services/issue_tracker_service_spec.rb index e6a1752576b..2fc4d69c2db 100644 --- a/spec/models/project_services/issue_tracker_service_spec.rb +++ b/spec/models/project_services/issue_tracker_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe IssueTrackerService do diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index 5428fcb1271..4a7eee1fbf3 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe JiraService do diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb index 56e587262ef..7bf093b71e7 100644 --- a/spec/models/project_services/kubernetes_service_spec.rb +++ b/spec/models/project_services/kubernetes_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe KubernetesService, :use_clean_rails_memory_store_caching do diff --git a/spec/models/project_services/mattermost_service_spec.rb b/spec/models/project_services/mattermost_service_spec.rb index 10c62ca55a7..6261c70f266 100644 --- a/spec/models/project_services/mattermost_service_spec.rb +++ b/spec/models/project_services/mattermost_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe MattermostService do diff --git a/spec/models/project_services/mattermost_slash_commands_service_spec.rb b/spec/models/project_services/mattermost_slash_commands_service_spec.rb index 1983e0cc967..87e482059f2 100644 --- a/spec/models/project_services/mattermost_slash_commands_service_spec.rb +++ b/spec/models/project_services/mattermost_slash_commands_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe MattermostSlashCommandsService do diff --git a/spec/models/project_services/microsoft_teams_service_spec.rb b/spec/models/project_services/microsoft_teams_service_spec.rb index 3351c6280b4..521d5265753 100644 --- a/spec/models/project_services/microsoft_teams_service_spec.rb +++ b/spec/models/project_services/microsoft_teams_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe MicrosoftTeamsService do diff --git a/spec/models/project_services/packagist_service_spec.rb b/spec/models/project_services/packagist_service_spec.rb index 6acee311700..53f18a1bdd9 100644 --- a/spec/models/project_services/packagist_service_spec.rb +++ b/spec/models/project_services/packagist_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PackagistService do diff --git a/spec/models/project_services/pipelines_email_service_spec.rb b/spec/models/project_services/pipelines_email_service_spec.rb index 75ae2207910..ca17e7453b8 100644 --- a/spec/models/project_services/pipelines_email_service_spec.rb +++ b/spec/models/project_services/pipelines_email_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PipelinesEmailService, :mailer do diff --git a/spec/models/project_services/pivotaltracker_service_spec.rb b/spec/models/project_services/pivotaltracker_service_spec.rb index f7d2372eca2..de2c8790405 100644 --- a/spec/models/project_services/pivotaltracker_service_spec.rb +++ b/spec/models/project_services/pivotaltracker_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PivotaltrackerService do diff --git a/spec/models/project_services/pushover_service_spec.rb b/spec/models/project_services/pushover_service_spec.rb index 54b8c658ff6..d2a45f48705 100644 --- a/spec/models/project_services/pushover_service_spec.rb +++ b/spec/models/project_services/pushover_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PushoverService do diff --git a/spec/models/project_services/redmine_service_spec.rb b/spec/models/project_services/redmine_service_spec.rb index 2ac14eab5e1..ac570ac27e1 100644 --- a/spec/models/project_services/redmine_service_spec.rb +++ b/spec/models/project_services/redmine_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RedmineService do diff --git a/spec/models/project_services/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb index 13cf4d1915e..01f580c5d01 100644 --- a/spec/models/project_services/slack_service_spec.rb +++ b/spec/models/project_services/slack_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe SlackService do diff --git a/spec/models/project_services/slack_slash_commands_service_spec.rb b/spec/models/project_services/slack_slash_commands_service_spec.rb index 5c4bce90ace..8c57907d064 100644 --- a/spec/models/project_services/slack_slash_commands_service_spec.rb +++ b/spec/models/project_services/slack_slash_commands_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe SlackSlashCommandsService do diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/project_services/teamcity_service_spec.rb index 64b4efca43a..96dccae733b 100644 --- a/spec/models/project_services/teamcity_service_spec.rb +++ b/spec/models/project_services/teamcity_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe TeamcityService, :use_clean_rails_memory_store_caching do diff --git a/spec/models/project_services/youtrack_service_spec.rb b/spec/models/project_services/youtrack_service_spec.rb index 9524b526a46..bf9d892f66c 100644 --- a/spec/models/project_services/youtrack_service_spec.rb +++ b/spec/models/project_services/youtrack_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe YoutrackService do diff --git a/spec/models/project_snippet_spec.rb b/spec/models/project_snippet_spec.rb index 1b439bcfad1..e87b4f41f4d 100644 --- a/spec/models/project_snippet_spec.rb +++ b/spec/models/project_snippet_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProjectSnippet do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 90dcf861849..33e514cd7b9 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Project do @@ -2141,6 +2143,15 @@ describe Project do expect(project.add_import_job).to eq(import_jid) end + + context 'without repository' do + it 'schedules RepositoryImportWorker' do + project = create(:project, import_url: generate(:url)) + + expect(RepositoryImportWorker).to receive(:perform_async).with(project.id).and_return(import_jid) + expect(project.add_import_job).to eq(import_jid) + end + end end context 'not forked' do diff --git a/spec/models/project_statistics_spec.rb b/spec/models/project_statistics_spec.rb index 64c39f09e33..c670b6aac56 100644 --- a/spec/models/project_statistics_spec.rb +++ b/spec/models/project_statistics_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe ProjectStatistics do diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb index 3537dead5d1..77c88a04cde 100644 --- a/spec/models/project_team_spec.rb +++ b/spec/models/project_team_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe ProjectTeam do @@ -193,6 +195,30 @@ describe ProjectTeam do end end + describe '#add_users' do + let(:user1) { create(:user) } + let(:user2) { create(:user) } + let(:project) { create(:project) } + + it 'add the given users to the team' do + project.team.add_users([user1, user2], :reporter) + + expect(project.team.reporter?(user1)).to be(true) + expect(project.team.reporter?(user2)).to be(true) + end + end + + describe '#add_user' do + let(:user) { create(:user) } + let(:project) { create(:project) } + + it 'add the given user to the team' do + project.team.add_user(user, :reporter) + + expect(project.team.reporter?(user)).to be(true) + end + end + describe "#human_max_access" do it 'returns Maintainer role' do user = create(:user) diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index 7be8d67ba9e..2525a6aebe0 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -1,4 +1,5 @@ -# coding: utf-8 +# frozen_string_literal: true + require "spec_helper" describe ProjectWiki do diff --git a/spec/models/protectable_dropdown_spec.rb b/spec/models/protectable_dropdown_spec.rb index d4433a88a15..aca3df9fdde 100644 --- a/spec/models/protectable_dropdown_spec.rb +++ b/spec/models/protectable_dropdown_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProtectableDropdown do diff --git a/spec/models/protected_branch/merge_access_level_spec.rb b/spec/models/protected_branch/merge_access_level_spec.rb index 612e4a0e332..39dd586b157 100644 --- a/spec/models/protected_branch/merge_access_level_spec.rb +++ b/spec/models/protected_branch/merge_access_level_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProtectedBranch::MergeAccessLevel do diff --git a/spec/models/protected_branch/push_access_level_spec.rb b/spec/models/protected_branch/push_access_level_spec.rb index 9ccdc22fd41..628c8d29ecd 100644 --- a/spec/models/protected_branch/push_access_level_spec.rb +++ b/spec/models/protected_branch/push_access_level_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProtectedBranch::PushAccessLevel do diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb index dafe7646366..267434a4148 100644 --- a/spec/models/protected_branch_spec.rb +++ b/spec/models/protected_branch_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProtectedBranch do diff --git a/spec/models/protected_tag_spec.rb b/spec/models/protected_tag_spec.rb index e5a0f6ec23f..79120d17d39 100644 --- a/spec/models/protected_tag_spec.rb +++ b/spec/models/protected_tag_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProtectedTag do diff --git a/spec/models/push_event_payload_spec.rb b/spec/models/push_event_payload_spec.rb index 69a4922b6fd..6b59ee5ee57 100644 --- a/spec/models/push_event_payload_spec.rb +++ b/spec/models/push_event_payload_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PushEventPayload do diff --git a/spec/models/push_event_spec.rb b/spec/models/push_event_spec.rb index bfe7a30b96a..f86500f91cd 100644 --- a/spec/models/push_event_spec.rb +++ b/spec/models/push_event_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PushEvent do diff --git a/spec/models/redirect_route_spec.rb b/spec/models/redirect_route_spec.rb index 106ae59af29..6ecb5c31c7e 100644 --- a/spec/models/redirect_route_spec.rb +++ b/spec/models/redirect_route_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe RedirectRoute do diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb index 157c96c1f65..b4b32c95dee 100644 --- a/spec/models/release_spec.rb +++ b/spec/models/release_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe Release do diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb index c06e9a08ab4..0478094034a 100644 --- a/spec/models/remote_mirror_spec.rb +++ b/spec/models/remote_mirror_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe RemoteMirror, :mailer do diff --git a/spec/models/repository_language_spec.rb b/spec/models/repository_language_spec.rb index e2e4beb512f..13a4cd1e7cf 100644 --- a/spec/models/repository_language_spec.rb +++ b/spec/models/repository_language_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RepositoryLanguage do diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 6599b4e765a..2578208659a 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Repository do diff --git a/spec/models/route_spec.rb b/spec/models/route_spec.rb index 48799781b87..20289afbeb5 100644 --- a/spec/models/route_spec.rb +++ b/spec/models/route_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Route do diff --git a/spec/models/sent_notification_spec.rb b/spec/models/sent_notification_spec.rb index 6c35ed8f649..09be90b82ed 100644 --- a/spec/models/sent_notification_spec.rb +++ b/spec/models/sent_notification_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe SentNotification do diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb index 25eecb3f909..2f025038bab 100644 --- a/spec/models/service_spec.rb +++ b/spec/models/service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Service do diff --git a/spec/models/snippet_blob_spec.rb b/spec/models/snippet_blob_spec.rb index 7c71c458fcc..88441e39d45 100644 --- a/spec/models/snippet_blob_spec.rb +++ b/spec/models/snippet_blob_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe SnippetBlob do diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb index 664dc3fa145..3524cdae3b8 100644 --- a/spec/models/snippet_spec.rb +++ b/spec/models/snippet_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Snippet do diff --git a/spec/models/spam_log_spec.rb b/spec/models/spam_log_spec.rb index 90a2caaeb88..e9ea234f75d 100644 --- a/spec/models/spam_log_spec.rb +++ b/spec/models/spam_log_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe SpamLog do diff --git a/spec/models/ssh_host_key_spec.rb b/spec/models/ssh_host_key_spec.rb index 4c677569561..a17cd8ba345 100644 --- a/spec/models/ssh_host_key_spec.rb +++ b/spec/models/ssh_host_key_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe SshHostKey do diff --git a/spec/models/subscription_spec.rb b/spec/models/subscription_spec.rb index 9e4c2620d82..41bd48810b2 100644 --- a/spec/models/subscription_spec.rb +++ b/spec/models/subscription_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Subscription do diff --git a/spec/models/system_note_metadata_spec.rb b/spec/models/system_note_metadata_spec.rb index 1e3f587e460..bcd3c03f947 100644 --- a/spec/models/system_note_metadata_spec.rb +++ b/spec/models/system_note_metadata_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe SystemNoteMetadata do diff --git a/spec/models/term_agreement_spec.rb b/spec/models/term_agreement_spec.rb index 950dfa09a6a..42a48048b67 100644 --- a/spec/models/term_agreement_spec.rb +++ b/spec/models/term_agreement_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe TermAgreement do diff --git a/spec/models/timelog_spec.rb b/spec/models/timelog_spec.rb index a0c93c531ea..9d69a0ab148 100644 --- a/spec/models/timelog_spec.rb +++ b/spec/models/timelog_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe Timelog do diff --git a/spec/models/todo_spec.rb b/spec/models/todo_spec.rb index 3682e21ca40..b5bf294790a 100644 --- a/spec/models/todo_spec.rb +++ b/spec/models/todo_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Todo do diff --git a/spec/models/tree_spec.rb b/spec/models/tree_spec.rb index 6bdb62a0864..c2d5dfdf9c4 100644 --- a/spec/models/tree_spec.rb +++ b/spec/models/tree_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Tree do diff --git a/spec/models/trending_project_spec.rb b/spec/models/trending_project_spec.rb index 3b5e7ca0d39..619fc8e7d38 100644 --- a/spec/models/trending_project_spec.rb +++ b/spec/models/trending_project_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe TrendingProject do diff --git a/spec/models/upload_spec.rb b/spec/models/upload_spec.rb index 5a0df9fbbb0..02702cb2497 100644 --- a/spec/models/upload_spec.rb +++ b/spec/models/upload_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe Upload do diff --git a/spec/models/user_agent_detail_spec.rb b/spec/models/user_agent_detail_spec.rb index b4669f8c1c2..f191d245045 100644 --- a/spec/models/user_agent_detail_spec.rb +++ b/spec/models/user_agent_detail_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe UserAgentDetail do diff --git a/spec/models/user_callout_spec.rb b/spec/models/user_callout_spec.rb index d54355afe12..b87f6f03d6f 100644 --- a/spec/models/user_callout_spec.rb +++ b/spec/models/user_callout_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe UserCallout do diff --git a/spec/models/user_custom_attribute_spec.rb b/spec/models/user_custom_attribute_spec.rb index 37fc3cb64f0..d0981b2d771 100644 --- a/spec/models/user_custom_attribute_spec.rb +++ b/spec/models/user_custom_attribute_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe UserCustomAttribute do diff --git a/spec/models/user_interacted_project_spec.rb b/spec/models/user_interacted_project_spec.rb index cb4bb3372d4..47d919c1d12 100644 --- a/spec/models/user_interacted_project_spec.rb +++ b/spec/models/user_interacted_project_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe UserInteractedProject do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 1be29d039a7..b7e36748fa2 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe User do diff --git a/spec/models/wiki_directory_spec.rb b/spec/models/wiki_directory_spec.rb index fb8575cfe2b..5fbcccf897e 100644 --- a/spec/models/wiki_directory_spec.rb +++ b/spec/models/wiki_directory_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe WikiDirectory do diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb index cba22b2cc4e..e68da67818a 100644 --- a/spec/models/wiki_page_spec.rb +++ b/spec/models/wiki_page_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe WikiPage do diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index 726ccba8807..125ed818bc6 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -2,6 +2,96 @@ require 'spec_helper' describe ProjectPolicy do include_context 'ProjectPolicy context' + set(:guest) { create(:user) } + set(:reporter) { create(:user) } + set(:developer) { create(:user) } + set(:maintainer) { create(:user) } + set(:owner) { create(:user) } + set(:admin) { create(:admin) } + let(:project) { create(:project, :public, namespace: owner.namespace) } + + let(:base_guest_permissions) do + %i[ + read_project read_board read_list read_wiki read_issue + read_project_for_iids read_issue_iid read_label + read_milestone read_project_snippet read_project_member read_note + create_project create_issue create_note upload_file create_merge_request_in + award_emoji + ] + end + + let(:base_reporter_permissions) do + %i[ + download_code fork_project create_project_snippet update_issue + admin_issue admin_label admin_list read_commit_status read_build + read_container_image read_pipeline read_environment read_deployment + read_merge_request download_wiki_code read_sentry_issue read_release + ] + end + + let(:team_member_reporter_permissions) do + %i[build_download_code build_read_container_image] + end + + let(:developer_permissions) do + %i[ + admin_milestone admin_merge_request update_merge_request create_commit_status + update_commit_status create_build update_build create_pipeline + update_pipeline create_merge_request_from create_wiki push_code + resolve_note create_container_image update_container_image + create_environment create_deployment create_release update_release + ] + end + + let(:base_maintainer_permissions) do + %i[ + push_to_delete_protected_branch update_project_snippet update_environment + update_deployment admin_project_snippet admin_project_member admin_note admin_wiki admin_project + admin_commit_status admin_build admin_container_image + admin_pipeline admin_environment admin_deployment destroy_release add_cluster + daily_statistics + ] + end + + let(:public_permissions) do + %i[ + download_code fork_project read_commit_status read_pipeline + read_container_image build_download_code build_read_container_image + download_wiki_code read_release + ] + end + + let(:owner_permissions) do + %i[ + change_namespace change_visibility_level rename_project remove_project + archive_project remove_fork_project destroy_merge_request destroy_issue + set_issue_iid set_issue_created_at set_note_created_at + ] + end + + # Used in EE specs + let(:additional_guest_permissions) { [] } + let(:additional_reporter_permissions) { [] } + let(:additional_maintainer_permissions) { [] } + + let(:guest_permissions) { base_guest_permissions + additional_guest_permissions } + let(:reporter_permissions) { base_reporter_permissions + additional_reporter_permissions } + let(:maintainer_permissions) { base_maintainer_permissions + additional_maintainer_permissions } + + before do + project.add_guest(guest) + project.add_maintainer(maintainer) + project.add_developer(developer) + project.add_reporter(reporter) + end + + def expect_allowed(*permissions) + permissions.each { |p| is_expected.to be_allowed(p) } + end + + def expect_disallowed(*permissions) + permissions.each { |p| is_expected.not_to be_allowed(p) } + end it 'does not include the read_issue permission when the issue author is not a member of the private project' do project = create(:project, :private) diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb index f50bcf54b46..ad6cb012d0b 100644 --- a/spec/presenters/ci/build_runner_presenter_spec.rb +++ b/spec/presenters/ci/build_runner_presenter_spec.rb @@ -136,6 +136,24 @@ describe Ci::BuildRunnerPresenter do is_expected.to eq(1) end end + + context 'when pipeline is detached merge request pipeline' do + let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) } + let(:pipeline) { merge_request.all_pipelines.first } + let(:build) { create(:ci_build, ref: pipeline.ref, pipeline: pipeline) } + + it 'returns the default git depth for pipelines for merge requests' do + is_expected.to eq(described_class::DEFAULT_GIT_DEPTH_MERGE_REQUEST) + end + + context 'when pipeline is legacy detached merge request pipeline' do + let(:merge_request) { create(:merge_request, :with_legacy_detached_merge_request_pipeline) } + + it 'behaves as branch pipeline' do + is_expected.to eq(0) + end + end + end end describe '#refspecs' do @@ -165,5 +183,25 @@ describe Ci::BuildRunnerPresenter do end end end + + context 'when pipeline is detached merge request pipeline' do + let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) } + let(:pipeline) { merge_request.all_pipelines.first } + let(:build) { create(:ci_build, ref: pipeline.ref, pipeline: pipeline) } + + it 'returns the correct refspecs' do + is_expected + .to contain_exactly('+refs/merge-requests/1/head:refs/merge-requests/1/head') + end + + context 'when pipeline is legacy detached merge request pipeline' do + let(:merge_request) { create(:merge_request, :with_legacy_detached_merge_request_pipeline) } + + it 'returns the correct refspecs' do + is_expected.to contain_exactly('+refs/tags/*:refs/tags/*', + '+refs/heads/*:refs/remotes/origin/*') + end + end + end end end diff --git a/spec/presenters/clusters/cluster_presenter_spec.rb b/spec/presenters/clusters/cluster_presenter_spec.rb index 754ba0a594c..a9d786bc872 100644 --- a/spec/presenters/clusters/cluster_presenter_spec.rb +++ b/spec/presenters/clusters/cluster_presenter_spec.rb @@ -228,4 +228,20 @@ describe Clusters::ClusterPresenter do it { is_expected.to eq(group_cluster_path(group, cluster)) } end end + + describe '#read_only_kubernetes_platform_fields?' do + subject { described_class.new(cluster).read_only_kubernetes_platform_fields? } + + context 'with a user-provided cluster' do + let(:cluster) { build_stubbed(:cluster, :provided_by_user) } + + it { is_expected.to be_falsy } + end + + context 'with a GCP-provided cluster' do + let(:cluster) { build_stubbed(:cluster, :provided_by_gcp) } + + it { is_expected.to be_truthy } + end + end end diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb index b38cd66986f..8b503777443 100644 --- a/spec/requests/api/branches_spec.rb +++ b/spec/requests/api/branches_spec.rb @@ -20,9 +20,9 @@ describe API::Branches do let(:route) { "/projects/#{project_id}/repository/branches" } shared_examples_for 'repository branches' do - RSpec::Matchers.define :has_merged_branch_names_count do |expected| + RSpec::Matchers.define :has_up_to_merged_branch_names_count do |expected| match do |actual| - actual[:merged_branch_names].count == expected + expected >= actual[:merged_branch_names].count end end @@ -36,10 +36,30 @@ describe API::Branches do expect(branch_names).to match_array(project.repository.branch_names) end + def check_merge_status(json_response) + merged, unmerged = json_response.partition { |branch| branch['merged'] } + merged_branches = merged.map { |branch| branch['name'] } + unmerged_branches = unmerged.map { |branch| branch['name'] } + expect(Set.new(merged_branches)).to eq(project.repository.merged_branch_names(merged_branches + unmerged_branches)) + expect(project.repository.merged_branch_names(unmerged_branches)).to be_empty + end + it 'determines only a limited number of merged branch names' do - expect(API::Entities::Branch).to receive(:represent).with(anything, has_merged_branch_names_count(2)) + expect(API::Entities::Branch).to receive(:represent).with(anything, has_up_to_merged_branch_names_count(2)).and_call_original get api(route, current_user), params: { per_page: 2 } + + expect(response).to have_gitlab_http_status(200) + + check_merge_status(json_response) + end + + it 'merge status matches reality on paginated input' do + get api(route, current_user), params: { per_page: 20, page: 2 } + + expect(response).to have_gitlab_http_status(200) + + check_merge_status(json_response) end context 'when repository is disabled' do diff --git a/spec/requests/api/project_clusters_spec.rb b/spec/requests/api/project_clusters_spec.rb index 4e42e233b4c..81442125a1c 100644 --- a/spec/requests/api/project_clusters_spec.rb +++ b/spec/requests/api/project_clusters_spec.rb @@ -60,7 +60,7 @@ describe API::ProjectClusters do end let(:cluster) do - create(:cluster, :project, :provided_by_gcp, + create(:cluster, :project, :provided_by_gcp, :with_domain, platform_kubernetes: platform_kubernetes, user: current_user, projects: [project]) @@ -88,6 +88,7 @@ describe API::ProjectClusters do expect(json_response['platform_type']).to eq('kubernetes') expect(json_response['environment_scope']).to eq('*') expect(json_response['cluster_type']).to eq('project_type') + expect(json_response['domain']).to eq('example.com') end it 'returns project information' do @@ -187,6 +188,7 @@ describe API::ProjectClusters do let(:cluster_params) do { name: 'test-cluster', + domain: 'domain.example.com', platform_kubernetes_attributes: platform_kubernetes_attributes } end @@ -217,6 +219,7 @@ describe API::ProjectClusters do expect(cluster_result).to be_kubernetes expect(cluster_result.project).to eq(project) expect(cluster_result.name).to eq('test-cluster') + expect(cluster_result.domain).to eq('domain.example.com') expect(platform_kubernetes.rbac?).to be_truthy expect(platform_kubernetes.api_url).to eq(api_url) expect(platform_kubernetes.namespace).to eq(namespace) @@ -294,6 +297,7 @@ describe API::ProjectClusters do let(:update_params) do { + domain: 'new-domain.com', platform_kubernetes_attributes: platform_kubernetes_attributes } end @@ -330,6 +334,7 @@ describe API::ProjectClusters do end it 'should update cluster attributes' do + expect(cluster.domain).to eq('new-domain.com') expect(cluster.platform_kubernetes.namespace).to eq('new-namespace') end end @@ -342,6 +347,7 @@ describe API::ProjectClusters do end it 'should not update cluster attributes' do + expect(cluster.domain).not_to eq('new_domain.com') expect(cluster.platform_kubernetes.namespace).not_to eq('invalid_namespace') expect(cluster.kubernetes_namespace.namespace).not_to eq('invalid_namespace') end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 4c3c088b307..2bfb17d9c9a 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -13,12 +13,18 @@ shared_examples 'languages and percentages JSON response' do ) end - it 'returns expected language values' do - get api("/projects/#{project.id}/languages", user) + context "when the languages haven't been detected yet" do + it 'returns expected language values' do + get api("/projects/#{project.id}/languages", user) + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to eq({}) - expect(response).to have_gitlab_http_status(:ok) - expect(json_response).to eq(expected_languages) - expect(json_response.count).to be > 1 + get api("/projects/#{project.id}/languages", user) + + expect(response).to have_gitlab_http_status(:ok) + expect(JSON.parse(response.body)).to eq(expected_languages) + end end context 'when the languages were detected before' do diff --git a/spec/requests/api/releases_spec.rb b/spec/requests/api/releases_spec.rb index 1f317971a66..71ec091c42c 100644 --- a/spec/requests/api/releases_spec.rb +++ b/spec/requests/api/releases_spec.rb @@ -4,12 +4,14 @@ describe API::Releases do let(:project) { create(:project, :repository, :private) } let(:maintainer) { create(:user) } let(:reporter) { create(:user) } + let(:guest) { create(:user) } let(:non_project_member) { create(:user) } let(:commit) { create(:commit, project: project) } before do project.add_maintainer(maintainer) project.add_reporter(reporter) + project.add_guest(guest) project.repository.add_tag(maintainer, 'v0.1', commit.id) project.repository.add_tag(maintainer, 'v0.2', commit.id) @@ -66,6 +68,24 @@ describe API::Releases do end end + context 'when user is a guest' do + it 'responds 403 Forbidden' do + get api("/projects/#{project.id}/releases", guest) + + expect(response).to have_gitlab_http_status(:forbidden) + end + + context 'when project is public' do + let(:project) { create(:project, :repository, :public) } + + it 'responds 200 OK' do + get api("/projects/#{project.id}/releases", guest) + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + context 'when user is not a project member' do it 'cannot find the project' do get api("/projects/#{project.id}/releases", non_project_member) @@ -189,6 +209,24 @@ describe API::Releases do end end end + + context 'when user is a guest' do + it 'responds 403 Forbidden' do + get api("/projects/#{project.id}/releases/v0.1", guest) + + expect(response).to have_gitlab_http_status(:forbidden) + end + + context 'when project is public' do + let(:project) { create(:project, :repository, :public) } + + it 'responds 200 OK' do + get api("/projects/#{project.id}/releases/v0.1", guest) + + expect(response).to have_gitlab_http_status(:ok) + end + end + end end context 'when specified tag is not found in the project' do diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb index 3ccedd8dd06..5fdc7c64030 100644 --- a/spec/requests/api/runner_spec.rb +++ b/spec/requests/api/runner_spec.rb @@ -470,11 +470,11 @@ describe API::Runner, :clean_gitlab_redis_shared_state do expect(json_response['token']).to eq(job.token) expect(json_response['job_info']).to eq(expected_job_info) expect(json_response['git_info']).to eq(expected_git_info) - expect(json_response['image']).to eq({ 'name' => 'ruby:2.1', 'entrypoint' => '/bin/sh' }) + expect(json_response['image']).to eq({ 'name' => 'ruby:2.1', 'entrypoint' => '/bin/sh', 'ports' => [] }) expect(json_response['services']).to eq([{ 'name' => 'postgres', 'entrypoint' => nil, - 'alias' => nil, 'command' => nil }, + 'alias' => nil, 'command' => nil, 'ports' => [] }, { 'name' => 'docker:stable-dind', 'entrypoint' => '/bin/sh', - 'alias' => 'docker', 'command' => 'sleep 30' }]) + 'alias' => 'docker', 'command' => 'sleep 30', 'ports' => [] }]) expect(json_response['steps']).to eq(expected_steps) expect(json_response['artifacts']).to eq(expected_artifacts) expect(json_response['cache']).to eq(expected_cache) @@ -853,6 +853,56 @@ describe API::Runner, :clean_gitlab_redis_shared_state do end end + describe 'port support' do + let(:job) { create(:ci_build, pipeline: pipeline, options: options) } + + context 'when job image has ports' do + let(:options) do + { + image: { + name: 'ruby', + ports: [80] + }, + services: ['mysql'] + } + end + + it 'returns the image ports' do + request_job + + expect(response).to have_http_status(:created) + expect(json_response).to include( + 'id' => job.id, + 'image' => a_hash_including('name' => 'ruby', 'ports' => [{ 'number' => 80, 'protocol' => 'http', 'name' => 'default_port' }]), + 'services' => all(a_hash_including('name' => 'mysql'))) + end + end + + context 'when job services settings has ports' do + let(:options) do + { + image: 'ruby', + services: [ + { + name: 'tomcat', + ports: [{ number: 8081, protocol: 'http', name: 'custom_port' }] + } + ] + } + end + + it 'returns the service ports' do + request_job + + expect(response).to have_http_status(:created) + expect(json_response).to include( + 'id' => job.id, + 'image' => a_hash_including('name' => 'ruby'), + 'services' => all(a_hash_including('name' => 'tomcat', 'ports' => [{ 'number' => 8081, 'protocol' => 'http', 'name' => 'custom_port' }]))) + end + end + end + def request_job(token = runner.token, **params) new_params = params.merge(token: token, last_update: last_update) post api('/jobs/request'), params: new_params, headers: { 'User-Agent' => user_agent } diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb index 727fd8951f2..0e99ef38d2f 100644 --- a/spec/serializers/merge_request_widget_entity_spec.rb +++ b/spec/serializers/merge_request_widget_entity_spec.rb @@ -13,6 +13,10 @@ describe MergeRequestWidgetEntity do described_class.new(resource, request: request).as_json end + it 'has the latest sha of the target branch' do + is_expected.to include(:target_branch_sha) + end + describe 'source_project_full_path' do it 'includes the full path of the source project' do expect(subject[:source_project_full_path]).to be_present diff --git a/spec/serializers/pipeline_entity_spec.rb b/spec/serializers/pipeline_entity_spec.rb index 1d992e8a483..dba7fd91747 100644 --- a/spec/serializers/pipeline_entity_spec.rb +++ b/spec/serializers/pipeline_entity_spec.rb @@ -143,6 +143,11 @@ describe PipelineEntity do expect(subject[:flags][:detached_merge_request_pipeline]).to be_truthy end + it 'does not expose source sha and target sha' do + expect(subject[:source_sha]).to be_nil + expect(subject[:target_sha]).to be_nil + end + context 'when user is a developer' do before do project.add_developer(user) @@ -189,6 +194,11 @@ describe PipelineEntity do it 'makes atached flag true' do expect(subject[:flags][:merge_request_pipeline]).to be_truthy end + + it 'exposes source sha and target sha' do + expect(subject[:source_sha]).to be_present + expect(subject[:target_sha]).to be_present + end end end end diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb index 24707cd2d41..866d709d446 100644 --- a/spec/services/ci/create_pipeline_service_spec.rb +++ b/spec/services/ci/create_pipeline_service_spec.rb @@ -306,6 +306,56 @@ describe Ci::CreatePipelineService do it_behaves_like 'a failed pipeline' end + + context 'when config has ports' do + context 'in the main image' do + let(:ci_yaml) do + <<-EOS + image: + name: ruby:2.2 + ports: + - 80 + EOS + end + + it_behaves_like 'a failed pipeline' + end + + context 'in the job image' do + let(:ci_yaml) do + <<-EOS + image: ruby:2.2 + + test: + script: rspec + image: + name: ruby:2.2 + ports: + - 80 + EOS + end + + it_behaves_like 'a failed pipeline' + end + + context 'in the service' do + let(:ci_yaml) do + <<-EOS + image: ruby:2.2 + + test: + script: rspec + image: ruby:2.2 + services: + - name: test + ports: + - 80 + EOS + end + + it_behaves_like 'a failed pipeline' + end + end end context 'when commit contains a [ci skip] directive' do diff --git a/spec/services/error_tracking/list_issues_service_spec.rb b/spec/services/error_tracking/list_issues_service_spec.rb index 9d4fc62f923..3a8f3069911 100644 --- a/spec/services/error_tracking/list_issues_service_spec.rb +++ b/spec/services/error_tracking/list_issues_service_spec.rb @@ -53,7 +53,10 @@ describe ErrorTracking::ListIssuesService do before do allow(error_tracking_setting) .to receive(:list_sentry_issues) - .and_return(error: 'Sentry response status code: 401') + .and_return( + error: 'Sentry response status code: 401', + error_type: ErrorTracking::ProjectErrorTrackingSetting::SENTRY_API_ERROR_TYPE_NON_20X_RESPONSE + ) end it 'returns the error' do @@ -64,6 +67,25 @@ describe ErrorTracking::ListIssuesService do ) end end + + context 'when list_sentry_issues returns error with http_status' do + before do + allow(error_tracking_setting) + .to receive(:list_sentry_issues) + .and_return( + error: 'Sentry API response is missing keys. key not found: "id"', + error_type: ErrorTracking::ProjectErrorTrackingSetting::SENTRY_API_ERROR_TYPE_MISSING_KEYS + ) + end + + it 'returns the error with correct http_status' do + expect(result).to eq( + status: :error, + http_status: :internal_server_error, + message: 'Sentry API response is missing keys. key not found: "id"' + ) + end + end end context 'with unauthorized user' do diff --git a/spec/services/git/tag_push_service_spec.rb b/spec/services/git/tag_push_service_spec.rb index e151db5827f..2d960fc9f08 100644 --- a/spec/services/git/tag_push_service_spec.rb +++ b/spec/services/git/tag_push_service_spec.rb @@ -31,6 +31,20 @@ describe Git::TagPushService do end end + describe 'System Hooks' do + let!(:push_data) { service.tap(&:execute).push_data } + + it "executes system hooks after pushing a tag" do + expect_next_instance_of(SystemHooksService) do |system_hooks_service| + expect(system_hooks_service) + .to receive(:execute_hooks) + .with(push_data, :tag_push_hooks) + end + + service.execute + end + end + describe "Pipelines" do subject { service.execute } diff --git a/spec/services/groups/destroy_service_spec.rb b/spec/services/groups/destroy_service_spec.rb index d80d0f5a8a8..98114ea4919 100644 --- a/spec/services/groups/destroy_service_spec.rb +++ b/spec/services/groups/destroy_service_spec.rb @@ -82,44 +82,6 @@ describe Groups::DestroyService do expect(Group.unscoped.count).to eq(2) end end - - context 'potential race conditions' do - context "when the `GroupDestroyWorker` task runs immediately" do - it "deletes the group" do - # Commit the contents of this spec's transaction so far - # so subsequent db connections can see it. - # - # DO NOT REMOVE THIS LINE, even if you see a WARNING with "No - # transaction is currently in progress". Without this, this - # spec will always be green, since the group created in setup - # cannot be seen by any other connections / threads in this spec. - Group.connection.commit_db_transaction - - group_record = run_with_new_database_connection do |conn| - conn.execute("SELECT * FROM namespaces WHERE id = #{group.id}").first - end - - expect(group_record).not_to be_nil - - # Execute the contents of `GroupDestroyWorker` in a separate thread, to - # simulate data manipulation by the Sidekiq worker (different database - # connection / transaction). - expect(GroupDestroyWorker).to receive(:perform_async).and_wrap_original do |m, group_id, user_id| - Thread.new { m[group_id, user_id] }.join(5) - end - - # Kick off the initial group destroy in a new thread, so that - # it doesn't share this spec's database transaction. - Thread.new { described_class.new(group, user).async_execute }.join(5) - - group_record = run_with_new_database_connection do |conn| - conn.execute("SELECT * FROM namespaces WHERE id = #{group.id}").first - end - - expect(group_record).to be_nil - end - end - end end describe 'synchronous delete' do diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb index 715b1168bfb..d50412b6d2c 100644 --- a/spec/services/issues/create_service_spec.rb +++ b/spec/services/issues/create_service_spec.rb @@ -138,6 +138,20 @@ describe Issues::CreateService do end end + context 'when duplicate label titles are given' do + let(:label) { create(:label, project: project) } + + let(:opts) do + { title: 'Title', + description: 'Description', + labels: [label.title, label.title] } + end + + it 'assigns the label once' do + expect(issue.labels).to contain_exactly(label) + end + end + it 'executes issue hooks when issue is not confidential' do opts = { title: 'Title', description: 'Description', confidential: false } diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index f1684209729..1c8a4b608d5 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -592,6 +592,16 @@ describe Issues::UpdateService, :mailer do expect(result.label_ids).not_to include(label.id) end end + + context 'when duplicate label titles are given' do + let(:params) do + { labels: [label3.title, label3.title] } + end + + it 'assigns the label once' do + expect(result.labels).to contain_exactly(label3) + end + end end context 'updating asssignee_id' do diff --git a/spec/services/labels/available_labels_service_spec.rb b/spec/services/labels/available_labels_service_spec.rb new file mode 100644 index 00000000000..4d5c87ecc53 --- /dev/null +++ b/spec/services/labels/available_labels_service_spec.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true +require 'spec_helper' + +describe Labels::AvailableLabelsService do + let(:user) { create(:user) } + let(:project) { create(:project, :public, group: group) } + let(:group) { create(:group) } + + let(:project_label) { create(:label, project: project) } + let(:other_project_label) { create(:label) } + let(:group_label) { create(:group_label, group: group) } + let(:other_group_label) { create(:group_label) } + let(:labels) { [project_label, other_project_label, group_label, other_group_label] } + + context '#find_or_create_by_titles' do + let(:label_titles) { labels.map(&:title).push('non existing title') } + + context 'when parent is a project' do + context 'when a user is not a project member' do + it 'returns only relevant label ids' do + result = described_class.new(user, project, labels: label_titles).find_or_create_by_titles + + expect(result).to match_array([project_label, group_label]) + end + end + + context 'when a user is a project member' do + before do + project.add_developer(user) + end + + it 'creates new labels for not found titles' do + result = described_class.new(user, project, labels: label_titles).find_or_create_by_titles + + expect(result.count).to eq(5) + expect(result).to include(project_label, group_label) + expect(result).not_to include(other_project_label, other_group_label) + end + end + end + + context 'when parent is a group' do + context 'when a user is not a group member' do + it 'returns only relevant label ids' do + result = described_class.new(user, group, labels: label_titles).find_or_create_by_titles + + expect(result).to match_array([group_label]) + end + end + + context 'when a user is a group member' do + before do + group.add_developer(user) + end + + it 'creates new labels for not found titles' do + result = described_class.new(user, group, labels: label_titles).find_or_create_by_titles + + expect(result.count).to eq(5) + expect(result).to include(group_label) + expect(result).not_to include(project_label, other_project_label, other_group_label) + end + end + end + end + + context '#filter_labels_ids_in_param' do + let(:label_ids) { labels.map(&:id).push(99999) } + + context 'when parent is a project' do + it 'returns only relevant label ids' do + result = described_class.new(user, project, ids: label_ids).filter_labels_ids_in_param(:ids) + + expect(result).to match_array([project_label.id, group_label.id]) + end + end + + context 'when parent is a group' do + it 'returns only relevant label ids' do + result = described_class.new(user, group, ids: label_ids).filter_labels_ids_in_param(:ids) + + expect(result).to match_array([group_label.id]) + end + end + end +end diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb index a04a4d5fc36..55e7b46248b 100644 --- a/spec/services/merge_requests/create_service_spec.rb +++ b/spec/services/merge_requests/create_service_spec.rb @@ -173,7 +173,7 @@ describe MergeRequests::CreateService do end end - describe 'Merge request pipelines' do + describe 'Pipelines for merge requests' do before do stub_ci_pipeline_yaml_file(YAML.dump(config)) end @@ -189,12 +189,46 @@ describe MergeRequests::CreateService do } end - it 'creates a merge request pipeline and sets it as a head pipeline' do + it 'creates a detached merge request pipeline and sets it as a head pipeline' do expect(merge_request).to be_persisted merge_request.reload expect(merge_request.merge_request_pipelines.count).to eq(1) - expect(merge_request.actual_head_pipeline).to be_merge_request_event + expect(merge_request.actual_head_pipeline).to be_detached_merge_request_pipeline + end + + context 'when merge request is submitted from forked project' do + let(:target_project) { fork_project(project, nil, repository: true) } + + let(:opts) do + { + title: 'Awesome merge_request', + source_branch: 'feature', + target_branch: 'master', + target_project_id: target_project.id + } + end + + before do + target_project.add_developer(assignee) + target_project.add_maintainer(user) + end + + it 'create legacy detached merge request pipeline for fork merge request' do + expect(merge_request.actual_head_pipeline) + .to be_legacy_detached_merge_request_pipeline + end + end + + context 'when ci_use_merge_request_ref feature flag is false' do + before do + stub_feature_flags(ci_use_merge_request_ref: false) + end + + it 'create legacy detached merge request pipeline for non-fork merge request' do + expect(merge_request.actual_head_pipeline) + .to be_legacy_detached_merge_request_pipeline + end end context 'when there are no commits between source branch and target branch' do @@ -207,7 +241,7 @@ describe MergeRequests::CreateService do } end - it 'does not create a merge request pipeline' do + it 'does not create a detached merge request pipeline' do expect(merge_request).to be_persisted merge_request.reload @@ -225,7 +259,7 @@ describe MergeRequests::CreateService do merge_request end - it 'sets the latest merge request pipeline as the head pipeline' do + it 'sets the latest detached merge request pipeline as the head pipeline' do expect(merge_request.actual_head_pipeline).to be_merge_request_event end end @@ -235,7 +269,7 @@ describe MergeRequests::CreateService do stub_feature_flags(ci_merge_request_pipeline: false) end - it 'does not create a merge request pipeline' do + it 'does not create a detached merge request pipeline' do expect(merge_request).to be_persisted merge_request.reload @@ -254,7 +288,7 @@ describe MergeRequests::CreateService do } end - it 'does not create a merge request pipeline' do + it 'does not create a detached merge request pipeline' do expect(merge_request).to be_persisted merge_request.reload diff --git a/spec/services/merge_requests/merge_to_ref_service_spec.rb b/spec/services/merge_requests/merge_to_ref_service_spec.rb index fabca8f6b4a..a3b48abae26 100644 --- a/spec/services/merge_requests/merge_to_ref_service_spec.rb +++ b/spec/services/merge_requests/merge_to_ref_service_spec.rb @@ -40,15 +40,6 @@ describe MergeRequests::MergeToRefService do end shared_examples_for 'successfully evaluates pre-condition checks' do - it 'returns error when feature is disabled' do - stub_feature_flags(merge_to_tmp_merge_ref_path: false) - - result = service.execute(merge_request) - - expect(result[:status]).to eq(:error) - expect(result[:message]).to eq('Feature is not enabled') - end - it 'returns an error when the failing to process the merge' do allow(project.repository).to receive(:merge_to_ref).and_return(nil) @@ -180,6 +171,17 @@ describe MergeRequests::MergeToRefService do it { expect(todo).not_to be_done } end + context 'when merge request is WIP state' do + it 'fails to merge' do + merge_request = create(:merge_request, title: 'WIP: The feature') + + result = service.execute(merge_request) + + expect(result[:status]).to eq(:error) + expect(result[:message]).to eq("Merge request is not mergeable to #{merge_request.merge_ref_path}") + end + end + it 'returns error when user has no authorization to admin the merge request' do unauthorized_user = create(:user) project.add_reporter(unauthorized_user) diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index 6c8ff163692..25cbac6d7ee 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -141,7 +141,7 @@ describe MergeRequests::RefreshService do end end - describe 'Merge request pipelines' do + describe 'Pipelines for merge requests' do before do stub_ci_pipeline_yaml_file(YAML.dump(config)) end @@ -159,7 +159,7 @@ describe MergeRequests::RefreshService do } end - it 'create merge request pipeline with commits' do + it 'create detached merge request pipeline with commits' do expect { subject } .to change { @merge_request.merge_request_pipelines.count }.by(1) .and change { @fork_merge_request.merge_request_pipelines.count }.by(1) @@ -170,7 +170,34 @@ describe MergeRequests::RefreshService do expect(@another_merge_request.has_commits?).to be_falsy end - context "when branch pipeline was created before a merge request pipline has been created" do + it 'create detached merge request pipeline for non-fork merge request' do + subject + + expect(@merge_request.merge_request_pipelines.first) + .to be_detached_merge_request_pipeline + end + + it 'create legacy detached merge request pipeline for fork merge request' do + subject + + expect(@fork_merge_request.merge_request_pipelines.first) + .to be_legacy_detached_merge_request_pipeline + end + + context 'when ci_use_merge_request_ref feature flag is false' do + before do + stub_feature_flags(ci_use_merge_request_ref: false) + end + + it 'create legacy detached merge request pipeline for non-fork merge request' do + subject + + expect(@merge_request.merge_request_pipelines.first) + .to be_legacy_detached_merge_request_pipeline + end + end + + context "when branch pipeline was created before a detaced merge request pipeline has been created" do before do create(:ci_pipeline, project: @merge_request.source_project, sha: @merge_request.diff_head_sha, @@ -180,7 +207,7 @@ describe MergeRequests::RefreshService do subject end - it 'sets the latest merge request pipeline as a head pipeline' do + it 'sets the latest detached merge request pipeline as a head pipeline' do @merge_request.reload expect(@merge_request.actual_head_pipeline).to be_merge_request_event end @@ -193,7 +220,7 @@ describe MergeRequests::RefreshService do end context "when MergeRequestUpdateWorker is retried by an exception" do - it 'does not re-create a duplicate merge request pipeline' do + it 'does not re-create a duplicate detached merge request pipeline' do expect do service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/master') end.to change { @merge_request.merge_request_pipelines.count }.by(1) @@ -209,7 +236,7 @@ describe MergeRequests::RefreshService do stub_feature_flags(ci_merge_request_pipeline: false) end - it 'does not create a merge request pipeline' do + it 'does not create a detached merge request pipeline' do expect { subject } .not_to change { @merge_request.merge_request_pipelines.count } end @@ -226,7 +253,7 @@ describe MergeRequests::RefreshService do } end - it 'does not create a merge request pipeline' do + it 'does not create a detached merge request pipeline' do expect { subject } .not_to change { @merge_request.merge_request_pipelines.count } end diff --git a/spec/services/notes/build_service_spec.rb b/spec/services/notes/build_service_spec.rb index af4daff336b..96fff20f7fb 100644 --- a/spec/services/notes/build_service_spec.rb +++ b/spec/services/notes/build_service_spec.rb @@ -128,37 +128,19 @@ describe Notes::BuildService do subject { described_class.new(project, author, note: 'Test', in_reply_to_discussion_id: note.discussion_id).execute } - shared_examples 'an individual note reply' do - it 'builds another individual note' do - expect(subject).to be_valid - expect(subject).to be_a(Note) - expect(subject.discussion_id).not_to eq(note.discussion_id) - end + it 'sets the note up to be in reply to that note' do + expect(subject).to be_valid + expect(subject).to be_a(DiscussionNote) + expect(subject.discussion_id).to eq(note.discussion_id) end - context 'when reply_to_individual_notes is disabled' do - before do - stub_feature_flags(reply_to_individual_notes: false) - end - - it_behaves_like 'an individual note reply' - end + context 'when noteable does not support replies' do + let(:note) { create(:note_on_commit) } - context 'when reply_to_individual_notes is enabled' do - before do - stub_feature_flags(reply_to_individual_notes: true) - end - - it 'sets the note up to be in reply to that note' do + it 'builds another individual note' do expect(subject).to be_valid - expect(subject).to be_a(DiscussionNote) - expect(subject.discussion_id).to eq(note.discussion_id) - end - - context 'when noteable does not support replies' do - let(:note) { create(:note_on_commit) } - - it_behaves_like 'an individual note reply' + expect(subject).to be_a(Note) + expect(subject.discussion_id).not_to eq(note.discussion_id) end end end diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb index 8d8e81173ff..bcbb8950910 100644 --- a/spec/services/notes/create_service_spec.rb +++ b/spec/services/notes/create_service_spec.rb @@ -298,41 +298,20 @@ describe Notes::CreateService do subject { described_class.new(project, user, reply_opts).execute } - context 'when reply_to_individual_notes is disabled' do - before do - stub_feature_flags(reply_to_individual_notes: false) - end - - it 'creates an individual note' do - expect(subject.type).to eq(nil) - expect(subject.discussion_id).not_to eq(existing_note.discussion_id) - end - - it 'does not convert existing note' do - expect { subject }.not_to change { existing_note.reload.type } - end + it 'creates a DiscussionNote in reply to existing note' do + expect(subject).to be_a(DiscussionNote) + expect(subject.discussion_id).to eq(existing_note.discussion_id) end - context 'when reply_to_individual_notes is enabled' do - before do - stub_feature_flags(reply_to_individual_notes: true) - end - - it 'creates a DiscussionNote in reply to existing note' do - expect(subject).to be_a(DiscussionNote) - expect(subject.discussion_id).to eq(existing_note.discussion_id) - end - - it 'converts existing note to DiscussionNote' do - expect do - existing_note + it 'converts existing note to DiscussionNote' do + expect do + existing_note - Timecop.freeze(Time.now + 1.minute) { subject } + Timecop.freeze(Time.now + 1.minute) { subject } - existing_note.reload - end.to change { existing_note.type }.from(nil).to('DiscussionNote') - .and change { existing_note.updated_at } - end + existing_note.reload + end.to change { existing_note.type }.from(nil).to('DiscussionNote') + .and change { existing_note.updated_at } end end end diff --git a/spec/services/projects/after_import_service_spec.rb b/spec/services/projects/after_import_service_spec.rb index 4dd6c6dab86..765b4ffae8f 100644 --- a/spec/services/projects/after_import_service_spec.rb +++ b/spec/services/projects/after_import_service_spec.rb @@ -13,7 +13,7 @@ describe Projects::AfterImportService do describe '#execute' do before do allow(Projects::HousekeepingService) - .to receive(:new).with(project).and_return(housekeeping_service) + .to receive(:new).with(project, :gc).and_return(housekeeping_service) allow(housekeeping_service) .to receive(:execute).and_yield diff --git a/spec/services/projects/detect_repository_languages_service_spec.rb b/spec/services/projects/detect_repository_languages_service_spec.rb index deea1189cdf..b38bd62c9f0 100644 --- a/spec/services/projects/detect_repository_languages_service_spec.rb +++ b/spec/services/projects/detect_repository_languages_service_spec.rb @@ -19,6 +19,10 @@ describe Projects::DetectRepositoryLanguagesService, :clean_gitlab_redis_shared_ expect(names).to eq(%w[Ruby JavaScript HTML CoffeeScript]) end + + it 'updates detected_repository_languages flag' do + expect { subject.execute }.to change(project, :detected_repository_languages).to(true) + end end context 'with a previous detection' do @@ -36,6 +40,12 @@ describe Projects::DetectRepositoryLanguagesService, :clean_gitlab_redis_shared_ expect(repository_languages).to eq(%w[Ruby D]) end + + it "doesn't touch detected_repository_languages flag" do + expect(project).not_to receive(:update_column).with(:detected_repository_languages, true) + + subject.execute + end end context 'when no repository exists' do diff --git a/spec/services/projects/housekeeping_service_spec.rb b/spec/services/projects/housekeeping_service_spec.rb index 18ecef1c0a1..12ae9105627 100644 --- a/spec/services/projects/housekeeping_service_spec.rb +++ b/spec/services/projects/housekeeping_service_spec.rb @@ -88,6 +88,19 @@ describe Projects::HousekeepingService do expect(project.pushes_since_gc).to eq(1) end end + + it 'runs the task specifically requested' do + housekeeping = described_class.new(project, :gc) + + allow(housekeeping).to receive(:try_obtain_lease).and_return(:gc_uuid) + allow(housekeeping).to receive(:lease_key).and_return(:gc_lease_key) + + expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :gc, :gc_lease_key, :gc_uuid).twice + + 2.times do + housekeeping.execute + end + end end describe '#needed?' do diff --git a/spec/services/projects/repository_languages_service_spec.rb b/spec/services/projects/repository_languages_service_spec.rb new file mode 100644 index 00000000000..61c1b8c5ec1 --- /dev/null +++ b/spec/services/projects/repository_languages_service_spec.rb @@ -0,0 +1,48 @@ +require 'spec_helper' + +describe Projects::RepositoryLanguagesService do + let(:service) { described_class.new(project, project.owner) } + + context 'when detected_repository_languages flag is set' do + let(:project) { create(:project) } + + context 'when a project is without detected programming languages' do + it 'schedules a worker and returns the empty result' do + expect(::DetectRepositoryLanguagesWorker).to receive(:perform_async).with(project.id, project.owner.id) + expect(service.execute).to eq([]) + end + end + + context 'when a project is with detected programming languages' do + let!(:repository_language) { create(:repository_language, project: project) } + + it 'does not schedule a worker and returns the detected languages' do + expect(::DetectRepositoryLanguagesWorker).not_to receive(:perform_async).with(project.id, project.owner.id) + + languages = service.execute + + expect(languages.size).to eq(1) + expect(languages.last.attributes.values).to eq( + [project.id, repository_language.programming_language_id, repository_language.share] + ) + end + + it 'sets detected_repository_languages flag' do + expect { service.execute }.to change(project, :detected_repository_languages).from(nil).to(true) + end + end + end + + context 'when detected_repository_languages flag is not set' do + let!(:repository_language) { create(:repository_language, project: project) } + let(:project) { create(:project, detected_repository_languages: true) } + let(:languages) { service.execute } + + it 'returns repository languages' do + expect(languages.size).to eq(1) + expect(languages.last.attributes.values).to eq( + [project.id, repository_language.programming_language_id, repository_language.share] + ) + end + end +end diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb index ea33d156c8a..c7e5cca324f 100644 --- a/spec/services/quick_actions/interpret_service_spec.rb +++ b/spec/services/quick_actions/interpret_service_spec.rb @@ -10,11 +10,13 @@ describe QuickActions::InterpretService do let(:milestone) { create(:milestone, project: project, title: '9.10') } let(:commit) { create(:commit, project: project) } let(:inprogress) { create(:label, project: project, title: 'In Progress') } + let(:helmchart) { create(:label, project: project, title: 'Helm Chart Registry') } let(:bug) { create(:label, project: project, title: 'Bug') } let(:note) { build(:note, commit_id: merge_request.diff_head_sha) } let(:service) { described_class.new(project, developer) } before do + stub_licensed_features(multiple_issue_assignees: false) project.add_developer(developer) end @@ -93,6 +95,26 @@ describe QuickActions::InterpretService do end end + shared_examples 'multiword label name starting without ~' do + it 'fetches label ids and populates add_label_ids if content contains /label' do + helmchart # populate the label + _, updates = service.execute(content, issuable) + + expect(updates).to eq(add_label_ids: [helmchart.id]) + end + end + + shared_examples 'label name is included in the middle of another label name' do + it 'ignores the sublabel when the content contains the includer label name' do + helmchart # populate the label + create(:label, project: project, title: 'Chart') + + _, updates = service.execute(content, issuable) + + expect(updates).to eq(add_label_ids: [helmchart.id]) + end + end + shared_examples 'unlabel command' do it 'fetches label ids and populates remove_label_ids if content contains /unlabel' do issuable.update!(label_ids: [inprogress.id]) # populate the label @@ -623,6 +645,26 @@ describe QuickActions::InterpretService do let(:issuable) { issue } end + it_behaves_like 'multiword label name starting without ~' do + let(:content) { %(/label "#{helmchart.title}") } + let(:issuable) { issue } + end + + it_behaves_like 'multiword label name starting without ~' do + let(:content) { %(/label "#{helmchart.title}") } + let(:issuable) { merge_request } + end + + it_behaves_like 'label name is included in the middle of another label name' do + let(:content) { %(/label ~"#{helmchart.title}") } + let(:issuable) { issue } + end + + it_behaves_like 'label name is included in the middle of another label name' do + let(:content) { %(/label ~"#{helmchart.title}") } + let(:issuable) { merge_request } + end + it_behaves_like 'unlabel command' do let(:content) { %(/unlabel ~"#{inprogress.title}") } let(:issuable) { issue } diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b3bd453ebd6..60db3e1bc46 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -66,6 +66,7 @@ RSpec.configure do |config| metadata[:type] = match[1].singularize.to_sym if match end + config.include LicenseHelpers config.include ActiveJob::TestHelper config.include ActiveSupport::Testing::TimeHelpers config.include CycleAnalyticsHelpers diff --git a/spec/support/features/issuable_quick_actions_shared_examples.rb b/spec/support/features/issuable_quick_actions_shared_examples.rb deleted file mode 100644 index 2a883ce1074..00000000000 --- a/spec/support/features/issuable_quick_actions_shared_examples.rb +++ /dev/null @@ -1,389 +0,0 @@ -# Specifications for behavior common to all objects with executable attributes. -# It takes a `issuable_type`, and expect an `issuable`. - -shared_examples 'issuable record that supports quick actions in its description and notes' do |issuable_type| - include Spec::Support::Helpers::Features::NotesHelpers - - let(:maintainer) { create(:user) } - let(:project) do - case issuable_type - when :merge_request - create(:project, :public, :repository) - when :issue - create(:project, :public) - end - end - let!(:milestone) { create(:milestone, project: project, title: 'ASAP') } - let!(:label_bug) { create(:label, project: project, title: 'bug') } - let!(:label_feature) { create(:label, project: project, title: 'feature') } - let(:new_url_opts) { {} } - - before do - project.add_maintainer(maintainer) - - gitlab_sign_in(maintainer) - end - - after do - # Ensure all outstanding Ajax requests are complete to avoid database deadlocks - wait_for_requests - end - - describe "new #{issuable_type}", :js do - context 'with commands in the description' do - it "creates the #{issuable_type} and interpret commands accordingly" do - case issuable_type - when :merge_request - visit public_send("namespace_project_new_merge_request_path", project.namespace, project, new_url_opts) - when :issue - visit public_send("new_namespace_project_issue_path", project.namespace, project, new_url_opts) - end - fill_in "#{issuable_type}_title", with: 'bug 345' - fill_in "#{issuable_type}_description", with: "bug description\n/label ~bug\n/milestone %\"ASAP\"" - click_button "Submit #{issuable_type}".humanize - - issuable = project.public_send(issuable_type.to_s.pluralize).first - - expect(issuable.description).to eq "bug description" - expect(issuable.labels).to eq [label_bug] - expect(issuable.milestone).to eq milestone - expect(page).to have_content 'bug 345' - expect(page).to have_content 'bug description' - end - end - end - - describe "note on #{issuable_type}", :js do - before do - visit public_send("project_#{issuable_type}_path", project, issuable) - end - - context 'with a note containing commands' do - it 'creates a note without the commands and interpret the commands accordingly' do - assignee = create(:user, username: 'bob') - add_note("Awesome!\n\n/assign @bob\n\n/label ~bug\n\n/milestone %\"ASAP\"") - - expect(page).to have_content 'Awesome!' - expect(page).not_to have_content '/assign @bob' - expect(page).not_to have_content '/label ~bug' - expect(page).not_to have_content '/milestone %"ASAP"' - - wait_for_requests - issuable.reload - note = issuable.notes.user.first - - expect(note.note).to eq "Awesome!" - expect(issuable.assignees).to eq [assignee] - expect(issuable.labels).to eq [label_bug] - expect(issuable.milestone).to eq milestone - end - - it 'removes the quick action from note and explains it in the preview' do - preview_note("Awesome!\n\n/close") - - expect(page).to have_content 'Awesome!' - expect(page).not_to have_content '/close' - issuable_name = issuable.is_a?(Issue) ? 'issue' : 'merge request' - expect(page).to have_content "Closes this #{issuable_name}." - end - end - - context 'with a note containing only commands' do - it 'does not create a note but interpret the commands accordingly' do - assignee = create(:user, username: 'bob') - add_note("/assign @bob\n\n/label ~bug\n\n/milestone %\"ASAP\"") - - expect(page).not_to have_content '/assign @bob' - expect(page).not_to have_content '/label ~bug' - expect(page).not_to have_content '/milestone %"ASAP"' - expect(page).to have_content 'Commands applied' - - issuable.reload - - expect(issuable.notes.user).to be_empty - expect(issuable.assignees).to eq [assignee] - expect(issuable.labels).to eq [label_bug] - expect(issuable.milestone).to eq milestone - end - end - - context "with a note closing the #{issuable_type}" do - before do - expect(issuable).to be_open - end - - context "when current user can close #{issuable_type}" do - it "closes the #{issuable_type}" do - add_note("/close") - - expect(page).not_to have_content '/close' - expect(page).to have_content 'Commands applied' - - expect(issuable.reload).to be_closed - end - end - - context "when current user cannot close #{issuable_type}" do - before do - guest = create(:user) - project.add_guest(guest) - - gitlab_sign_out - gitlab_sign_in(guest) - visit public_send("project_#{issuable_type}_path", project, issuable) - end - - it "does not close the #{issuable_type}" do - add_note("/close") - - expect(page).not_to have_content 'Commands applied' - - expect(issuable).to be_open - end - end - end - - context "with a note reopening the #{issuable_type}" do - before do - issuable.close - expect(issuable).to be_closed - end - - context "when current user can reopen #{issuable_type}" do - it "reopens the #{issuable_type}" do - add_note("/reopen") - - expect(page).not_to have_content '/reopen' - expect(page).to have_content 'Commands applied' - - expect(issuable.reload).to be_open - end - end - - context "when current user cannot reopen #{issuable_type}" do - before do - guest = create(:user) - project.add_guest(guest) - - gitlab_sign_out - gitlab_sign_in(guest) - visit public_send("project_#{issuable_type}_path", project, issuable) - end - - it "does not reopen the #{issuable_type}" do - add_note("/reopen") - - expect(page).not_to have_content 'Commands applied' - - expect(issuable).to be_closed - end - end - end - - context "with a note changing the #{issuable_type}'s title" do - context "when current user can change title of #{issuable_type}" do - it "reopens the #{issuable_type}" do - add_note("/title Awesome new title") - - expect(page).not_to have_content '/title' - expect(page).to have_content 'Commands applied' - - expect(issuable.reload.title).to eq 'Awesome new title' - end - end - - context "when current user cannot change title of #{issuable_type}" do - before do - guest = create(:user) - project.add_guest(guest) - - gitlab_sign_out - gitlab_sign_in(guest) - visit public_send("project_#{issuable_type}_path", project, issuable) - end - - it "does not change the #{issuable_type} title" do - add_note("/title Awesome new title") - - expect(page).not_to have_content 'Commands applied' - - expect(issuable.reload.title).not_to eq 'Awesome new title' - end - end - end - - context "with a note marking the #{issuable_type} as todo" do - it "creates a new todo for the #{issuable_type}" do - add_note("/todo") - - expect(page).not_to have_content '/todo' - expect(page).to have_content 'Commands applied' - - todos = TodosFinder.new(maintainer).execute - todo = todos.first - - expect(todos.size).to eq 1 - expect(todo).to be_pending - expect(todo.target).to eq issuable - expect(todo.author).to eq maintainer - expect(todo.user).to eq maintainer - end - end - - context "with a note marking the #{issuable_type} as done" do - before do - TodoService.new.mark_todo(issuable, maintainer) - end - - it "creates a new todo for the #{issuable_type}" do - todos = TodosFinder.new(maintainer).execute - todo = todos.first - - expect(todos.size).to eq 1 - expect(todos.first).to be_pending - expect(todo.target).to eq issuable - expect(todo.author).to eq maintainer - expect(todo.user).to eq maintainer - - add_note("/done") - - expect(page).not_to have_content '/done' - expect(page).to have_content 'Commands applied' - - expect(todo.reload).to be_done - end - end - - context "with a note subscribing to the #{issuable_type}" do - it "creates a new todo for the #{issuable_type}" do - expect(issuable.subscribed?(maintainer, project)).to be_falsy - - add_note("/subscribe") - - expect(page).not_to have_content '/subscribe' - expect(page).to have_content 'Commands applied' - - expect(issuable.subscribed?(maintainer, project)).to be_truthy - end - end - - context "with a note unsubscribing to the #{issuable_type} as done" do - before do - issuable.subscribe(maintainer, project) - end - - it "creates a new todo for the #{issuable_type}" do - expect(issuable.subscribed?(maintainer, project)).to be_truthy - - add_note("/unsubscribe") - - expect(page).not_to have_content '/unsubscribe' - expect(page).to have_content 'Commands applied' - - expect(issuable.subscribed?(maintainer, project)).to be_falsy - end - end - - context "with a note assigning the #{issuable_type} to the current user" do - it "assigns the #{issuable_type} to the current user" do - add_note("/assign me") - - expect(page).not_to have_content '/assign me' - expect(page).to have_content 'Commands applied' - - expect(issuable.reload.assignees).to eq [maintainer] - end - end - - context "with a note locking the #{issuable_type} discussion" do - before do - issuable.update(discussion_locked: false) - expect(issuable).not_to be_discussion_locked - end - - context "when current user can lock #{issuable_type} discussion" do - it "locks the #{issuable_type} discussion" do - add_note("/lock") - - expect(page).not_to have_content '/lock' - expect(page).to have_content 'Commands applied' - - expect(issuable.reload).to be_discussion_locked - end - end - - context "when current user cannot lock #{issuable_type}" do - before do - guest = create(:user) - project.add_guest(guest) - - gitlab_sign_out - sign_in(guest) - visit public_send("project_#{issuable_type}_path", project, issuable) - end - - it "does not lock the #{issuable_type} discussion" do - add_note("/lock") - - expect(page).not_to have_content 'Commands applied' - - expect(issuable).not_to be_discussion_locked - end - end - end - - context "with a note unlocking the #{issuable_type} discussion" do - before do - issuable.update(discussion_locked: true) - expect(issuable).to be_discussion_locked - end - - context "when current user can unlock #{issuable_type} discussion" do - it "unlocks the #{issuable_type} discussion" do - add_note("/unlock") - - expect(page).not_to have_content '/unlock' - expect(page).to have_content 'Commands applied' - - expect(issuable.reload).not_to be_discussion_locked - end - end - - context "when current user cannot unlock #{issuable_type}" do - before do - guest = create(:user) - project.add_guest(guest) - - gitlab_sign_out - sign_in(guest) - visit public_send("project_#{issuable_type}_path", project, issuable) - end - - it "does not unlock the #{issuable_type} discussion" do - add_note("/unlock") - - expect(page).not_to have_content 'Commands applied' - - expect(issuable).to be_discussion_locked - end - end - end - end - - describe "preview of note on #{issuable_type}", :js do - it 'removes quick actions from note and explains them' do - create(:user, username: 'bob') - - visit public_send("project_#{issuable_type}_path", project, issuable) - - page.within('.js-main-target-form') do - fill_in 'note[note]', with: "Awesome!\n/assign @bob " - click_on 'Preview' - - expect(page).to have_content 'Awesome!' - expect(page).not_to have_content '/assign @bob' - expect(page).to have_content 'Assigns @bob.' - end - end - end -end diff --git a/spec/support/helpers/license_helper.rb b/spec/support/helpers/license_helper.rb new file mode 100644 index 00000000000..4aaad55a8ef --- /dev/null +++ b/spec/support/helpers/license_helper.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +# Placeholder module for EE implementation needed for CE specs to be run in EE codebase +module LicenseHelpers + def stub_licensed_features(features) + # do nothing + end +end diff --git a/spec/support/helpers/stub_worker.rb b/spec/support/helpers/stub_worker.rb new file mode 100644 index 00000000000..58b7ee93dff --- /dev/null +++ b/spec/support/helpers/stub_worker.rb @@ -0,0 +1,9 @@ +# Inspired by https://github.com/ljkbennett/stub_env/blob/master/lib/stub_env/helpers.rb +module StubWorker + def stub_worker(queue:) + Class.new do + include Sidekiq::Worker + sidekiq_options queue: queue + end + end +end diff --git a/spec/support/shared_context/policies/project_policy_shared_context.rb b/spec/support/shared_context/policies/project_policy_shared_context.rb index 8bcd26ec0cd..3ad6e067674 100644 --- a/spec/support/shared_context/policies/project_policy_shared_context.rb +++ b/spec/support/shared_context/policies/project_policy_shared_context.rb @@ -15,7 +15,7 @@ RSpec.shared_context 'ProjectPolicy context' do read_project_for_iids read_issue_iid read_label read_milestone read_project_snippet read_project_member read_note create_project create_issue create_note upload_file create_merge_request_in - award_emoji read_release + award_emoji ] end @@ -24,7 +24,7 @@ RSpec.shared_context 'ProjectPolicy context' do download_code fork_project create_project_snippet update_issue admin_issue admin_label admin_list read_commit_status read_build read_container_image read_pipeline read_environment read_deployment - read_merge_request download_wiki_code read_sentry_issue + read_merge_request download_wiki_code read_sentry_issue read_release ] end diff --git a/spec/support/shared_examples/malicious_regexp_shared_examples.rb b/spec/support/shared_examples/malicious_regexp_shared_examples.rb index db69b75c0c8..a86050e2cf2 100644 --- a/spec/support/shared_examples/malicious_regexp_shared_examples.rb +++ b/spec/support/shared_examples/malicious_regexp_shared_examples.rb @@ -2,7 +2,8 @@ require 'timeout' shared_examples 'malicious regexp' do let(:malicious_text) { 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!' } - let(:malicious_regexp) { '(?i)^(([a-z])+.)+[A-Z]([a-z])+$' } + let(:malicious_regexp_re2) { '(?i)^(([a-z])+.)+[A-Z]([a-z])+$' } + let(:malicious_regexp_ruby) { '/^(([a-z])+.)+[A-Z]([a-z])+$/i' } it 'takes under a second' do expect { Timeout.timeout(1) { subject } }.not_to raise_error diff --git a/spec/support/shared_examples/quick_actions/commit/tag_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/commit/tag_quick_action_shared_examples.rb new file mode 100644 index 00000000000..4604d867507 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/commit/tag_quick_action_shared_examples.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +shared_examples 'tag quick action' do +end diff --git a/spec/support/shared_examples/quick_actions/issuable/assign_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/assign_quick_action_shared_examples.rb new file mode 100644 index 00000000000..d97da6be192 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/assign_quick_action_shared_examples.rb @@ -0,0 +1,110 @@ +# frozen_string_literal: true + +shared_examples 'assign quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets assign quick action accordingly" do + assignee = create(:user, username: 'bob') + + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/assign @bob" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable.assignees).to eq [assignee] + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + end + + it "creates the #{issuable_type} and interprets assign quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/assign me" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable.assignees).to eq [maintainer] + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'creates the note and interprets the assign quick action accordingly' do + assignee = create(:user, username: 'bob') + add_note("Awesome!\n\n/assign @bob") + + expect(page).to have_content 'Awesome!' + expect(page).not_to have_content '/assign @bob' + + wait_for_requests + issuable.reload + note = issuable.notes.user.first + + expect(note.note).to eq 'Awesome!' + expect(issuable.assignees).to eq [assignee] + end + + it "assigns the #{issuable_type} to the current user" do + add_note("/assign me") + + expect(page).not_to have_content '/assign me' + expect(page).to have_content 'Commands applied' + + expect(issuable.reload.assignees).to eq [maintainer] + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains assign quick action to bob' do + create(:user, username: 'bob') + + visit public_send("project_#{issuable_type}_path", project, issuable) + + page.within('.js-main-target-form') do + fill_in 'note[note]', with: "Awesome!\n/assign @bob " + click_on 'Preview' + + expect(page).not_to have_content '/assign @bob' + expect(page).to have_content 'Awesome!' + expect(page).to have_content 'Assigns @bob.' + end + end + + it 'explains assign quick action to me' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + page.within('.js-main-target-form') do + fill_in 'note[note]', with: "Awesome!\n/assign me" + click_on 'Preview' + + expect(page).not_to have_content '/assign me' + expect(page).to have_content 'Awesome!' + expect(page).to have_content "Assigns @#{maintainer.username}." + end + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/award_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/award_quick_action_shared_examples.rb new file mode 100644 index 00000000000..74cbfa3f4b4 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/award_quick_action_shared_examples.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +shared_examples 'award quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets award quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/award :100:" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable).to be_opened + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + expect(issuable.award_emoji).to eq [] + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + expect(issuable.award_emoji).to eq [] + end + + it 'creates the note and interprets the award quick action accordingly' do + add_note("/award :100:") + + wait_for_requests + expect(page).not_to have_content '/award' + expect(page).to have_content 'Commands applied' + expect(issuable.reload.award_emoji.last.name).to eq('100') + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains label quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note('/award :100:') + + expect(page).not_to have_content '/award' + expect(page).to have_selector "gl-emoji[data-name='100']" + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb new file mode 100644 index 00000000000..e0d0b790a0e --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +shared_examples 'close quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets close quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/close" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable).to be_opened + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + end + end + + context "post note to existing #{issuable_type}" do + before do + expect(issuable).to be_opened + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'creates the note and interprets the close quick action accordingly' do + add_note("this is done, close\n\n/close") + + wait_for_requests + expect(page).not_to have_content '/close' + expect(page).to have_content 'this is done, close' + + issuable.reload + note = issuable.notes.user.first + + expect(note.note).to eq 'this is done, close' + expect(issuable).to be_closed + end + + context "when current user cannot close #{issuable_type}" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + end + + it "does not close the #{issuable_type}" do + add_note('/close') + + expect(page).not_to have_content 'Commands applied' + expect(issuable).to be_open + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains close quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + page.within('.js-main-target-form') do + fill_in 'note[note]', with: "this is done, close\n/close" + click_on 'Preview' + + expect(page).not_to have_content '/close' + expect(page).to have_content 'this is done, close' + expect(page).to have_content "Closes this #{issuable_type.to_s.humanize.downcase}." + end + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/copy_metadata_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/copy_metadata_quick_action_shared_examples.rb new file mode 100644 index 00000000000..1e1e3c7bc95 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/copy_metadata_quick_action_shared_examples.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +shared_examples 'copy_metadata quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets copy_metadata quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/copy_metadata #{source_issuable.to_reference(project)}" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).last + + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + issuable.reload + expect(issuable.description).to eq 'bug description' + expect(issuable.milestone).to eq milestone + expect(issuable.labels).to match_array([label_bug, label_feature]) + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'creates the note and interprets copy_metadata quick action accordingly' do + add_note("/copy_metadata #{source_issuable.to_reference(project)}") + + wait_for_requests + expect(page).not_to have_content '/copy_metadata' + expect(page).to have_content 'Commands applied' + issuable.reload + expect(issuable.milestone).to eq milestone + expect(issuable.labels).to match_array([label_bug, label_feature]) + end + + context "when current user cannot copy_metadata" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'does not copy_metadata' do + add_note("/copy_metadata #{source_issuable.to_reference(project)}") + + wait_for_requests + expect(page).not_to have_content '/copy_metadata' + expect(page).not_to have_content 'Commands applied' + issuable.reload + expect(issuable.milestone).not_to eq milestone + expect(issuable.labels).to eq [] + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains copy_metadata quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note("/copy_metadata #{source_issuable.to_reference(project)}") + + expect(page).not_to have_content '/copy_metadata' + expect(page).to have_content "Copy labels and milestone from #{source_issuable.to_reference(project)}." + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/done_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/done_quick_action_shared_examples.rb new file mode 100644 index 00000000000..8a72bbc13bf --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/done_quick_action_shared_examples.rb @@ -0,0 +1,103 @@ +# frozen_string_literal: true + +shared_examples 'done quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets done quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/done" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable).to be_opened + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + + todos = TodosFinder.new(maintainer).execute + expect(todos.size).to eq 0 + end + end + + context "post note to existing #{issuable_type}" do + before do + TodoService.new.mark_todo(issuable, maintainer) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'creates the note and interprets the done quick action accordingly' do + todos = TodosFinder.new(maintainer).execute + todo = todos.first + expect(todo.reload).to be_pending + + expect(todos.size).to eq 1 + expect(todo.target).to eq issuable + expect(todo.author).to eq maintainer + expect(todo.user).to eq maintainer + + add_note('/done') + + wait_for_requests + expect(page).not_to have_content '/done' + expect(page).to have_content 'Commands applied' + expect(todo.reload).to be_done + end + + context "when current user cannot mark #{issuable_type} todo as done" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it "does not set the #{issuable_type} todo as done" do + todos = TodosFinder.new(maintainer).execute + todo = todos.first + expect(todo.reload).to be_pending + + expect(todos.size).to eq 1 + expect(todo.target).to eq issuable + expect(todo.author).to eq maintainer + expect(todo.user).to eq maintainer + + add_note('/done') + + expect(page).not_to have_content 'Commands applied' + expect(todo.reload).to be_pending + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains done quick action' do + TodoService.new.mark_todo(issuable, maintainer) + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note('/done') + + expect(page).not_to have_content '/done' + expect(page).to have_content "Marks todo as done." + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/estimate_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/estimate_quick_action_shared_examples.rb new file mode 100644 index 00000000000..648755d7e55 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/estimate_quick_action_shared_examples.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +shared_examples 'estimate quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets estimate quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/estimate 1d 2h 3m" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + expect(issuable.time_estimate).to eq 36180 + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'creates the note and interprets the estimate quick action accordingly' do + add_note("/estimate 1d 2h 3m") + + wait_for_requests + expect(page).not_to have_content '/estimate' + expect(page).to have_content 'Commands applied' + expect(issuable.reload.time_estimate).to eq 36180 + end + + context "when current user cannot set estimate to #{issuable_type}" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'does not set estimate' do + add_note("/estimate ~bug ~feature") + + wait_for_requests + expect(page).not_to have_content '/estimate' + expect(issuable.reload.time_estimate).to eq 0 + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains estimate quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note('/estimate 1d 2h 3m') + + expect(page).not_to have_content '/estimate' + expect(page).to have_content 'Sets time estimate to 1d 2h 3m.' + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/label_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/label_quick_action_shared_examples.rb new file mode 100644 index 00000000000..9066e382b70 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/label_quick_action_shared_examples.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +shared_examples 'label quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets label quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/label ~bug ~feature" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable).to be_opened + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + expect(issuable.labels).to match_array([label_bug, label_feature]) + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + expect(issuable.labels).to eq [] + end + + it 'creates the note and interprets the label quick action accordingly' do + add_note("/label ~bug ~feature") + + wait_for_requests + expect(page).not_to have_content '/label' + expect(page).to have_content 'Commands applied' + expect(issuable.reload.labels).to match_array([label_bug, label_feature]) + end + + context "when current user cannot set label to #{issuable_type}" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'does not set label' do + add_note("/label ~bug ~feature") + + wait_for_requests + expect(page).not_to have_content '/label' + expect(issuable.labels).to eq [] + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains label quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note('/label ~bug ~feature') + + expect(page).not_to have_content '/label' + expect(page).to have_content 'Adds bug feature labels.' + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/lock_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/lock_quick_action_shared_examples.rb new file mode 100644 index 00000000000..d3197f2a459 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/lock_quick_action_shared_examples.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +shared_examples 'lock quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets lock quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/lock" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable).to be_opened + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + expect(issuable).not_to be_discussion_locked + end + end + + context "post note to existing #{issuable_type}" do + before do + issuable.update(discussion_locked: false) + expect(issuable).not_to be_discussion_locked + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'creates the note and interprets the lock quick action accordingly' do + add_note('/lock') + + wait_for_requests + expect(page).not_to have_content '/lock' + expect(page).to have_content 'Commands applied' + expect(issuable.reload).to be_discussion_locked + end + + context "when current user cannot lock to #{issuable_type}" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it "does not lock the #{issuable_type}" do + add_note('/lock') + + wait_for_requests + expect(page).not_to have_content '/lock' + expect(issuable).not_to be_discussion_locked + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains lock quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note('/lock') + + expect(page).not_to have_content '/lock' + expect(page).to have_content "Locks the discussion" + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/milestone_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/milestone_quick_action_shared_examples.rb new file mode 100644 index 00000000000..7f16ce93b6a --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/milestone_quick_action_shared_examples.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +shared_examples 'milestone quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets milestone quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/milestone %\"ASAP\"" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable).to be_opened + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + expect(issuable.milestone).to eq milestone + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + expect(issuable.milestone).to be_nil + end + + it 'creates the note and interprets the milestone quick action accordingly' do + add_note("/milestone %\"ASAP\"") + + wait_for_requests + expect(page).not_to have_content '/milestone' + expect(page).to have_content 'Commands applied' + expect(issuable.reload.milestone).to eq milestone + end + + context "when current user cannot set milestone to #{issuable_type}" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'does not set milestone' do + add_note('/milestone') + + wait_for_requests + expect(page).not_to have_content '/milestone' + expect(issuable.reload.milestone).to be_nil + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains milestone quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note("/milestone %\"ASAP\"") + + expect(page).not_to have_content '/milestone' + expect(page).to have_content 'Sets the milestone to %ASAP' + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/relabel_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/relabel_quick_action_shared_examples.rb new file mode 100644 index 00000000000..643ae77516a --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/relabel_quick_action_shared_examples.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +shared_examples 'relabel quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets relabel quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/label ~bug /relabel ~feature" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable).to be_opened + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + expect(issuable.labels).to eq [label_bug, label_feature] + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + issuable.update(labels: [label_bug]) + end + + it 'creates the note and interprets the relabel quick action accordingly' do + add_note('/relabel ~feature') + + wait_for_requests + expect(page).not_to have_content '/relabel' + expect(page).to have_content 'Commands applied' + expect(issuable.reload.labels).to match_array([label_feature]) + end + + it 'creates the note and interprets the relabel quick action with empty param' do + add_note('/relabel') + + wait_for_requests + expect(page).not_to have_content '/relabel' + expect(page).to have_content 'Commands applied' + expect(issuable.reload.labels).to match_array([label_bug]) + end + + context "when current user cannot relabel to #{issuable_type}" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'does not relabel' do + add_note('/relabel ~feature') + + wait_for_requests + expect(page).not_to have_content '/relabel' + expect(issuable.labels).to match_array([label_bug]) + end + end + end + + context "preview of note on #{issuable_type}", :js do + before do + issuable.update(labels: [label_bug]) + visit public_send("project_#{issuable_type}_path", project, issuable) + end + + it 'explains relabel all quick action' do + preview_note('/relabel ~feature') + + expect(page).not_to have_content '/relabel' + expect(page).to have_content 'Replaces all labels with feature label.' + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/remove_estimate_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/remove_estimate_quick_action_shared_examples.rb new file mode 100644 index 00000000000..24f6f8d5bf4 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/remove_estimate_quick_action_shared_examples.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +shared_examples 'remove_estimate quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets estimate quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/remove_estimate" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + expect(issuable.time_estimate).to eq 0 + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + issuable.update_attribute(:time_estimate, 36180) + end + + it 'creates the note and interprets the remove_estimate quick action accordingly' do + add_note("/remove_estimate") + + wait_for_requests + expect(page).not_to have_content '/remove_estimate' + expect(page).to have_content 'Commands applied' + expect(issuable.reload.time_estimate).to eq 0 + end + + context "when current user cannot remove_estimate" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'does not remove_estimate' do + add_note('/remove_estimate') + + wait_for_requests + expect(page).not_to have_content '/remove_estimate' + expect(issuable.reload.time_estimate).to eq 36180 + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains remove_estimate quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note('/remove_estimate') + + expect(page).not_to have_content '/remove_estimate' + expect(page).to have_content 'Removes time estimate.' + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/remove_milestone_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/remove_milestone_quick_action_shared_examples.rb new file mode 100644 index 00000000000..edd92d5cdbc --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/remove_milestone_quick_action_shared_examples.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +shared_examples 'remove_milestone quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets remove_milestone quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/remove_milestone" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable).to be_opened + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + expect(issuable.milestone).to be_nil + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + issuable.update(milestone: milestone) + expect(issuable.milestone).to eq(milestone) + end + + it 'creates the note and interprets the remove_milestone quick action accordingly' do + add_note("/remove_milestone") + + wait_for_requests + expect(page).not_to have_content '/remove_milestone' + expect(page).to have_content 'Commands applied' + expect(issuable.reload.milestone).to be_nil + end + + context "when current user cannot remove milestone to #{issuable_type}" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'does not remove milestone' do + add_note('/remove_milestone') + + wait_for_requests + expect(page).not_to have_content '/remove_milestone' + expect(issuable.reload.milestone).to eq(milestone) + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains remove_milestone quick action' do + issuable.update(milestone: milestone) + expect(issuable.milestone).to eq(milestone) + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note("/remove_milestone") + + expect(page).not_to have_content '/remove_milestone' + expect(page).to have_content 'Removes %ASAP milestone.' + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/remove_time_spent_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/remove_time_spent_quick_action_shared_examples.rb new file mode 100644 index 00000000000..6d5894b2318 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/remove_time_spent_quick_action_shared_examples.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +shared_examples 'remove_time_spent quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets remove_time_spent quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/remove_time_spent" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + expect(issuable.total_time_spent).to eq 0 + end + end + + context "post note to existing #{issuable_type}" do + before do + issuable.update!(spend_time: { duration: 36180, user_id: maintainer.id }) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'creates the note and interprets the remove_time_spent quick action accordingly' do + add_note("/remove_time_spent") + + wait_for_requests + expect(page).not_to have_content '/remove_time_spent' + expect(page).to have_content 'Commands applied' + expect(issuable.reload.total_time_spent).to eq 0 + end + + context "when current user cannot set remove_time_spent time" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'does not set remove_time_spent time' do + add_note("/remove_time_spent") + + wait_for_requests + expect(page).not_to have_content '/remove_time_spent' + expect(issuable.reload.total_time_spent).to eq 36180 + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains remove_time_spent quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note('/remove_time_spent') + + expect(page).not_to have_content '/remove_time_spent' + expect(page).to have_content 'Removes spent time.' + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/reopen_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/reopen_quick_action_shared_examples.rb new file mode 100644 index 00000000000..af173e93bb5 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/reopen_quick_action_shared_examples.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +shared_examples 'reopen quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets reopen quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/reopen" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable).to be_opened + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + end + end + + context "post note to existing #{issuable_type}" do + before do + issuable.close + expect(issuable).to be_closed + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'creates the note and interprets the reopen quick action accordingly' do + add_note('/reopen') + + wait_for_requests + expect(page).not_to have_content '/reopen' + expect(page).to have_content 'Commands applied' + + issuable.reload + expect(issuable).to be_opened + end + + context "when current user cannot reopen #{issuable_type}" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it "does not reopen the #{issuable_type}" do + add_note('/reopen') + + expect(page).not_to have_content 'Commands applied' + expect(issuable).to be_closed + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains reopen quick action' do + issuable.close + expect(issuable).to be_closed + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note('/reopen') + + expect(page).not_to have_content '/reopen' + expect(page).to have_content "Reopens this #{issuable_type.to_s.humanize.downcase}." + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb new file mode 100644 index 00000000000..0a526808585 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +shared_examples 'shrug quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets shrug quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/shrug oops" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq "bug description\noops ¯\\_(ツ)_/¯" + expect(page).to have_content 'bug 345' + expect(page).to have_content "bug description\noops ¯\\_(ツ)_/¯" + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'creates the note and interprets shrug quick action accordingly' do + add_note("/shrug oops") + + wait_for_requests + expect(page).not_to have_content '/shrug oops' + expect(page).to have_content "oops ¯\\_(ツ)_/¯" + expect(issuable.notes.last.note).to eq "oops ¯\\_(ツ)_/¯" + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains shrug quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note('/shrug oops') + + expect(page).not_to have_content '/shrug' + expect(page).to have_content "oops ¯\\_(ツ)_/¯" + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/spend_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/spend_quick_action_shared_examples.rb new file mode 100644 index 00000000000..97b4885eba0 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/spend_quick_action_shared_examples.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +shared_examples 'spend quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets spend quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/spend 1d 2h 3m" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + expect(issuable.total_time_spent).to eq 36180 + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'creates the note and interprets the spend quick action accordingly' do + add_note("/spend 1d 2h 3m") + + wait_for_requests + expect(page).not_to have_content '/spend' + expect(page).to have_content 'Commands applied' + expect(issuable.reload.total_time_spent).to eq 36180 + end + + context "when current user cannot set spend time" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'does not set spend time' do + add_note("/spend 1s 2h 3m") + + wait_for_requests + expect(page).not_to have_content '/spend' + expect(issuable.reload.total_time_spent).to eq 0 + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains spend quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note('/spend 1d 2h 3m') + + expect(page).not_to have_content '/spend' + expect(page).to have_content 'Adds 1d 2h 3m spent time.' + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/subscribe_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/subscribe_quick_action_shared_examples.rb new file mode 100644 index 00000000000..15aefd511a5 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/subscribe_quick_action_shared_examples.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +shared_examples 'subscribe quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets subscribe quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/subscribe" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable).to be_opened + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + expect(issuable.subscribed?(maintainer, project)).to be_truthy + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + expect(issuable.subscribed?(maintainer, project)).to be_falsy + end + + it 'creates the note and interprets the subscribe quick action accordingly' do + add_note('/subscribe') + + wait_for_requests + expect(page).not_to have_content '/subscribe' + expect(page).to have_content 'Commands applied' + expect(issuable.subscribed?(maintainer, project)).to be_truthy + end + + context "when current user cannot subscribe to #{issuable_type}" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it "does not subscribe to the #{issuable_type}" do + add_note('/subscribe') + + wait_for_requests + expect(page).not_to have_content '/subscribe' + expect(page).to have_content 'Commands applied' + expect(issuable.subscribed?(maintainer, project)).to be_falsy + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains subscribe quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note('/subscribe') + + expect(page).not_to have_content '/subscribe' + expect(page).to have_content "Subscribes to this #{issuable_type.to_s.humanize.downcase}" + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb new file mode 100644 index 00000000000..ef831e39872 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +shared_examples 'tableflip quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets tableflip quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/tableflip oops" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq "bug description\noops (╯°□°)╯︵ ┻━┻" + expect(page).to have_content 'bug 345' + expect(page).to have_content "bug description\noops (╯°□°)╯︵ ┻━┻" + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'creates the note and interprets tableflip quick action accordingly' do + add_note("/tableflip oops") + + wait_for_requests + expect(page).not_to have_content '/tableflip oops' + expect(page).to have_content "oops (╯°□°)╯︵ ┻━┻" + expect(issuable.notes.last.note).to eq "oops (╯°□°)╯︵ ┻━┻" + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains tableflip quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note('/tableflip oops') + + expect(page).not_to have_content '/tableflip' + expect(page).to have_content "oops (╯°□°)╯︵ ┻━┻" + end + end +end diff --git a/spec/support/shared_examples/time_tracking_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb index 909d4e2ee8d..ed904c8d539 100644 --- a/spec/support/shared_examples/time_tracking_shared_examples.rb +++ b/spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb @@ -1,4 +1,17 @@ -shared_examples 'issuable time tracker' do +# frozen_string_literal: true + +shared_examples 'issuable time tracker' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + after do + wait_for_requests + end + it 'renders the sidebar component empty state' do page.within '.time-tracking-no-tracking-pane' do expect(page).to have_content 'No estimate or time spent' diff --git a/spec/support/shared_examples/quick_actions/issuable/title_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/title_quick_action_shared_examples.rb new file mode 100644 index 00000000000..93a69093dde --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/title_quick_action_shared_examples.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +shared_examples 'title quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets title quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/title new title" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable).to be_opened + expect(issuable.title).to eq 'bug 345' + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'creates the note and interprets the title quick action accordingly' do + add_note('/title New title') + + wait_for_requests + expect(page).not_to have_content '/title new title' + expect(page).to have_content 'Commands applied' + expect(page).to have_content 'New title' + + issuable.reload + expect(issuable.title).to eq 'New title' + end + + context "when current user cannot set title #{issuable_type}" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it "does not set title to the #{issuable_type}" do + add_note('/title New title') + + expect(page).not_to have_content 'Commands applied' + expect(issuable.title).not_to eq 'New title' + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains title quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note('/title New title') + wait_for_requests + + expect(page).not_to have_content '/title New title' + expect(page).to have_content 'Changes the title to "New title".' + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/todo_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/todo_quick_action_shared_examples.rb new file mode 100644 index 00000000000..cccc28127ce --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/todo_quick_action_shared_examples.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +shared_examples 'todo quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets todo quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/todo" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable).to be_opened + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + + todos = TodosFinder.new(maintainer).execute + expect(todos.size).to eq 0 + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'creates the note and interprets the todo quick action accordingly' do + add_note('/todo') + + wait_for_requests + expect(page).not_to have_content '/todo' + expect(page).to have_content 'Commands applied' + + todos = TodosFinder.new(maintainer).execute + todo = todos.first + + expect(todos.size).to eq 1 + expect(todo).to be_pending + expect(todo.target).to eq issuable + expect(todo.author).to eq maintainer + expect(todo.user).to eq maintainer + end + + context "when current user cannot add todo #{issuable_type}" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it "does not add todo the #{issuable_type}" do + add_note('/todo') + + expect(page).not_to have_content 'Commands applied' + todos = TodosFinder.new(maintainer).execute + expect(todos.size).to eq 0 + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains todo quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note('/todo') + + expect(page).not_to have_content '/todo' + expect(page).to have_content "Adds a todo." + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/unassign_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/unassign_quick_action_shared_examples.rb new file mode 100644 index 00000000000..0b1a52bc860 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/unassign_quick_action_shared_examples.rb @@ -0,0 +1,120 @@ +# frozen_string_literal: true + +shared_examples 'unassign quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets unassign quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/unassign @bob" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable.assignees).to eq [] + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + end + + it "creates the #{issuable_type} and interprets unassign quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/unassign me" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable.assignees).to eq [] + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'creates the note and interprets the unassign quick action accordingly' do + assignee = create(:user, username: 'bob') + issuable.update(assignee_ids: [assignee.id]) + expect(issuable.assignees).to eq [assignee] + + add_note("Awesome!\n\n/unassign @bob") + + expect(page).to have_content 'Awesome!' + expect(page).not_to have_content '/unassign @bob' + + wait_for_requests + issuable.reload + note = issuable.notes.user.first + + expect(note.note).to eq 'Awesome!' + expect(issuable.assignees).to eq [] + end + + it "unassigns the #{issuable_type} from current user" do + issuable.update(assignee_ids: [maintainer.id]) + expect(issuable.reload.assignees).to eq [maintainer] + expect(issuable.assignees).to eq [maintainer] + + add_note("/unassign me") + + expect(page).not_to have_content '/unassign me' + expect(page).to have_content 'Commands applied' + + expect(issuable.reload.assignees).to eq [] + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains unassign quick action: from bob' do + assignee = create(:user, username: 'bob') + issuable.update(assignee_ids: [assignee.id]) + expect(issuable.assignees).to eq [assignee] + + visit public_send("project_#{issuable_type}_path", project, issuable) + + page.within('.js-main-target-form') do + fill_in 'note[note]', with: "Awesome!\n/unassign @bob " + click_on 'Preview' + + expect(page).not_to have_content '/unassign @bob' + expect(page).to have_content 'Awesome!' + expect(page).to have_content 'Removes assignee @bob.' + end + end + + it 'explains unassign quick action: from me' do + issuable.update(assignee_ids: [maintainer.id]) + expect(issuable.assignees).to eq [maintainer] + + visit public_send("project_#{issuable_type}_path", project, issuable) + + page.within('.js-main-target-form') do + fill_in 'note[note]', with: "Awesome!\n/unassign me" + click_on 'Preview' + + expect(page).not_to have_content '/unassign me' + expect(page).to have_content 'Awesome!' + expect(page).to have_content "Removes assignee @#{maintainer.username}." + end + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/unlabel_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/unlabel_quick_action_shared_examples.rb new file mode 100644 index 00000000000..1a1ee05841f --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/unlabel_quick_action_shared_examples.rb @@ -0,0 +1,102 @@ +# frozen_string_literal: true + +shared_examples 'unlabel quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets unlabel quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/label ~bug /unlabel" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable).to be_opened + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + expect(issuable.labels).to eq [label_bug] + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + issuable.update(labels: [label_bug, label_feature]) + end + + it 'creates the note and interprets the unlabel all quick action accordingly' do + add_note("/unlabel") + + wait_for_requests + expect(page).not_to have_content '/unlabel' + expect(page).to have_content 'Commands applied' + expect(issuable.reload.labels).to eq [] + end + + it 'creates the note and interprets the unlabel some quick action accordingly' do + add_note("/unlabel ~bug") + + wait_for_requests + expect(page).not_to have_content '/unlabel' + expect(page).to have_content 'Commands applied' + expect(issuable.reload.labels).to match_array([label_feature]) + end + + context "when current user cannot unlabel to #{issuable_type}" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'does not unlabel' do + add_note("/unlabel") + + wait_for_requests + expect(page).not_to have_content '/unlabel' + expect(issuable.labels).to match_array([label_bug, label_feature]) + end + end + end + + context "preview of note on #{issuable_type}", :js do + before do + issuable.update(labels: [label_bug, label_feature]) + visit public_send("project_#{issuable_type}_path", project, issuable) + end + + it 'explains unlabel all quick action' do + preview_note('/unlabel') + + expect(page).not_to have_content '/unlabel' + expect(page).to have_content 'Removes all labels.' + end + + it 'explains unlabel some quick action' do + preview_note('/unlabel ~bug') + + expect(page).not_to have_content '/unlabel' + expect(page).to have_content 'Removes bug label.' + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/unlock_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/unlock_quick_action_shared_examples.rb new file mode 100644 index 00000000000..998ff99b32e --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/unlock_quick_action_shared_examples.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +shared_examples 'unlock quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets unlock quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/unlock" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable).to be_opened + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + expect(issuable).not_to be_discussion_locked + end + end + + context "post note to existing #{issuable_type}" do + before do + issuable.update(discussion_locked: true) + expect(issuable).to be_discussion_locked + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it 'creates the note and interprets the unlock quick action accordingly' do + add_note('/unlock') + + wait_for_requests + expect(page).not_to have_content '/unlock' + expect(page).to have_content 'Commands applied' + expect(issuable.reload).not_to be_discussion_locked + end + + context "when current user cannot unlock to #{issuable_type}" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it "does not lock the #{issuable_type}" do + add_note('/unlock') + + wait_for_requests + expect(page).not_to have_content '/unlock' + expect(issuable).to be_discussion_locked + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains unlock quick action' do + issuable.update(discussion_locked: true) + expect(issuable).to be_discussion_locked + + visit public_send("project_#{issuable_type}_path", project, issuable) + + preview_note('/unlock') + + expect(page).not_to have_content '/unlock' + expect(page).to have_content 'Unlocks the discussion' + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issuable/unsubscribe_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/unsubscribe_quick_action_shared_examples.rb new file mode 100644 index 00000000000..bd92f133889 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/unsubscribe_quick_action_shared_examples.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +shared_examples 'unsubscribe quick action' do |issuable_type| + before do + project.add_maintainer(maintainer) + gitlab_sign_in(maintainer) + end + + context "new #{issuable_type}", :js do + before do + case issuable_type + when :merge_request + visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts) + wait_for_all_requests + when :issue + visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts) + wait_for_all_requests + end + end + + it "creates the #{issuable_type} and interprets unsubscribe quick action accordingly" do + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/unsubscribe" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq 'bug description' + expect(issuable).to be_opened + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + expect(issuable.subscribed?(maintainer, project)).to be_truthy + end + end + + context "post note to existing #{issuable_type}" do + before do + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + issuable.subscribe(maintainer, project) + expect(issuable.subscribed?(maintainer, project)).to be_truthy + end + + it 'creates the note and interprets the unsubscribe quick action accordingly' do + add_note('/unsubscribe') + + wait_for_requests + expect(page).not_to have_content '/unsubscribe' + expect(page).to have_content 'Commands applied' + expect(issuable.subscribed?(maintainer, project)).to be_falsey + end + + context "when current user cannot unsubscribe to #{issuable_type}" do + before do + guest = create(:user) + project.add_guest(guest) + + gitlab_sign_out + gitlab_sign_in(guest) + visit public_send("project_#{issuable_type}_path", project, issuable) + wait_for_all_requests + end + + it "does not unsubscribe to the #{issuable_type}" do + add_note('/unsubscribe') + + wait_for_requests + expect(page).not_to have_content '/unsubscribe' + expect(issuable.subscribed?(maintainer, project)).to be_truthy + end + end + end + + context "preview of note on #{issuable_type}", :js do + it 'explains unsubscribe quick action' do + visit public_send("project_#{issuable_type}_path", project, issuable) + issuable.subscribe(maintainer, project) + expect(issuable.subscribed?(maintainer, project)).to be_truthy + + preview_note('/unsubscribe') + + expect(page).not_to have_content '/unsubscribe' + expect(page).to have_content "Unsubscribes from this #{issuable_type.to_s.humanize.downcase}." + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issue/board_move_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/board_move_quick_action_shared_examples.rb new file mode 100644 index 00000000000..6edd20bb024 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issue/board_move_quick_action_shared_examples.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +shared_examples 'board_move quick action' do +end diff --git a/spec/support/shared_examples/quick_actions/issue/confidential_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/confidential_quick_action_shared_examples.rb new file mode 100644 index 00000000000..c68e5aee842 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issue/confidential_quick_action_shared_examples.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +shared_examples 'confidential quick action' do +end diff --git a/spec/support/shared_examples/quick_actions/issue/create_merge_request_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/create_merge_request_quick_action_shared_examples.rb new file mode 100644 index 00000000000..5bfc3bb222f --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issue/create_merge_request_quick_action_shared_examples.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +shared_examples 'create_merge_request quick action' do +end diff --git a/spec/support/shared_examples/quick_actions/issue/due_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/due_quick_action_shared_examples.rb new file mode 100644 index 00000000000..db3ecccc339 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issue/due_quick_action_shared_examples.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +shared_examples 'due quick action not available' do + it 'does not set the due date' do + add_note('/due 2016-08-28') + + expect(page).not_to have_content 'Commands applied' + expect(page).not_to have_content '/due 2016-08-28' + end +end + +shared_examples 'due quick action available and date can be added' do + it 'sets the due date accordingly' do + add_note('/due 2016-08-28') + + expect(page).not_to have_content '/due 2016-08-28' + expect(page).to have_content 'Commands applied' + + visit project_issue_path(project, issue) + + page.within '.due_date' do + expect(page).to have_content 'Aug 28, 2016' + end + end +end diff --git a/spec/support/shared_examples/quick_actions/issue/duplicate_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/duplicate_quick_action_shared_examples.rb new file mode 100644 index 00000000000..24576fe0021 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issue/duplicate_quick_action_shared_examples.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +shared_examples 'duplicate quick action' do +end diff --git a/spec/support/shared_examples/quick_actions/issue/move_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/move_quick_action_shared_examples.rb new file mode 100644 index 00000000000..953e67b0423 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issue/move_quick_action_shared_examples.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +shared_examples 'move quick action' do +end diff --git a/spec/support/shared_examples/quick_actions/issue/remove_due_date_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/remove_due_date_quick_action_shared_examples.rb new file mode 100644 index 00000000000..5904164fcfc --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issue/remove_due_date_quick_action_shared_examples.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +shared_examples 'remove_due_date action not available' do + it 'does not remove the due date' do + add_note("/remove_due_date") + + expect(page).not_to have_content 'Commands applied' + expect(page).not_to have_content '/remove_due_date' + end +end + +shared_examples 'remove_due_date action available and due date can be removed' do + it 'removes the due date accordingly' do + add_note('/remove_due_date') + + expect(page).not_to have_content '/remove_due_date' + expect(page).to have_content 'Commands applied' + + visit project_issue_path(project, issue) + + page.within '.due_date' do + expect(page).to have_content 'No due date' + end + end +end diff --git a/spec/support/shared_examples/quick_actions/merge_request/merge_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/merge_request/merge_quick_action_shared_examples.rb new file mode 100644 index 00000000000..31d88183f0d --- /dev/null +++ b/spec/support/shared_examples/quick_actions/merge_request/merge_quick_action_shared_examples.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +shared_examples 'merge quick action' do +end diff --git a/spec/support/shared_examples/quick_actions/merge_request/target_branch_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/merge_request/target_branch_quick_action_shared_examples.rb new file mode 100644 index 00000000000..ccb4a85325b --- /dev/null +++ b/spec/support/shared_examples/quick_actions/merge_request/target_branch_quick_action_shared_examples.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +shared_examples 'target_branch quick action' do +end diff --git a/spec/support/shared_examples/quick_actions/merge_request/wip_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/merge_request/wip_quick_action_shared_examples.rb new file mode 100644 index 00000000000..6abb12b41b2 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/merge_request/wip_quick_action_shared_examples.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +shared_examples 'wip quick action' do +end diff --git a/spec/uploaders/object_storage_spec.rb b/spec/uploaders/object_storage_spec.rb index 533e9d87ea6..9ce9a353913 100644 --- a/spec/uploaders/object_storage_spec.rb +++ b/spec/uploaders/object_storage_spec.rb @@ -375,7 +375,7 @@ describe ObjectStorage do describe '#fog_public' do subject { uploader.fog_public } - it { is_expected.to eq(false) } + it { is_expected.to eq(nil) } end describe '.workhorse_authorize' do 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 2c60ccfb754..c6c10001bc5 100644 --- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb +++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb @@ -113,4 +113,56 @@ describe 'layouts/nav/sidebar/_project' do end end end + + describe 'ci/cd settings tab' do + before do + project.update!(archived: project_archived) + end + + context 'when project is archived' do + let(:project_archived) { true } + + it 'does not show the ci/cd settings tab' do + render + + expect(rendered).not_to have_link('CI / CD', href: project_settings_ci_cd_path(project)) + end + end + + context 'when project is active' do + let(:project_archived) { false } + + it 'shows the ci/cd settings tab' do + render + + expect(rendered).to have_link('CI / CD', href: project_settings_ci_cd_path(project)) + end + end + end + + describe 'operations settings tab' do + before do + project.update!(archived: project_archived) + end + + context 'when project is archived' do + let(:project_archived) { true } + + it 'does not show the operations settings tab' do + render + + expect(rendered).not_to have_link('Operations', href: project_settings_operations_path(project)) + end + end + + context 'when project is active' do + let(:project_archived) { false } + + it 'shows the operations settings tab' do + render + + expect(rendered).to have_link('Operations', href: project_settings_operations_path(project)) + end + end + end end diff --git a/spec/workers/admin_email_worker_spec.rb b/spec/workers/admin_email_worker_spec.rb index 27687f069ea..f72b932423f 100644 --- a/spec/workers/admin_email_worker_spec.rb +++ b/spec/workers/admin_email_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe AdminEmailWorker do diff --git a/spec/workers/archive_trace_worker_spec.rb b/spec/workers/archive_trace_worker_spec.rb index 7244ad4f199..368ed3f3db1 100644 --- a/spec/workers/archive_trace_worker_spec.rb +++ b/spec/workers/archive_trace_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ArchiveTraceWorker do diff --git a/spec/workers/authorized_projects_worker_spec.rb b/spec/workers/authorized_projects_worker_spec.rb index d095138f6b7..4c02278de64 100644 --- a/spec/workers/authorized_projects_worker_spec.rb +++ b/spec/workers/authorized_projects_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe AuthorizedProjectsWorker do diff --git a/spec/workers/background_migration_worker_spec.rb b/spec/workers/background_migration_worker_spec.rb index 3bd072e7125..746c858609f 100644 --- a/spec/workers/background_migration_worker_spec.rb +++ b/spec/workers/background_migration_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BackgroundMigrationWorker, :sidekiq, :clean_gitlab_redis_shared_state do diff --git a/spec/workers/build_coverage_worker_spec.rb b/spec/workers/build_coverage_worker_spec.rb index ba20488f663..25686ae68ca 100644 --- a/spec/workers/build_coverage_worker_spec.rb +++ b/spec/workers/build_coverage_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BuildCoverageWorker do diff --git a/spec/workers/build_finished_worker_spec.rb b/spec/workers/build_finished_worker_spec.rb index ccb26849e67..33f327d4a0c 100644 --- a/spec/workers/build_finished_worker_spec.rb +++ b/spec/workers/build_finished_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BuildFinishedWorker do diff --git a/spec/workers/build_hooks_worker_spec.rb b/spec/workers/build_hooks_worker_spec.rb index 97654a93f5c..59b252a8be3 100644 --- a/spec/workers/build_hooks_worker_spec.rb +++ b/spec/workers/build_hooks_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BuildHooksWorker do diff --git a/spec/workers/build_success_worker_spec.rb b/spec/workers/build_success_worker_spec.rb index 5eb9709ded9..065aeaf2b65 100644 --- a/spec/workers/build_success_worker_spec.rb +++ b/spec/workers/build_success_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BuildSuccessWorker do diff --git a/spec/workers/build_trace_sections_worker_spec.rb b/spec/workers/build_trace_sections_worker_spec.rb index 45243f45547..97fc0a2da0c 100644 --- a/spec/workers/build_trace_sections_worker_spec.rb +++ b/spec/workers/build_trace_sections_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe BuildTraceSectionsWorker do diff --git a/spec/workers/ci/archive_traces_cron_worker_spec.rb b/spec/workers/ci/archive_traces_cron_worker_spec.rb index 478fb7d2c0f..eca6cf5235f 100644 --- a/spec/workers/ci/archive_traces_cron_worker_spec.rb +++ b/spec/workers/ci/archive_traces_cron_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::ArchiveTracesCronWorker do diff --git a/spec/workers/ci/build_schedule_worker_spec.rb b/spec/workers/ci/build_schedule_worker_spec.rb index 4a3fe84d7f7..647f9763fed 100644 --- a/spec/workers/ci/build_schedule_worker_spec.rb +++ b/spec/workers/ci/build_schedule_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::BuildScheduleWorker do diff --git a/spec/workers/cluster_provision_worker_spec.rb b/spec/workers/cluster_provision_worker_spec.rb index da32f29fec0..9cc2ad12bfc 100644 --- a/spec/workers/cluster_provision_worker_spec.rb +++ b/spec/workers/cluster_provision_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ClusterProvisionWorker do diff --git a/spec/workers/cluster_wait_for_ingress_ip_address_worker_spec.rb b/spec/workers/cluster_wait_for_ingress_ip_address_worker_spec.rb index 2e2e9afd25a..a9ffdfb085e 100644 --- a/spec/workers/cluster_wait_for_ingress_ip_address_worker_spec.rb +++ b/spec/workers/cluster_wait_for_ingress_ip_address_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ClusterWaitForIngressIpAddressWorker do diff --git a/spec/workers/concerns/application_worker_spec.rb b/spec/workers/concerns/application_worker_spec.rb index 901d77178bc..ae5244e2f62 100644 --- a/spec/workers/concerns/application_worker_spec.rb +++ b/spec/workers/concerns/application_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ApplicationWorker do diff --git a/spec/workers/concerns/cluster_queue_spec.rb b/spec/workers/concerns/cluster_queue_spec.rb index 4118b9aa194..732d55dfbde 100644 --- a/spec/workers/concerns/cluster_queue_spec.rb +++ b/spec/workers/concerns/cluster_queue_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ClusterQueue do diff --git a/spec/workers/concerns/cronjob_queue_spec.rb b/spec/workers/concerns/cronjob_queue_spec.rb index c042a52f41f..cf4d47b7500 100644 --- a/spec/workers/concerns/cronjob_queue_spec.rb +++ b/spec/workers/concerns/cronjob_queue_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe CronjobQueue do diff --git a/spec/workers/concerns/gitlab/github_import/notify_upon_death_spec.rb b/spec/workers/concerns/gitlab/github_import/notify_upon_death_spec.rb index 4b9aa9a7ef8..200cdffd560 100644 --- a/spec/workers/concerns/gitlab/github_import/notify_upon_death_spec.rb +++ b/spec/workers/concerns/gitlab/github_import/notify_upon_death_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::NotifyUponDeath do diff --git a/spec/workers/concerns/gitlab/github_import/object_importer_spec.rb b/spec/workers/concerns/gitlab/github_import/object_importer_spec.rb index 9c187bead0a..51b685b5792 100644 --- a/spec/workers/concerns/gitlab/github_import/object_importer_spec.rb +++ b/spec/workers/concerns/gitlab/github_import/object_importer_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::ObjectImporter do diff --git a/spec/workers/concerns/gitlab/github_import/queue_spec.rb b/spec/workers/concerns/gitlab/github_import/queue_spec.rb index a96f583aff7..d262bc2e05c 100644 --- a/spec/workers/concerns/gitlab/github_import/queue_spec.rb +++ b/spec/workers/concerns/gitlab/github_import/queue_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::Queue do diff --git a/spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb b/spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb index 8de4059c4ae..294eacf09ab 100644 --- a/spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb +++ b/spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::ReschedulingMethods do diff --git a/spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb b/spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb index d85a87f2cb0..f9081a875b5 100644 --- a/spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb +++ b/spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::StageMethods do diff --git a/spec/workers/concerns/pipeline_background_queue_spec.rb b/spec/workers/concerns/pipeline_background_queue_spec.rb index 24c0a3c6a20..78ceafb359f 100644 --- a/spec/workers/concerns/pipeline_background_queue_spec.rb +++ b/spec/workers/concerns/pipeline_background_queue_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PipelineBackgroundQueue do diff --git a/spec/workers/concerns/pipeline_queue_spec.rb b/spec/workers/concerns/pipeline_queue_spec.rb index a312b307fce..eedfceb8bf0 100644 --- a/spec/workers/concerns/pipeline_queue_spec.rb +++ b/spec/workers/concerns/pipeline_queue_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PipelineQueue do diff --git a/spec/workers/concerns/project_import_options_spec.rb b/spec/workers/concerns/project_import_options_spec.rb index 3699fd83a9a..c5fbcfb5fb0 100644 --- a/spec/workers/concerns/project_import_options_spec.rb +++ b/spec/workers/concerns/project_import_options_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProjectImportOptions do diff --git a/spec/workers/concerns/repository_check_queue_spec.rb b/spec/workers/concerns/repository_check_queue_spec.rb index d2eeecfc9a8..55ed71f124c 100644 --- a/spec/workers/concerns/repository_check_queue_spec.rb +++ b/spec/workers/concerns/repository_check_queue_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RepositoryCheckQueue do diff --git a/spec/workers/concerns/waitable_worker_spec.rb b/spec/workers/concerns/waitable_worker_spec.rb index ce38cde9208..37fadd6ac02 100644 --- a/spec/workers/concerns/waitable_worker_spec.rb +++ b/spec/workers/concerns/waitable_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe WaitableWorker do diff --git a/spec/workers/create_gpg_signature_worker_spec.rb b/spec/workers/create_gpg_signature_worker_spec.rb index f5479e57260..ae09b4b77f1 100644 --- a/spec/workers/create_gpg_signature_worker_spec.rb +++ b/spec/workers/create_gpg_signature_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe CreateGpgSignatureWorker do diff --git a/spec/workers/create_note_diff_file_worker_spec.rb b/spec/workers/create_note_diff_file_worker_spec.rb index 0ac946a1232..e35aaa7d593 100644 --- a/spec/workers/create_note_diff_file_worker_spec.rb +++ b/spec/workers/create_note_diff_file_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe CreateNoteDiffFileWorker do diff --git a/spec/workers/create_pipeline_worker_spec.rb b/spec/workers/create_pipeline_worker_spec.rb index 02cb0f46cb4..62a17da80c0 100644 --- a/spec/workers/create_pipeline_worker_spec.rb +++ b/spec/workers/create_pipeline_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe CreatePipelineWorker do diff --git a/spec/workers/delete_diff_files_worker_spec.rb b/spec/workers/delete_diff_files_worker_spec.rb index e0edd313922..9f8b20df48e 100644 --- a/spec/workers/delete_diff_files_worker_spec.rb +++ b/spec/workers/delete_diff_files_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe DeleteDiffFilesWorker do diff --git a/spec/workers/delete_merged_branches_worker_spec.rb b/spec/workers/delete_merged_branches_worker_spec.rb index 39009d9e4b2..a218ca921d9 100644 --- a/spec/workers/delete_merged_branches_worker_spec.rb +++ b/spec/workers/delete_merged_branches_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe DeleteMergedBranchesWorker do diff --git a/spec/workers/delete_user_worker_spec.rb b/spec/workers/delete_user_worker_spec.rb index 06d9e125105..c963b886e62 100644 --- a/spec/workers/delete_user_worker_spec.rb +++ b/spec/workers/delete_user_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe DeleteUserWorker do diff --git a/spec/workers/deployments/success_worker_spec.rb b/spec/workers/deployments/success_worker_spec.rb index ba7d45eca01..1c68922b03d 100644 --- a/spec/workers/deployments/success_worker_spec.rb +++ b/spec/workers/deployments/success_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Deployments::SuccessWorker do diff --git a/spec/workers/detect_repository_languages_worker_spec.rb b/spec/workers/detect_repository_languages_worker_spec.rb index ff3878fbc8e..dbf32555985 100644 --- a/spec/workers/detect_repository_languages_worker_spec.rb +++ b/spec/workers/detect_repository_languages_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe DetectRepositoryLanguagesWorker do diff --git a/spec/workers/email_receiver_worker_spec.rb b/spec/workers/email_receiver_worker_spec.rb index 045135255d6..f8a31fcdee6 100644 --- a/spec/workers/email_receiver_worker_spec.rb +++ b/spec/workers/email_receiver_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe EmailReceiverWorker, :mailer do diff --git a/spec/workers/emails_on_push_worker_spec.rb b/spec/workers/emails_on_push_worker_spec.rb index 05b4fb49ea3..0f87df89c29 100644 --- a/spec/workers/emails_on_push_worker_spec.rb +++ b/spec/workers/emails_on_push_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe EmailsOnPushWorker, :mailer do diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb index ebe02373275..8fddd8540ef 100644 --- a/spec/workers/every_sidekiq_worker_spec.rb +++ b/spec/workers/every_sidekiq_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'Every Sidekiq worker' do diff --git a/spec/workers/expire_build_artifacts_worker_spec.rb b/spec/workers/expire_build_artifacts_worker_spec.rb index 27995cf1611..74d6b5605d1 100644 --- a/spec/workers/expire_build_artifacts_worker_spec.rb +++ b/spec/workers/expire_build_artifacts_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ExpireBuildArtifactsWorker do diff --git a/spec/workers/expire_build_instance_artifacts_worker_spec.rb b/spec/workers/expire_build_instance_artifacts_worker_spec.rb index e1a56c72162..bdb5a3801d9 100644 --- a/spec/workers/expire_build_instance_artifacts_worker_spec.rb +++ b/spec/workers/expire_build_instance_artifacts_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ExpireBuildInstanceArtifactsWorker do diff --git a/spec/workers/expire_job_cache_worker_spec.rb b/spec/workers/expire_job_cache_worker_spec.rb index 1b614342a18..6ac285ca944 100644 --- a/spec/workers/expire_job_cache_worker_spec.rb +++ b/spec/workers/expire_job_cache_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ExpireJobCacheWorker do diff --git a/spec/workers/expire_pipeline_cache_worker_spec.rb b/spec/workers/expire_pipeline_cache_worker_spec.rb index 54c9a69d329..c98b69ef76c 100644 --- a/spec/workers/expire_pipeline_cache_worker_spec.rb +++ b/spec/workers/expire_pipeline_cache_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ExpirePipelineCacheWorker do diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb index 4895a968d6e..2459638c3e6 100644 --- a/spec/workers/git_garbage_collect_worker_spec.rb +++ b/spec/workers/git_garbage_collect_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'fileutils' require 'spec_helper' diff --git a/spec/workers/gitlab/github_import/advance_stage_worker_spec.rb b/spec/workers/gitlab/github_import/advance_stage_worker_spec.rb index fc7aafbc0c9..b1647d8c7df 100644 --- a/spec/workers/gitlab/github_import/advance_stage_worker_spec.rb +++ b/spec/workers/gitlab/github_import/advance_stage_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::AdvanceStageWorker, :clean_gitlab_redis_shared_state do diff --git a/spec/workers/gitlab/github_import/import_diff_note_worker_spec.rb b/spec/workers/gitlab/github_import/import_diff_note_worker_spec.rb index 5b1c6b6010a..42d69ff6166 100644 --- a/spec/workers/gitlab/github_import/import_diff_note_worker_spec.rb +++ b/spec/workers/gitlab/github_import/import_diff_note_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::ImportDiffNoteWorker do diff --git a/spec/workers/gitlab/github_import/import_issue_worker_spec.rb b/spec/workers/gitlab/github_import/import_issue_worker_spec.rb index ab070d6d081..06a573e16b7 100644 --- a/spec/workers/gitlab/github_import/import_issue_worker_spec.rb +++ b/spec/workers/gitlab/github_import/import_issue_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::ImportIssueWorker do diff --git a/spec/workers/gitlab/github_import/import_note_worker_spec.rb b/spec/workers/gitlab/github_import/import_note_worker_spec.rb index 3a30f06bb2d..5110c3ff11b 100644 --- a/spec/workers/gitlab/github_import/import_note_worker_spec.rb +++ b/spec/workers/gitlab/github_import/import_note_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::ImportNoteWorker do diff --git a/spec/workers/gitlab/github_import/import_pull_request_worker_spec.rb b/spec/workers/gitlab/github_import/import_pull_request_worker_spec.rb index 3cccd7cab21..d46e381fc51 100644 --- a/spec/workers/gitlab/github_import/import_pull_request_worker_spec.rb +++ b/spec/workers/gitlab/github_import/import_pull_request_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::ImportPullRequestWorker do diff --git a/spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb b/spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb index 7ff133f1049..fa4ded8e42f 100644 --- a/spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb +++ b/spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::RefreshImportJidWorker do diff --git a/spec/workers/gitlab/github_import/stage/finish_import_worker_spec.rb b/spec/workers/gitlab/github_import/stage/finish_import_worker_spec.rb index 91e0cddb5d8..35a856802c2 100644 --- a/spec/workers/gitlab/github_import/stage/finish_import_worker_spec.rb +++ b/spec/workers/gitlab/github_import/stage/finish_import_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::Stage::FinishImportWorker do diff --git a/spec/workers/gitlab/github_import/stage/import_base_data_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_base_data_worker_spec.rb index ad6154cc4a4..0c7fc2a164e 100644 --- a/spec/workers/gitlab/github_import/stage/import_base_data_worker_spec.rb +++ b/spec/workers/gitlab/github_import/stage/import_base_data_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::Stage::ImportBaseDataWorker do diff --git a/spec/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker_spec.rb index ab347f5b75b..5d96f562c30 100644 --- a/spec/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker_spec.rb +++ b/spec/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::Stage::ImportIssuesAndDiffNotesWorker do diff --git a/spec/workers/gitlab/github_import/stage/import_lfs_objects_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_lfs_objects_worker_spec.rb index b19884d7991..e7c9dabb292 100644 --- a/spec/workers/gitlab/github_import/stage/import_lfs_objects_worker_spec.rb +++ b/spec/workers/gitlab/github_import/stage/import_lfs_objects_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::Stage::ImportLfsObjectsWorker do diff --git a/spec/workers/gitlab/github_import/stage/import_notes_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_notes_worker_spec.rb index 94cff9e4e80..90590a45900 100644 --- a/spec/workers/gitlab/github_import/stage/import_notes_worker_spec.rb +++ b/spec/workers/gitlab/github_import/stage/import_notes_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::Stage::ImportNotesWorker do diff --git a/spec/workers/gitlab/github_import/stage/import_pull_requests_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_pull_requests_worker_spec.rb index 1fbb073a34a..15d485f1018 100644 --- a/spec/workers/gitlab/github_import/stage/import_pull_requests_worker_spec.rb +++ b/spec/workers/gitlab/github_import/stage/import_pull_requests_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::Stage::ImportPullRequestsWorker do diff --git a/spec/workers/gitlab/github_import/stage/import_repository_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_repository_worker_spec.rb index adab535ac05..6d47d73b92e 100644 --- a/spec/workers/gitlab/github_import/stage/import_repository_worker_spec.rb +++ b/spec/workers/gitlab/github_import/stage/import_repository_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::GithubImport::Stage::ImportRepositoryWorker do diff --git a/spec/workers/gitlab_shell_worker_spec.rb b/spec/workers/gitlab_shell_worker_spec.rb index 6b222af454d..0758cfc4ee2 100644 --- a/spec/workers/gitlab_shell_worker_spec.rb +++ b/spec/workers/gitlab_shell_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe GitlabShellWorker do diff --git a/spec/workers/gitlab_usage_ping_worker_spec.rb b/spec/workers/gitlab_usage_ping_worker_spec.rb index 49b4e04dc7c..aff5d112cdd 100644 --- a/spec/workers/gitlab_usage_ping_worker_spec.rb +++ b/spec/workers/gitlab_usage_ping_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe GitlabUsagePingWorker do diff --git a/spec/workers/group_destroy_worker_spec.rb b/spec/workers/group_destroy_worker_spec.rb index a170c84ab12..90a4150a31a 100644 --- a/spec/workers/group_destroy_worker_spec.rb +++ b/spec/workers/group_destroy_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe GroupDestroyWorker do diff --git a/spec/workers/hashed_storage/migrator_worker_spec.rb b/spec/workers/hashed_storage/migrator_worker_spec.rb index a85f820a3eb..a318cdd003e 100644 --- a/spec/workers/hashed_storage/migrator_worker_spec.rb +++ b/spec/workers/hashed_storage/migrator_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe HashedStorage::MigratorWorker do diff --git a/spec/workers/hashed_storage/project_migrate_worker_spec.rb b/spec/workers/hashed_storage/project_migrate_worker_spec.rb index 340e722aa7e..f266c7dbe8c 100644 --- a/spec/workers/hashed_storage/project_migrate_worker_spec.rb +++ b/spec/workers/hashed_storage/project_migrate_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe HashedStorage::ProjectMigrateWorker, :clean_gitlab_redis_shared_state do diff --git a/spec/workers/invalid_gpg_signature_update_worker_spec.rb b/spec/workers/invalid_gpg_signature_update_worker_spec.rb index 5972696515b..4f727469ea8 100644 --- a/spec/workers/invalid_gpg_signature_update_worker_spec.rb +++ b/spec/workers/invalid_gpg_signature_update_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe InvalidGpgSignatureUpdateWorker do diff --git a/spec/workers/issue_due_scheduler_worker_spec.rb b/spec/workers/issue_due_scheduler_worker_spec.rb index 2710267d384..61ad8330840 100644 --- a/spec/workers/issue_due_scheduler_worker_spec.rb +++ b/spec/workers/issue_due_scheduler_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe IssueDueSchedulerWorker do diff --git a/spec/workers/mail_scheduler/issue_due_worker_spec.rb b/spec/workers/mail_scheduler/issue_due_worker_spec.rb index 1026ae5b4bf..fa17775e9f2 100644 --- a/spec/workers/mail_scheduler/issue_due_worker_spec.rb +++ b/spec/workers/mail_scheduler/issue_due_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe MailScheduler::IssueDueWorker do diff --git a/spec/workers/mail_scheduler/notification_service_worker_spec.rb b/spec/workers/mail_scheduler/notification_service_worker_spec.rb index 5cfba01850c..0729c5f9ffb 100644 --- a/spec/workers/mail_scheduler/notification_service_worker_spec.rb +++ b/spec/workers/mail_scheduler/notification_service_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe MailScheduler::NotificationServiceWorker do diff --git a/spec/workers/merge_worker_spec.rb b/spec/workers/merge_worker_spec.rb index b57c275c770..138a99abde6 100644 --- a/spec/workers/merge_worker_spec.rb +++ b/spec/workers/merge_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe MergeWorker do diff --git a/spec/workers/namespaceless_project_destroy_worker_spec.rb b/spec/workers/namespaceless_project_destroy_worker_spec.rb index 2f21a1321e1..4fbda37e268 100644 --- a/spec/workers/namespaceless_project_destroy_worker_spec.rb +++ b/spec/workers/namespaceless_project_destroy_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe NamespacelessProjectDestroyWorker do diff --git a/spec/workers/new_issue_worker_spec.rb b/spec/workers/new_issue_worker_spec.rb index baa8ddb59e5..88a75ce5b70 100644 --- a/spec/workers/new_issue_worker_spec.rb +++ b/spec/workers/new_issue_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe NewIssueWorker do diff --git a/spec/workers/new_merge_request_worker_spec.rb b/spec/workers/new_merge_request_worker_spec.rb index c3f29a40d58..d078ddd07d9 100644 --- a/spec/workers/new_merge_request_worker_spec.rb +++ b/spec/workers/new_merge_request_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe NewMergeRequestWorker do diff --git a/spec/workers/new_note_worker_spec.rb b/spec/workers/new_note_worker_spec.rb index 575361c93d4..2966a201a62 100644 --- a/spec/workers/new_note_worker_spec.rb +++ b/spec/workers/new_note_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe NewNoteWorker do diff --git a/spec/workers/pages_domain_verification_cron_worker_spec.rb b/spec/workers/pages_domain_verification_cron_worker_spec.rb index 8f780428c82..9b479da1cb6 100644 --- a/spec/workers/pages_domain_verification_cron_worker_spec.rb +++ b/spec/workers/pages_domain_verification_cron_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PagesDomainVerificationCronWorker do diff --git a/spec/workers/pages_domain_verification_worker_spec.rb b/spec/workers/pages_domain_verification_worker_spec.rb index 372fc95ab4a..2f23dcb487f 100644 --- a/spec/workers/pages_domain_verification_worker_spec.rb +++ b/spec/workers/pages_domain_verification_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PagesDomainVerificationWorker do diff --git a/spec/workers/pipeline_hooks_worker_spec.rb b/spec/workers/pipeline_hooks_worker_spec.rb index 035e329839f..60df08f40da 100644 --- a/spec/workers/pipeline_hooks_worker_spec.rb +++ b/spec/workers/pipeline_hooks_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PipelineHooksWorker do diff --git a/spec/workers/pipeline_metrics_worker_spec.rb b/spec/workers/pipeline_metrics_worker_spec.rb index 896f9e6e7f2..6beecbcd114 100644 --- a/spec/workers/pipeline_metrics_worker_spec.rb +++ b/spec/workers/pipeline_metrics_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PipelineMetricsWorker do diff --git a/spec/workers/pipeline_notification_worker_spec.rb b/spec/workers/pipeline_notification_worker_spec.rb index eb539ffd893..98b0f139fe2 100644 --- a/spec/workers/pipeline_notification_worker_spec.rb +++ b/spec/workers/pipeline_notification_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PipelineNotificationWorker, :mailer do diff --git a/spec/workers/pipeline_process_worker_spec.rb b/spec/workers/pipeline_process_worker_spec.rb index 86e9d7f6684..d33cf72e51e 100644 --- a/spec/workers/pipeline_process_worker_spec.rb +++ b/spec/workers/pipeline_process_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PipelineProcessWorker do diff --git a/spec/workers/pipeline_schedule_worker_spec.rb b/spec/workers/pipeline_schedule_worker_spec.rb index ff408427926..f23910d23be 100644 --- a/spec/workers/pipeline_schedule_worker_spec.rb +++ b/spec/workers/pipeline_schedule_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PipelineScheduleWorker do diff --git a/spec/workers/pipeline_success_worker_spec.rb b/spec/workers/pipeline_success_worker_spec.rb index d1c84adda6f..4cbe384b47a 100644 --- a/spec/workers/pipeline_success_worker_spec.rb +++ b/spec/workers/pipeline_success_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PipelineSuccessWorker do diff --git a/spec/workers/pipeline_update_worker_spec.rb b/spec/workers/pipeline_update_worker_spec.rb index 0b456cfd0da..0225e4a9601 100644 --- a/spec/workers/pipeline_update_worker_spec.rb +++ b/spec/workers/pipeline_update_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PipelineUpdateWorker do diff --git a/spec/workers/plugin_worker_spec.rb b/spec/workers/plugin_worker_spec.rb index 9238a8199bc..ca6c9986131 100644 --- a/spec/workers/plugin_worker_spec.rb +++ b/spec/workers/plugin_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PluginWorker do diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index 9cddad71a51..66958a4c116 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PostReceive do diff --git a/spec/workers/process_commit_worker_spec.rb b/spec/workers/process_commit_worker_spec.rb index 2d071c181c2..47bac63511e 100644 --- a/spec/workers/process_commit_worker_spec.rb +++ b/spec/workers/process_commit_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProcessCommitWorker do diff --git a/spec/workers/project_cache_worker_spec.rb b/spec/workers/project_cache_worker_spec.rb index b9b5445562f..a7353227043 100644 --- a/spec/workers/project_cache_worker_spec.rb +++ b/spec/workers/project_cache_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProjectCacheWorker do diff --git a/spec/workers/project_destroy_worker_spec.rb b/spec/workers/project_destroy_worker_spec.rb index 6132f145f8d..ec40900a5b7 100644 --- a/spec/workers/project_destroy_worker_spec.rb +++ b/spec/workers/project_destroy_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProjectDestroyWorker do diff --git a/spec/workers/project_export_worker_spec.rb b/spec/workers/project_export_worker_spec.rb index 8899969c178..8065087796c 100644 --- a/spec/workers/project_export_worker_spec.rb +++ b/spec/workers/project_export_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ProjectExportWorker do diff --git a/spec/workers/propagate_service_template_worker_spec.rb b/spec/workers/propagate_service_template_worker_spec.rb index af1fb80a51d..fb4ced77832 100644 --- a/spec/workers/propagate_service_template_worker_spec.rb +++ b/spec/workers/propagate_service_template_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PropagateServiceTemplateWorker do diff --git a/spec/workers/prune_old_events_worker_spec.rb b/spec/workers/prune_old_events_worker_spec.rb index ea2b6ae229e..f1eef1923bf 100644 --- a/spec/workers/prune_old_events_worker_spec.rb +++ b/spec/workers/prune_old_events_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PruneOldEventsWorker do diff --git a/spec/workers/prune_web_hook_logs_worker_spec.rb b/spec/workers/prune_web_hook_logs_worker_spec.rb index b3ec71d4a00..e57334967fd 100644 --- a/spec/workers/prune_web_hook_logs_worker_spec.rb +++ b/spec/workers/prune_web_hook_logs_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe PruneWebHookLogsWorker do diff --git a/spec/workers/reactive_caching_worker_spec.rb b/spec/workers/reactive_caching_worker_spec.rb index 3da851de067..2395e6ec947 100644 --- a/spec/workers/reactive_caching_worker_spec.rb +++ b/spec/workers/reactive_caching_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe ReactiveCachingWorker do diff --git a/spec/workers/rebase_worker_spec.rb b/spec/workers/rebase_worker_spec.rb index 900332ed6b3..578b8cf7451 100644 --- a/spec/workers/rebase_worker_spec.rb +++ b/spec/workers/rebase_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RebaseWorker, '#perform' do diff --git a/spec/workers/remote_mirror_notification_worker_spec.rb b/spec/workers/remote_mirror_notification_worker_spec.rb index e3db10ed645..5182f67b4af 100644 --- a/spec/workers/remote_mirror_notification_worker_spec.rb +++ b/spec/workers/remote_mirror_notification_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RemoteMirrorNotificationWorker, :mailer do diff --git a/spec/workers/remove_expired_group_links_worker_spec.rb b/spec/workers/remove_expired_group_links_worker_spec.rb index 689bc3d27b4..10d9aa37dee 100644 --- a/spec/workers/remove_expired_group_links_worker_spec.rb +++ b/spec/workers/remove_expired_group_links_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RemoveExpiredGroupLinksWorker do diff --git a/spec/workers/remove_expired_members_worker_spec.rb b/spec/workers/remove_expired_members_worker_spec.rb index 058fdf4c009..69a5725bb35 100644 --- a/spec/workers/remove_expired_members_worker_spec.rb +++ b/spec/workers/remove_expired_members_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RemoveExpiredMembersWorker do diff --git a/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb b/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb index 57f83c1dbe9..0e21933a9a5 100644 --- a/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb +++ b/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RemoveUnreferencedLfsObjectsWorker do diff --git a/spec/workers/repository_check/batch_worker_spec.rb b/spec/workers/repository_check/batch_worker_spec.rb index 50b93fce2dc..051c6a5d141 100644 --- a/spec/workers/repository_check/batch_worker_spec.rb +++ b/spec/workers/repository_check/batch_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RepositoryCheck::BatchWorker do diff --git a/spec/workers/repository_check/clear_worker_spec.rb b/spec/workers/repository_check/clear_worker_spec.rb index 1c49415d46c..7ad9e287204 100644 --- a/spec/workers/repository_check/clear_worker_spec.rb +++ b/spec/workers/repository_check/clear_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RepositoryCheck::ClearWorker do diff --git a/spec/workers/repository_check/dispatch_worker_spec.rb b/spec/workers/repository_check/dispatch_worker_spec.rb index 7877429aa8f..03efb6a0a80 100644 --- a/spec/workers/repository_check/dispatch_worker_spec.rb +++ b/spec/workers/repository_check/dispatch_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RepositoryCheck::DispatchWorker do diff --git a/spec/workers/repository_check/single_repository_worker_spec.rb b/spec/workers/repository_check/single_repository_worker_spec.rb index f11875cffd1..65e1c5e9d5d 100644 --- a/spec/workers/repository_check/single_repository_worker_spec.rb +++ b/spec/workers/repository_check/single_repository_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' require 'fileutils' diff --git a/spec/workers/repository_cleanup_worker_spec.rb b/spec/workers/repository_cleanup_worker_spec.rb index 3adae0b6cfa..e58664cf22a 100644 --- a/spec/workers/repository_cleanup_worker_spec.rb +++ b/spec/workers/repository_cleanup_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RepositoryCleanupWorker do diff --git a/spec/workers/repository_fork_worker_spec.rb b/spec/workers/repository_fork_worker_spec.rb index 31bfe88d0bd..26fd67adfaa 100644 --- a/spec/workers/repository_fork_worker_spec.rb +++ b/spec/workers/repository_fork_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RepositoryForkWorker do diff --git a/spec/workers/repository_import_worker_spec.rb b/spec/workers/repository_import_worker_spec.rb index 87ac4bc05c1..b8767af8eee 100644 --- a/spec/workers/repository_import_worker_spec.rb +++ b/spec/workers/repository_import_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RepositoryImportWorker do diff --git a/spec/workers/repository_remove_remote_worker_spec.rb b/spec/workers/repository_remove_remote_worker_spec.rb index 6ddb653d142..6eba5c50960 100644 --- a/spec/workers/repository_remove_remote_worker_spec.rb +++ b/spec/workers/repository_remove_remote_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe RepositoryRemoveRemoteWorker do diff --git a/spec/workers/repository_update_remote_mirror_worker_spec.rb b/spec/workers/repository_update_remote_mirror_worker_spec.rb index b582a3650b6..4de51ecb3e9 100644 --- a/spec/workers/repository_update_remote_mirror_worker_spec.rb +++ b/spec/workers/repository_update_remote_mirror_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe RepositoryUpdateRemoteMirrorWorker do diff --git a/spec/workers/run_pipeline_schedule_worker_spec.rb b/spec/workers/run_pipeline_schedule_worker_spec.rb index 481a84837f9..690af22f4dc 100644 --- a/spec/workers/run_pipeline_schedule_worker_spec.rb +++ b/spec/workers/run_pipeline_schedule_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe RunPipelineScheduleWorker do diff --git a/spec/workers/stage_update_worker_spec.rb b/spec/workers/stage_update_worker_spec.rb index 7bc76c79464..429d42bac29 100644 --- a/spec/workers/stage_update_worker_spec.rb +++ b/spec/workers/stage_update_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe StageUpdateWorker do diff --git a/spec/workers/stuck_ci_jobs_worker_spec.rb b/spec/workers/stuck_ci_jobs_worker_spec.rb index e09b8e5b964..72de62f1188 100644 --- a/spec/workers/stuck_ci_jobs_worker_spec.rb +++ b/spec/workers/stuck_ci_jobs_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe StuckCiJobsWorker do diff --git a/spec/workers/stuck_import_jobs_worker_spec.rb b/spec/workers/stuck_import_jobs_worker_spec.rb index e94d2be9850..dcb8e59ed28 100644 --- a/spec/workers/stuck_import_jobs_worker_spec.rb +++ b/spec/workers/stuck_import_jobs_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe StuckImportJobsWorker do diff --git a/spec/workers/stuck_merge_jobs_worker_spec.rb b/spec/workers/stuck_merge_jobs_worker_spec.rb index 5aaff27a6b2..09efed6d2cf 100644 --- a/spec/workers/stuck_merge_jobs_worker_spec.rb +++ b/spec/workers/stuck_merge_jobs_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe StuckMergeJobsWorker do diff --git a/spec/workers/system_hook_push_worker_spec.rb b/spec/workers/system_hook_push_worker_spec.rb index b1d446ed25f..890a622d11a 100644 --- a/spec/workers/system_hook_push_worker_spec.rb +++ b/spec/workers/system_hook_push_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe SystemHookPushWorker do diff --git a/spec/workers/todos_destroyer/confidential_issue_worker_spec.rb b/spec/workers/todos_destroyer/confidential_issue_worker_spec.rb index 9d7c0b8f560..18876b71615 100644 --- a/spec/workers/todos_destroyer/confidential_issue_worker_spec.rb +++ b/spec/workers/todos_destroyer/confidential_issue_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe TodosDestroyer::ConfidentialIssueWorker do diff --git a/spec/workers/todos_destroyer/entity_leave_worker_spec.rb b/spec/workers/todos_destroyer/entity_leave_worker_spec.rb index 955447906aa..cb14fac0910 100644 --- a/spec/workers/todos_destroyer/entity_leave_worker_spec.rb +++ b/spec/workers/todos_destroyer/entity_leave_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe TodosDestroyer::EntityLeaveWorker do diff --git a/spec/workers/todos_destroyer/group_private_worker_spec.rb b/spec/workers/todos_destroyer/group_private_worker_spec.rb index fcc38989ced..d9a240136d5 100644 --- a/spec/workers/todos_destroyer/group_private_worker_spec.rb +++ b/spec/workers/todos_destroyer/group_private_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe TodosDestroyer::GroupPrivateWorker do diff --git a/spec/workers/todos_destroyer/private_features_worker_spec.rb b/spec/workers/todos_destroyer/private_features_worker_spec.rb index 9599f5ee071..abd04acc3bd 100644 --- a/spec/workers/todos_destroyer/private_features_worker_spec.rb +++ b/spec/workers/todos_destroyer/private_features_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe TodosDestroyer::PrivateFeaturesWorker do diff --git a/spec/workers/todos_destroyer/project_private_worker_spec.rb b/spec/workers/todos_destroyer/project_private_worker_spec.rb index 15d926fa9d5..c1bb0438ec3 100644 --- a/spec/workers/todos_destroyer/project_private_worker_spec.rb +++ b/spec/workers/todos_destroyer/project_private_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe TodosDestroyer::ProjectPrivateWorker do diff --git a/spec/workers/trending_projects_worker_spec.rb b/spec/workers/trending_projects_worker_spec.rb index c3c6fdcf2d5..6e524085662 100644 --- a/spec/workers/trending_projects_worker_spec.rb +++ b/spec/workers/trending_projects_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe TrendingProjectsWorker do diff --git a/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb b/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb index d20d926f5a0..c4af829a5e2 100644 --- a/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb +++ b/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe UpdateHeadPipelineForMergeRequestWorker do diff --git a/spec/workers/update_merge_requests_worker_spec.rb b/spec/workers/update_merge_requests_worker_spec.rb index 0b553db0ca4..486dade454a 100644 --- a/spec/workers/update_merge_requests_worker_spec.rb +++ b/spec/workers/update_merge_requests_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe UpdateMergeRequestsWorker do diff --git a/spec/workers/upload_checksum_worker_spec.rb b/spec/workers/upload_checksum_worker_spec.rb index 9e50ce15871..7202c8001b4 100644 --- a/spec/workers/upload_checksum_worker_spec.rb +++ b/spec/workers/upload_checksum_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' describe UploadChecksumWorker do diff --git a/spec/workers/wait_for_cluster_creation_worker_spec.rb b/spec/workers/wait_for_cluster_creation_worker_spec.rb index 0e92b298178..850eba263a7 100644 --- a/spec/workers/wait_for_cluster_creation_worker_spec.rb +++ b/spec/workers/wait_for_cluster_creation_worker_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe WaitForClusterCreationWorker do |